Designs by Duhart
The Billboard, BoxOffice and Dating demos are the actual Next.js application, served from a container on my own Kubernetes node and talking to the same Cloudflare Workers, R2 bucket and Stream account it uses in production. This page is how that is wired.
The alternative was to copy the player source into this site, 67 files and about 530 KB, and stub out the network calls. That works, and it starts lying the first time a component upstream changes. Running the real application leaves no copy to drift.
designsbyduhart.org (Cloudflare Workers)
│
└── iframe ──► demo.designsbyduhart.org
│ Cloudflare edge · TLS
▼
cloudflared tunnel ──► 127.0.0.1:30900
│
▼
Service/NodePort · namespace portfolio-demo
│
▼
Pod: Next.js standalone server
│
┌───────────┼───────────────┐
▼ ▼ ▼
billboard-api boxoffice-api dating: bundled
+ R2 (audio) + Stream (HLS) fictional profilesThe Billboard, BoxOffice and Dating demos are not recordings and not copies. They are served by a pod, and the pod is the part worth reading about. A single-node k3s cluster that already runs a twenty-one pod workload, with no ingress controller, no registry, and no memory to spare. Every decision below was forced by one of those three facts.
# deploy/demo/k8s/deployment.yaml (excerpt)
spec:
containers:
- name: web
image: web-platform-demo:latest
imagePullPolicy: Never # side-loaded into containerd; no registry
env:
- name: DEMO_MODE # also baked into the image, deliberately
value: "1"
resources: # sized against a node already 22% requested
requests: { cpu: 100m, memory: 256Mi }
limits: { cpu: "1", memory: 768Mi }
readinessProbe:
httpGet: { path: /billboard, port: http }
securityContext:
runAsUser: 1000 # numeric: the kubelet cannot resolve "node"
runAsNonRoot: true
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities: { drop: ["ALL"] }Captured from the cluster serving the demos. The pod name changes on every rollout; everything else is stable.
$ kubectl -n portfolio-demo get deploy,svc,pod NAME READY IMAGES deployment.apps/web-platform-demo 1/1 web-platform-demo:latest NAME TYPE CLUSTER-IP PORT(S) service/web-platform-demo NodePort 10.43.41.5 80:30900/TCP NAME READY STATUS IP NODE pod/web-platform-demo-66c94fd8c-k7bbx 1/1 Running 10.42.0.75 theone
Two upstream defects surfaced while proving the players actually work, and both are written up rather than quietly patched around: a streaming route that returns 500 to any HTTP Range request, which browsers send for all media, so seeking was broken in production, and a client that manufactured its own 401 before issuing a request the server would have answered.
Real: the components, the audio engine, the HLS pipeline, the API calls and the media. Changed for the demo: the route allow-list above, and one flag that lets an anonymous visitor’s playback request reach the server instead of being refused in the browser. No session is faked and no token is minted, so a genuine refusal from the API still refuses.
The Dating deck is the exception, and says so. It has no anonymous read path worth exposing, so in the demo build its data layer answers from invented profiles with drawn portraits. The UI is the product’s; the people are not real.
The write paths are the honest gap. Liking a track, saving a resume position and adding to a playlist all need an account, so they fail quietly here exactly as they were built to. Playback, seeking, queueing and adaptive bitrate do not.
The Billboard playerBoxOffice and the moderator consoleAll demos