Files
zeekayandHanzo AI 0412e26125
CI/CD / render (push) Waiting to run
Serve the Zoo sites from files, not from pods
zoo.vote and zoo.industries are static bundles a pod was re-serving on every
request. Both move to the site plane: the `public/` tree of the image digest
each Deployment ran is synced to s3://hanzo-sites/zoo/vote and
s3://hanzo-sites/zoo/industries, and each file now declares the Middleware that
reads the prefix together with the route that names it. zoo-industries' server
generated /public/config.json at boot from three SPA_* variables; the plane has
no boot, so that file travels in the prefix carrying the values the pod served.

zoo-ngo is deleted rather than converted. zoo.ngo and www.zoo.ngo already route
to s3://hanzo-sites/zoo/ngo, and that prefix holds a newer build than the pod
was serving to nobody -- no route in this namespace named it. A site declared
twice is a site that goes stale in one of them.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 15:02:38 -07:00

52 lines
1.9 KiB
YAML

# zoo.vote is files: one Middleware that serves them, one route that names it,
# and the endpoint-less Service the route schema requires. No image, so the
# chart renders no Deployment -- a static site is not a pod.
#
# The bundle is Zoo's own build. luxfi/vote is built once per tenant and the Zoo
# build carries VITE_VOTE_HOME=zoo, so the objects in this prefix are the
# `public/` tree of
# ghcr.io/zooai/vote@sha256:22c778f5b14a61116680bf4d1bcfb34d9499099af306df71ef8bae120a65e131,
# the digest the Deployment ran. That server read no SPA_* variable and so wrote
# nothing at boot -- the prefix is the whole site, with nothing a pod added.
#
# The tag it named, votesguard-zoo2, is mutable and no lane publishes here yet. A
# rebuild ships by syncing `public/` to this prefix, the way every other site on
# the plane does.
cd:
automated: true
ports:
- name: http
containerPort: 80
middlewares:
- name: vote
spec:
staticFiles:
root: s3://hanzo-sites/zoo/vote
# Vite emits ONE index.html for the whole app and the client router
# resolves every path, so a deep link has no file behind it and a miss must
# answer with the shell. Contrast zoo-industries, a file per route.
spaMode: true
spaIndex: index.html
indexFiles:
- index.html
routes:
- name: vote
spec:
entryPoints:
- websecure
routes:
- match: Host(`zoo.vote`) || Host(`www.zoo.vote`)
kind: Rule
# Above the Ingress this replaces, so the route is authoritative from the
# moment it exists rather than racing an object prune does not remove.
priority: 100
middlewares:
- name: vote
services:
- name: zoo-vote
port: 80
# The same default certificate the Ingress served: its cert-manager
# Certificate never went Ready, so naming the empty secret would change the
# bytes on the wire for nothing.
tls: {}