hotbox port#72
Conversation
Greptile SummaryThis PR adds Docker/nginx infrastructure to serve the docs site on hotbox, and swaps the canonical
Confidence Score: 3/5The infra additions are solid, but the hardcoded domain change in astro.config.ts will silently poison canonical URLs and OG metadata for any non-hotbox build made from this branch. The Dockerfile and nginx config are well-written and low-risk. The SITE_URL hardcoded to docs.efp.rip in the shared astro.config.ts gets stamped into every HTML file at build time, meaning the existing CI pipeline would emit pages with the wrong canonical domain for the docs.efp.app deployment. astro.config.ts — the SITE_URL change needs to be gated behind an environment variable before this is safe to merge. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Dev as Developer / hotbox
participant Docker as Docker Build
participant Builder as Stage 1: node:22-slim + bun
participant Runner as Stage 2: nginx:alpine
participant Client as Browser
Dev->>Docker: docker build .
Docker->>Builder: COPY package.json bun.lockb
Builder->>Builder: bun install --frozen-lockfile
Docker->>Builder: COPY . .
Builder->>Builder: bun run build to dist/
Docker->>Runner: COPY nginx.conf
Docker->>Runner: COPY dist/
Runner-->>Dev: Image ready (EXPOSE 8080)
Client->>Runner: GET /some/page
Runner->>Runner: "try_files $uri $uri/index.html $uri/ =404"
Runner-->>Client: 200 index.html
Client->>Runner: GET /_astro/bundle.abc123.js
Runner-->>Client: "200 + Cache-Control: max-age=31536000, immutable"
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Dev as Developer / hotbox
participant Docker as Docker Build
participant Builder as Stage 1: node:22-slim + bun
participant Runner as Stage 2: nginx:alpine
participant Client as Browser
Dev->>Docker: docker build .
Docker->>Builder: COPY package.json bun.lockb
Builder->>Builder: bun install --frozen-lockfile
Docker->>Builder: COPY . .
Builder->>Builder: bun run build to dist/
Docker->>Runner: COPY nginx.conf
Docker->>Runner: COPY dist/
Runner-->>Dev: Image ready (EXPOSE 8080)
Client->>Runner: GET /some/page
Runner->>Runner: "try_files $uri $uri/index.html $uri/ =404"
Runner-->>Client: 200 index.html
Client->>Runner: GET /_astro/bundle.abc123.js
Runner-->>Client: "200 + Cache-Control: max-age=31536000, immutable"
Reviews (1): Last reviewed commit: "hotbox port" | Re-trigger Greptile |
| import starlightLinksValidator from 'starlight-links-validator' | ||
|
|
||
| const SITE_URL = 'https://docs.efp.app/' | ||
| const SITE_URL = 'https://docs.efp.rip/' |
There was a problem hiding this comment.
SITE_URL hardcoded to hotbox domain bakes wrong canonicals into every build
SITE_URL is now https://docs.efp.rip/ in the shared astro.config.ts. Because output: 'static', every build — including the CI job in checks.yml that presumably still deploys to docs.efp.app — will emit canonical <link> tags, sitemap entries, og:image, and twitter:image metadata pointing at docs.efp.rip. Any page served from docs.efp.app will tell search engines its canonical URL is on a different domain, which is a direct SEO regression for the existing deployment.
The standard fix is to read the URL from an environment variable with the current domain as the fallback: const SITE_URL = process.env.SITE_URL ?? 'https://docs.efp.app/', then set SITE_URL=https://docs.efp.rip/ in the hotbox service environment. That way each deployment gets its own canonical base without touching shared config.
| gzip on; | ||
| gzip_types text/css application/javascript application/json image/svg+xml text/plain; |
There was a problem hiding this comment.
Missing
gzip_vary on. Without it, a caching proxy that has stored the gzip-encoded response will serve it to clients that did not send Accept-Encoding: gzip, causing garbled output for those clients. gzip_vary adds Vary: Accept-Encoding to gzip'd responses so proxy caches can distinguish between compressed and uncompressed variants.
| gzip on; | |
| gzip_types text/css application/javascript application/json image/svg+xml text/plain; | |
| gzip on; | |
| gzip_vary on; | |
| gzip_types text/css application/javascript application/json image/svg+xml text/plain; |
| server { | ||
| listen 8080; | ||
| root /usr/share/nginx/html; | ||
| index index.html; |
There was a problem hiding this comment.
Without
server_tokens off, nginx advertises its exact version string in the Server response header and in default error pages (e.g. nginx/1.27.3), making it trivial to target known CVEs for that version. This is a quick hardening win with no functional cost.
| server { | |
| listen 8080; | |
| root /usr/share/nginx/html; | |
| index index.html; | |
| server { | |
| listen 8080; | |
| server_tokens off; | |
| root /usr/share/nginx/html; | |
| index index.html; |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
No description provided.