The contact form could not be made to work by configuration. Two reasons, both fixed here. The endpoint never reached the browser. k8s/configmap.yaml carried PUBLIC_CONTACT_FORM_ENDPOINT, but the Deployment has no env/envFrom pointing at that ConfigMap, so it was dead config. Wiring it up would not have helped either: this is a static Astro build, so import.meta.env.PUBLIC_* is inlined when the image is built and the pod only serves pre-built HTML. Anything the browser needs has to arrive as a build arg. Add ARG/ENV to the Dockerfile and pass --build-arg from CI, sourced from a CONTACT_FORM_ENDPOINT Actions secret. Rewrite the ConfigMap as documentation of what the build expects, with an explicit warning not to add envFrom. Submission behaviour was also wrong for visitors. A native POST would have navigated them to the form provider's page; post in the background with fetch() and send them to our own /thank-you/ instead. On failure the form now stays put, re-enables the button and offers the phone and email fallback, rather than silently losing the inquiry. Add a honeypot (_gotcha, which Formspree treats as spam) positioned off-screen rather than display:none, so bots that skip hidden fields still fill it. Read data-endpoint at submit time rather than caching it at init, keeping the attribute the single source of truth. Tests: replace the old contact assertion, which faked a native GET navigation, with one that mocks the endpoint and exercises the real fetch path including the posted payload. Add a case for endpoint failure. typecheck 0/0/0, build 0/0, seo:lint clean on 20 pages, e2e 44 passed. The 4 remaining failures are the pre-existing stale nav assertions in docs/launch-checklist.md section 2.1, untouched here.
27 lines
1017 B
Docker
27 lines
1017 B
Docker
# syntax=docker/dockerfile:1
|
|
FROM node:22-alpine AS deps
|
|
WORKDIR /app
|
|
COPY package.json package-lock.json* ./
|
|
RUN npm ci
|
|
|
|
FROM node:22-alpine AS build
|
|
WORKDIR /app
|
|
# Astro is a STATIC build: import.meta.env.PUBLIC_* is inlined into the HTML here, at image build
|
|
# time. A runtime env var on the pod can never reach it (the pod only runs nginx over pre-built
|
|
# files), so anything the browser needs must arrive as a build arg. CI passes these; see
|
|
# .gitea/workflows/ci.yml.
|
|
ARG PUBLIC_CONTACT_FORM_ENDPOINT=""
|
|
ARG PUBLIC_SITE_URL="https://www.bluecapstrategies.com"
|
|
ENV PUBLIC_CONTACT_FORM_ENDPOINT=$PUBLIC_CONTACT_FORM_ENDPOINT \
|
|
PUBLIC_SITE_URL=$PUBLIC_SITE_URL
|
|
COPY --from=deps /app/node_modules ./node_modules
|
|
COPY . .
|
|
RUN npm run build
|
|
|
|
FROM nginx:1.27-alpine AS runtime
|
|
COPY deploy/nginx.conf /etc/nginx/conf.d/default.conf
|
|
COPY --from=build /app/dist /usr/share/nginx/html
|
|
EXPOSE 80
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD wget -qO- http://127.0.0.1/healthz || exit 1
|