Files
Calendar_Frontend/docs/deployment.md
T
PaddyandClaude Opus 5.5 0cda40f85e Rewrite the calendar frontend in Next.js
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>
2026-09-28 22:15:59 +02:00

3.3 KiB

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.

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.