diff --git a/AGENT.md b/AGENT.md index 962dce1..8739203 100644 --- a/AGENT.md +++ b/AGENT.md @@ -86,9 +86,11 @@ Password min length is enforced server-side by `GOTRUE_PASSWORD_MIN_LENGTH=10`. ## 7. Frontend conventions -- **Only** the anon key leaves the server. `frontend/99-config.sh` (bind-mounted into the nginx entrypoint dir) writes `config.js` at container start from `$SUPABASE_URL` / `$SUPABASE_ANON_KEY`. The service_role key is not mounted into `web`. -- The `web` service uses `nginx:1.27-alpine` directly (no `build:`). Static files + nginx.conf + the entrypoint script are bind-mounted read-only. Updating the frontend is `git pull` + restart the container. -- `.gitattributes` enforces `eol=lf` on `*.sh` files so the entrypoint doesn't break with CRLF on Windows checkouts. +- **Only** the anon key leaves the server. `config.js` is generated at container start via an inline `entrypoint:` command in `docker-compose.yml` (writes `window.MCCARS_CONFIG={SUPABASE_URL,SUPABASE_ANON_KEY}`). The service_role key is never mounted into the `web` container. +- **No entrypoint script file.** An earlier design used `frontend/99-config.sh` bind-mounted into `/docker-entrypoint.d/`. Abandoned because Unraid's filesystem does not preserve Unix execute bits on bind mounts — the script was silently skipped. The inline `entrypoint:` in compose needs no file permissions. +- `frontend/config.js` is **git-ignored** (generated at runtime, would commit stale `localhost` values otherwise). +- `index.html` / `admin.html` load `config.js` with a `?v=` query string (generated by a small inline `document.write` snippet) to defeat both browser and proxy caching. +- The `web` service uses `nginx:1.27-alpine` directly (no `build:`). Static files and `nginx.conf` are bind-mounted. Updating the frontend is `git pull` + `docker compose up -d --force-recreate web`. - `frontend/app.js` (public) creates a Supabase client with `persistSession: false` — the public site never needs a session. - `frontend/admin.js` uses `persistSession: true, storageKey: "mccars.auth"` and a single realtime channel `mccars-admin` that subscribes to leads/customers/vehicles. - `app.js` writes `vehicle_id` (uuid) **and** denormalized `vehicle_label` ("BMW M3") into the lead at submit time, so the admin UI renders even if the vehicle is later deleted. @@ -105,7 +107,10 @@ Password min length is enforced server-side by `GOTRUE_PASSWORD_MIN_LENGTH=10`. | Admin login works but Leads tab is empty | RLS: session is `anon` instead of `authenticated`. Check that `signInWithPassword` succeeded and token is attached to subsequent requests. | | Booking form submits but no row appears | anon lacks `INSERT` grant on `public.leads`. Check `02-leads.sql` ran (see `post-init` logs). | | `.sh` files reject with `\r: command not found` | CRLF line endings. `dos2unix` or re-save as LF. | -| Port 8000 "connection refused" on Windows | Docker Desktop wslrelay. Use `55521` (production port). | +| Port 8000 "connection refused" on Windows | Docker Desktop wslrelay. Use `55521` (production port). | +| `config.js` not generated, website uses fallback URL | Unraid doesn't preserve execute bits — entrypoint script skipped. Fixed: `config.js` is now written by an inline `entrypoint:` command in docker-compose, no file needed. | +| Website loads but API calls fail ("Failed to fetch") | `config.js` cached by NPM or browser with old `localhost` URL. The `?v=timestamp` cache-buster on the `