Skip to content

vojtechzicha/vrt-trains

Repository files navigation

VRT - Train Line Management System

A Next.js application for managing fictional train lines, viewing timetables, and displaying departure boards. Data is stored in MongoDB; the network is edited through the built-in admin UI.

Getting Started

pnpm install
cp .env.example .env.local   # then fill in your MongoDB Atlas connection string
pnpm dev

Open http://localhost:3000 in your browser. Manage the network under /admin.


Data Storage (MongoDB)

Data lives in MongoDB Atlas, which lets the app be edited live when deployed to a serverless host like Vercel (where the filesystem is read-only).

The data layer lives in lib/db/:

  • lib/db/mongodb.ts — connection management (cached across serverless invocations and dev HMR).
  • lib/db/repository.ts — a generic, type-safe Repository<T> over a collection of documents keyed by a string id.
  • lib/db/indexes.ts — collection names and index definitions. Indexes are created automatically on first use, so a freshly provisioned database needs no setup step.
  • lib/db/collections.ts — the typed repository per entity.

Domain access functions in lib/data/* (e.g. getStations, createLine) build on those repositories. The document shape of each collection is defined by the TypeScript interfaces in types/index.ts — that file is the source of truth for the data model (Station, Line, Variant, Timetable, RouteCorridor, OperatingPattern, LineSchedule).

All routes are dynamically rendered, so changes made through the admin UI appear immediately without a redeploy.


Configuration

Set these environment variables (locally in .env.local, on Vercel under Project → Settings → Environment Variables):

Variable Required Description
MONGODB_URI yes Atlas connection string (mongodb+srv://...).
MONGODB_DB no Database name within the cluster (defaults to vrt).
APP_PASSWORD no Password protecting /admin. Unset = admin open (see below).

Admin password protection

The public site (timetables, departure boards, line/station views) is always open. The /admin pages and the /api/admin/* mutation endpoints are gated by APP_PASSWORD:

  • Unset (typical for local dev): the admin area is open, no login required.
  • Set (recommended in production): visiting /admin redirects to /login; after entering the password a signed session is stored and you stay logged in for 7 days per device.

How it works (lib/serverAuth.ts, proxy.ts, app/api/auth/route.ts):

  • The password is never stored — the server only compares against APP_PASSWORD (constant-time) and discards the input.
  • Sessions are stateless HMAC tokens in an httpOnly cookie. The signing key is derived from the password, so changing APP_PASSWORD instantly invalidates every existing session.
  • proxy.ts verifies the session on every /admin and /api/admin/* request, so the gate can't be bypassed by calling the API directly.
  • Wrong-password guesses get a small, escalating delay.

Use a long, random APP_PASSWORD and always serve over HTTPS (Vercel does).


Project Structure

vrt/
├── app/                    # Next.js pages and API routes
│   ├── admin/             # Admin UI (password-gated when APP_PASSWORD is set)
│   ├── api/admin/         # Admin mutation endpoints (gated)
│   ├── api/auth/          # Login / logout endpoint
│   ├── login/             # Password prompt
│   ├── lines/             # Train line views
│   ├── stations/          # Station views
│   └── departures/        # Departure boards
├── components/            # React components
├── lib/
│   ├── data/              # Domain data access (built on lib/db)
│   └── db/                # MongoDB connection, repository, indexes
├── proxy.ts               # Admin password gate (middleware)
└── types/                 # TypeScript interfaces (the data model)

About

A Next.js application for managing fictional train lines, viewing timetables, and displaying departure boards.

Resources

Stars

Watchers

Forks

Contributors

Languages