Skip to content

Commit 2da4d7e

Browse files
committed
feat: remove Nitro and add custom service worker
1 parent 0f563b0 commit 2da4d7e

16 files changed

Lines changed: 272 additions & 453 deletions

.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
dist
3+
.nitro
4+
.output
5+
.env
6+
.env.*

.env.example

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
NITRO_PUBLIC_TOLGEE_BACKEND_FETCH_PREFIX=https://j26-translations.jamboree.se/dbc78bc1f5f74fadae0a49abfe745c57
1+
J26_PUBLIC_TOLGEE_BACKEND_FETCH_PREFIX=https://j26-translations.jamboree.se/dbc78bc1f5f74fadae0a49abfe745c57
22
# The following three variables are used only in development environment
3-
NITRO_PUBLIC_TOLGEE_API_URL=https://j26-tolgee.nihlen.dev
4-
NITRO_PUBLIC_TOLGEE_API_KEY=<replace-with-your-personal-access-token>
5-
NITRO_PUBLIC_TOLGEE_PROJECT_ID=2
3+
J26_PUBLIC_TOLGEE_API_URL=https://j26-tolgee.nihlen.dev
4+
J26_PUBLIC_TOLGEE_API_KEY=<replace-with-your-personal-access-token>
5+
J26_PUBLIC_TOLGEE_PROJECT_ID=2
66

7-
NITRO_PUBLIC_APP_CONFIGS=/app-config.json,/another-config.json,/_services/booking/api/app-config.json
8-
NITRO_PUBLIC_BOTTOM_NAV_ITEMS=page_my_schedule,page_all_activities,page_map,page_more
9-
NITRO_PUBLIC_ADDITIONAL_ROOT_PATHS=/notifs
7+
J26_PUBLIC_APP_CONFIGS=/app-config.json,/another-config.json,/_services/booking/api/app-config.json
8+
J26_PUBLIC_BOTTOM_NAV_ITEMS=page_my_schedule,page_all_activities,page_map,page_more
9+
J26_PUBLIC_ADDITIONAL_ROOT_PATHS=/notifs
1010

11-
NITRO_PUBLIC_NOTIFICATIONS_TENANT=jamboree26
11+
J26_PUBLIC_NOTIFICATIONS_TENANT=jamboree26
1212

13-
# NITRO_PUBLIC_DEV_BANNER_MESSAGE="This message will be shown in a banner on top of the app."
14-
NITRO_PUBLIC_PAYLOAD_API_URL=http://localhost:1337/api
15-
NITRO_PUBLIC_PAYLOAD_LOCALES=sv,en
13+
# J26_PUBLIC_DEV_BANNER_MESSAGE="This message will be shown in a banner on top of the app."
14+
J26_PUBLIC_PAYLOAD_API_URL=http://localhost:1337/api
15+
J26_PUBLIC_PAYLOAD_LOCALES=sv,en

.gitignore

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ dist
1212
dist-ssr
1313
dev-dist
1414
*.local
15-
.output
1615

1716
# Editor directories and files
1817
.vscode/*
@@ -30,6 +29,3 @@ dev-dist
3029
.env
3130
.env.*
3231
!.env.example
33-
34-
public/workbox-*.js
35-
public/sw.js

CLAUDE.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
66

77
```bash
88
# Development
9-
bun dev # Start dev server (Vite + Nitro)
9+
pnpm run dev # Start dev server (Vite)
1010

1111
# Build
12-
bun run build # Full production build
12+
pnpm run build # Full production build
1313

1414
# Lint & Format (Biome)
15-
bun run lint # Check linting
16-
bun run format # Check formatting
17-
bun run biome check # Lint + format check
18-
bun run biome check --write # Auto-fix
15+
pnpm run lint # Check linting
16+
pnpm run format # Check formatting
17+
pnpm run biome check # Lint + format check
18+
pnpm run biome check --write # Auto-fix
1919

2020
# Type checking
21-
bun run typecheck # Run tsc --noEmit
21+
pnpm run typecheck # Run tsc --noEmit
2222
```
2323

2424
There are no tests in this project.
@@ -33,11 +33,11 @@ Sub-apps are served at `/_services/<appname>` in production. The shell navigates
3333

3434
### Dynamic Route Configuration
3535

36-
Navigation items are not hardcoded — they are loaded at runtime from URLs listed in the `NITRO_PUBLIC_APP_CONFIGS` env var. Each config URL returns a JSON object validated with ArkType schemas (`src/dynamic-routes/app-config.ts`). Configs are parsed and merged in `src/dynamic-routes/dynamic-routes.ts`, then provided via React context (`src/dynamic-routes/dynamic-routes-context.tsx`). Bottom nav items are filtered to the IDs listed in `NITRO_PUBLIC_BOTTOM_NAV_ITEMS`.
36+
Navigation items are not hardcoded — they are loaded at runtime from URLs listed in the `J26_PUBLIC_APP_CONFIGS` env var. Each config URL returns a JSON object validated with ArkType schemas (`src/dynamic-routes/app-config.ts`). Configs are parsed and merged in `src/dynamic-routes/dynamic-routes.ts`, then provided via React context (`src/dynamic-routes/dynamic-routes-context.tsx`). Bottom nav items are filtered to the IDs listed in `J26_PUBLIC_BOTTOM_NAV_ITEMS`.
3737

3838
### Runtime Config
3939

40-
The Nitro server exposes a `/api/config` endpoint (`server/routes/api/config.ts`) that reads `NITRO_PUBLIC_*` environment variables and returns them as JSON. The frontend loads this on startup (`src/config.tsx`) and makes the config available globally.
40+
The frontend fetches `/config.json` on startup (`src/config.tsx`) and makes the config available globally. In dev, the `runtimeConfigPlugin` in `vite.config.ts` serves this from `J26_PUBLIC_*` env vars. In production, `docker/entrypoint.sh` generates the file before nginx starts.
4141

4242
### Authentication
4343

@@ -64,17 +64,25 @@ Tolgee (`src/tolgee.tsx`) with backend fetch. Two namespaces: `app` (UI strings)
6464
| Icons | Tabler Icons (dynamically imported, `src/icons/icons.tsx`) |
6565
| Validation | ArkType |
6666
| HTTP | `openapi-fetch` |
67-
| Build | Vite + Rolldown + Nitro |
67+
| Build | Vite + Rolldown |
6868
| Lint/Format | Biome |
6969

7070
### Key Environment Variables
7171

72+
All runtime config vars use the `J26_PUBLIC_` prefix (e.g. `J26_PUBLIC_APP_CONFIGS`). The prefix is stripped and the remainder converted to camelCase when served as `/config.json`.
73+
7274
```
73-
NITRO_PUBLIC_APP_CONFIGS # Comma-separated URLs to app config JSONs
74-
NITRO_PUBLIC_BOTTOM_NAV_ITEMS # Comma-separated page IDs for bottom nav
75-
NITRO_PUBLIC_TOLGEE_BACKEND_FETCH_PREFIX # Translation CDN prefix
76-
NITRO_PUBLIC_NOTIFICATIONS_TENANT # Notifications service tenant
77-
NITRO_PUBLIC_DEV_BANNER_MESSAGE # Optional dev mode banner text
75+
J26_PUBLIC_APP_CONFIGS # Comma-separated URLs to app config JSONs
76+
J26_PUBLIC_BOTTOM_NAV_ITEMS # Comma-separated page IDs for bottom nav
77+
J26_PUBLIC_TOLGEE_BACKEND_FETCH_PREFIX # Translation CDN prefix
78+
J26_PUBLIC_NOTIFICATIONS_TENANT # Notifications service tenant
79+
J26_PUBLIC_DEV_BANNER_MESSAGE # Optional dev mode banner text
80+
J26_PUBLIC_TOLGEE_API_URL # Tolgee API URL (dev only)
81+
J26_PUBLIC_TOLGEE_API_KEY # Tolgee API key (dev only)
82+
J26_PUBLIC_TOLGEE_PROJECT_ID # Tolgee project ID (dev only)
83+
J26_PUBLIC_ADDITIONAL_ROOT_PATHS # Comma-separated extra root paths
84+
J26_PUBLIC_PAYLOAD_API_URL # Payload CMS API URL
85+
J26_PUBLIC_PAYLOAD_LOCALES # Comma-separated supported locales
7886
```
7987

80-
Dev proxies (defined in `vite.config.ts`) forward `/auth/**`, `/notifications/**`, and `/_services/signupinfo/**` to `https://app.dev.j26.se/`.
88+
In dev, these are read from `.env` by the `runtimeConfigPlugin` in `vite.config.ts` and served at `/config.json`. In production, `docker/entrypoint.sh` uses `jq` to write `/config.json` from the container environment before nginx starts.

Dockerfile

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@ FROM base AS builder
1414
WORKDIR /app
1515
COPY --from=deps /app/node_modules ./node_modules
1616
COPY . .
17-
RUN pnpm run build && pnpm prune --prod
17+
RUN pnpm run build
1818

19-
FROM node:24-alpine AS runner
20-
WORKDIR /app
21-
RUN addgroup --system --gid 1001 nodejs
22-
RUN adduser --system --uid 1001 nitro
23-
COPY --from=builder /app .
24-
USER nitro
25-
EXPOSE 3000
26-
ENV PORT 3000
27-
CMD ["npm", "run", "start"]
19+
FROM nginx:alpine AS runner
20+
RUN apk add --no-cache jq
21+
COPY --from=builder /app/dist /usr/share/nginx/html
22+
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
23+
COPY docker/entrypoint.sh /entrypoint.sh
24+
RUN chmod +x /entrypoint.sh
25+
EXPOSE 80
26+
ENTRYPOINT ["/entrypoint.sh"]

docker/entrypoint.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh
2+
set -e
3+
4+
jq -n 'env | to_entries
5+
| map(select(.key | startswith("J26_PUBLIC_")))
6+
| map({
7+
key: (.key[11:] | ascii_downcase | gsub("_(?<c>.)"; "\(.c | ascii_upcase)")),
8+
value: .value
9+
})
10+
| from_entries' > /usr/share/nginx/html/config.json
11+
12+
exec nginx -g "daemon off;"

docker/nginx.conf

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
server {
2+
listen 80;
3+
root /usr/share/nginx/html;
4+
index index.html;
5+
6+
location / {
7+
try_files $uri $uri/ /index.html;
8+
}
9+
10+
location = /config.json {
11+
add_header Cache-Control "no-store";
12+
}
13+
}

index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
<link rel="icon" type="image/svg+xml" href="/favicon.svg" media="(prefers-color-scheme: light)" />
1414
<link rel="shortcut icon" href="/favicon.ico" media="(prefers-color-scheme: light)" />
1515

16+
<!-- For Tabler Icons -->
17+
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net">
18+
<link rel="preconnect" crossorigin="anonymous" href="https://cdn.jsdelivr.net">
19+
1620
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
1721
<title>j26-app</title>
1822
<script src="/auth/static/refresh.js" defer></script>

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"scripts": {
77
"dev": "vite",
88
"build": "tsc -b && vite build",
9-
"start": "node .output/server/index.mjs",
109
"preview": "vite preview",
1110
"lint": "biome check",
1211
"lint:fix": "biome check --write",
@@ -35,7 +34,6 @@
3534
"firebase": "^12.11.0",
3635
"jotai": "^2.18.1",
3736
"motion": "^12.38.0",
38-
"nitro": "3.0.260311-beta",
3937
"openapi-fetch": "^0.17.0",
4038
"react": "^19.2.4",
4139
"react-dom": "^19.2.4",
@@ -58,6 +56,11 @@
5856
"typescript": "~5.9.3",
5957
"vite": "npm:rolldown-vite@7.3.1",
6058
"vite-plugin-pwa": "^1.2.0",
59+
"workbox-cacheable-response": "^7.4.0",
60+
"workbox-expiration": "^7.4.0",
61+
"workbox-precaching": "^7.4.0",
62+
"workbox-routing": "^7.4.0",
63+
"workbox-strategies": "^7.4.0",
6164
"workbox-window": "^7.4.0"
6265
}
6366
}

0 commit comments

Comments
 (0)