This repository hosts the official TrainLCD landing page and system status page in a single monorepo. The LP is built with Astro, while the real-time status dashboard runs on Next.js 16 and React 19.
- Project Overview
- Key Features
- Repository Structure
- Tech Stack
- Getting Started
- Environment Variables
- Available Scripts
- Development Workflow
- Architecture Notes
- Database & Seeding
- Contributing
- License
apps/lp(Landing Page): Astro + Preact site optimized for static delivery. Used for the public product introduction and announcements.apps/status(Status Page): Next.js App Router app. Prisma + PostgreSQL store service snapshots, while Redis cache + SSE stream real-time updates to the UI.- Shared Tooling: Turbo Repo orchestrates tasks, and shared ESLint/TypeScript settings live under
packages/.
- π Real-time monitoring:
apps/statusautomatically refreshes via Redis Pub/Sub + Server-Sent Events. - π Localization:
detectLocale()inspectsAccept-Languageheaders and switches between Japanese and English (apps/status/app/server/lib/locale.ts). - π§ Static + dynamic hybrid: The LP ships as static assets, while the status app serves fresh data via SSR/ISR.
- π§° Centralized lint/TS config:
packages/eslint-configandpackages/typescript-configkeep code quality consistent. - π§ͺ Vitest coverage: Snapshot and event APIs include dedicated unit/integration tests inside
__tests__folders.
Website/
βββ apps/
β βββ lp/ # Astro landing page
β βββ status/ # Next.js status app (SSR + SSE)
βββ packages/
β βββ eslint-config/ # Shared ESLint rules
β βββ typescript-config/ # Shared TS config
βββ prisma/ # Prisma schema & seed
βββ .github/workflows/ # CI (code-quality, etc.)
βββ turbo.json # Turbo pipeline definition
βββ README.md
| Layer | Tools |
|---|---|
| Monorepo management | Turbo Repo, npm Workspaces |
| Landing page | Astro 5, Preact 10, Sharp |
| Status app | Next.js 16 (App Router), React 19, Tailwind CSS |
| Data | Prisma 6, PostgreSQL, Redis (ioredis) |
| Real-time | Server-Sent Events, Redis Pub/Sub |
| Testing & linting | Vitest 4, ESLint 9 |
npm install # Install all workspace dependencies
npm run lint # Run ESLint across the repo via Turbo
cd apps/status && npm run test # Execute status app tests (Vitest)Use Node.js 18+ and npm 10.x in local environments. npm run dev launches the dev servers defined in turbo.json, so multiple apps can run in parallel.
| Name | Purpose | Example |
|---|---|---|
DATABASE_URL |
PostgreSQL connection for Prisma | postgres://trainlcd:password@localhost:5432/trainlcd |
REDIS_URL |
Redis cache + pub/sub endpoint for status updates | redis://localhost:6379 |
ALLOWED_SNAPSHOT_ORIGINS |
Comma-separated list (or *) for /api/status/snapshot CORS |
https://status.trainlcd.app,https://app.trainlcd.com |
STATUS_UPDATE_API_KEY |
Shared secret for /api/status/events mutations |
super-secret-key |
Store secrets in .env.local under each app and load them via dotenv where needed.
| Script | Description |
|---|---|
npm run dev |
Start all app dev servers through Turbo |
npm run build |
Build every app/package in the workspace |
npm run lint |
Run ESLint with --max-warnings=0 |
npm run db:seed |
Execute prisma/seed.ts to load sample data |
apps/lp: npm run dev |
Launch the Astro server (default port 3000) |
apps/status: npm run dev |
Launch the Next.js server (SSE enabled) |
apps/status: npm run test |
Run Vitest suites for APIs and server logic |
- Run
npm install,npm run lint, andcd apps/status && npm run testto ensure a clean baseline. - Implement changes and add/extend tests under
__tests__(e.g.,apps/status/app/server/lib/__tests__). - Before opening a PR, run
npm run lint,cd apps/status && npm run test, andnpm run build. - Confirm the checklist: zero lint errors, all tests green, new functionality covered by tests.
- SSE stream:
apps/status/app/api/status/stream/route.tsmerges Redis pub/sub events with PostgreSQL seed data and emits a heartbeat every 30 seconds. Details live inapps/status/SSE_IMPLEMENTATION.md. - Middleware guard:
apps/status/middleware.tsenforces strict Origin checks, allowing onlystatus.trainlcd.appin production. - i18n: See
apps/status/I18N_IMPLEMENTATION.mdfor locale detection and theLocaleTextpattern used across services/incidents. - Caching: Redis keys encode the locale, caching service and incident payloads for ~60 seconds before falling back to Prisma queries.
Prisma schema files live in prisma/schema.prisma. Seed data can be loaded with:
npm run db:seedThe postinstall script inside apps/status runs prisma generate --schema=../../prisma/schema.prisma, so Prisma Client is ready right after installing dependencies.
- Discuss ideas via Issues/Discussions before large changes.
- Create feature branches such as
feat/<topic>. - Ensure lint/tests/build all succeed before opening a PR.
- Include a summary, screenshots (if applicable), and test results in the PR description.
Refer to AGENTS.md and the implementation memos for deeper contributor guidelines.
Distributed under the MIT License. See LICENSE for details.
