Replaces the Angular 18 app with Next.js 16 / React 19 / Tailwind 4 / shadcn, the same stack and design system as nachklang-feedback, planned in docs/rewrite-plan.md. - Admin: all calendars in one mobile-friendly list (month groups, calendar chips, Kommend/Vergangen/Alle, search, sort, filters in the URL), an edit sheet for create/edit/duplicate/delete, publish confirmation, and an "Abonnieren" dialog with subscription links for every calendar. - Public landing page: subscribe links from env instead of hardcoded, plus the next public events, server-rendered and revalidated every 5 minutes. - All times handled explicitly as Europe/Berlin; whole-day events stored as 00:00-23:59. Fixes carried over from the Angular app: the move dialog leaking a cancelled calendar change, saves that looked saved when they failed, in-place Date mutation, and duplicated calendar-id mappings. - Same shared-session auth as before (proxy.ts gate, /admin/me, 401 vs 403). - 112 Vitest tests over lib/; docs in docs/ (architecture, features, gotchas, API wish list, deployment). Needs the API branch feature/calendar-ical-escaping-subscriptions deployed first (GET /calendar/events/subscriptions). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
3.3 KiB
Markdown
70 lines
3.3 KiB
Markdown
# Deployment and switchover
|
|
|
|
How the Next.js app replaces the Angular build on `calendar.nachklang.art`. **The deploy itself is
|
|
done by a person** (never by Claude). Steps marked *unverified* could not be checked without access
|
|
to the Plesk server.
|
|
|
|
## Order matters
|
|
|
|
1. **API first**: merge and deploy the API branch `feature/calendar-ical-escaping-subscriptions`
|
|
(rebuild + restart; no new env vars - it uses the existing `API_BASE_URL` and
|
|
`*_CREDENTIAL` values). The old Angular app keeps working against it; the new app's "Abonnieren"
|
|
dialog needs it.
|
|
2. **Then the frontend.**
|
|
|
|
## Build
|
|
|
|
Node version: `.nvmrc` says 26, copied from the API repo - *unverified* that Plesk offers it; use
|
|
the version the API runs on.
|
|
|
|
```bash
|
|
npm ci
|
|
NEXT_PUBLIC_API_BASE_URL=https://api.nachklang.art \
|
|
NEXT_PUBLIC_ADMIN_APP_URL=https://admin.nachklang.art \
|
|
npm run build
|
|
```
|
|
|
|
- Both values are **inlined at build time** - they must be set for `npm run build`, not just at
|
|
runtime. (Values from the Angular `environment.prod.ts`.)
|
|
- `npm run build` runs `postbuild`, which copies `.next/static` into `.next/standalone/.next/static`.
|
|
Without it the standalone server serves the pages without CSS and JS.
|
|
- The build fetches the public events from the API to prerender `/`. If it can't reach the API it
|
|
still succeeds.
|
|
|
|
## Run (Plesk Node.js / Passenger)
|
|
|
|
- Application startup file: `.next/standalone/server.js`.
|
|
- The server listens on `PORT` (and `HOSTNAME`). Whether Passenger sets `PORT` itself or needs it
|
|
configured is *unverified* - check how the feedback app is set up on the same server.
|
|
- Optional runtime env: `API_BASE_URL` (internal address for the landing page's server-side fetch).
|
|
- The subdomain changes from serving static files to a Node.js app. *Unverified* how Plesk handles
|
|
that switch for an existing domain (document root vs. application root).
|
|
|
|
Checked locally (2026-09-28): `PORT=4300 node .next/standalone/server.js` serves `/` with events,
|
|
CSS/JS (200), the favicon, and redirects `/admin` without a cookie to `/admin/login`.
|
|
|
|
## Things that must already be true (unchanged from the Angular app)
|
|
|
|
The origin stays `https://calendar.nachklang.art`, so nothing should need changing - inferred from
|
|
the Angular app already using the same cookie auth:
|
|
|
|
- the API's CORS list contains `https://calendar.nachklang.art` (verified in `app.factory.ts`);
|
|
- the admin app's `NEXT_PUBLIC_ALLOWED_REDIRECT_ORIGINS` contains it (otherwise signing in lands on
|
|
the admin start page instead of coming back);
|
|
- the API's better-auth trusted origins contain it (otherwise sign-out fails).
|
|
|
|
## Smoke test after the switch
|
|
|
|
1. `/` loads styled, shows "Nächste Termine", and the Apple link opens a subscription.
|
|
2. `/admin` while signed out → admin login → back to `/admin` after signing in.
|
|
3. The list shows all calendars; an edit saves; "Abonnieren" lists links.
|
|
4. An account without calendar permission sees "Kein Zugriff" (no redirect loop).
|
|
5. "Abmelden" signs out and offers to sign in again.
|
|
6. On a phone: list, "+" button, bottom sheet.
|
|
7. An existing iCal subscription still updates (the feed URL is unchanged).
|
|
|
|
## Rollback
|
|
|
|
Keep the last Angular build (`dist/nachklang-calendar`) for about a week and switch the subdomain
|
|
back to it if needed. The API change is backwards compatible with the Angular app, so it can stay.
|