Termwise is a degree planning application built with Next.js App Router, React, TypeScript, and Tailwind CSS.
This README documents the target architecture direction: a PostgreSQL-backed application served through route-based APIs.
- Product Overview
- Architecture Report
- Tech Stack
- Project Structure
- Data Flow
- Environment Variables
- Scripts
- Related Docs
Termwise focuses on:
- Interactive term-by-term planning.
- Course discovery and prerequisite-aware planning support.
- Fast UI workflows for building and validating academic plans.
The system is organized into two primary boundaries:
- Frontend application (Next.js): route rendering, UI composition, and client-side interactions.
- Backend route layer: route handlers that validate requests, enforce business rules, and read/write PostgreSQL data.
- Route layer (
app/+ route handlers):- Receives HTTP requests.
- Validates payloads and query params.
- Delegates persistence to database access modules.
- Feature modules (
features/):- Encapsulate feature-specific UI and logic (planner, courses, plans, etc.).
- Keep business behavior close to feature boundaries.
- Shared components (
components/):- Reusable UI primitives and app-wide composed components.
- Library utilities (
lib/):- Shared helpers, utilities, and database integration points.
PostgreSQL is the source of truth for persisted application data. The intended data access pattern is:
- Request enters an app route or API route handler.
- Handler validates and normalizes request input.
- Handler executes parameterized PostgreSQL queries through a DB helper.
- Handler returns typed, serializable JSON responses to the client.
Guiding principles:
- Keep SQL access centralized in dedicated database modules.
- Use transactions for multi-step mutations that must be atomic.
- Return stable DTOs from route handlers; avoid leaking raw DB records directly.
- Prefer explicit schema migrations over ad hoc table changes.
The app uses route-driven boundaries for backend operations:
- Read endpoints for planner and catalog data.
- Mutation endpoints for plan create/update/save flows.
- Feature-specific routes grouped by domain concern.
Recommended conventions:
- Use clear REST semantics (
GET,POST,PATCH,DELETE) where applicable. - Validate at route boundaries.
- Keep route handlers thin and push domain logic into feature/data modules.
- Framework: Next.js 16 App Router
- UI: React 19, Tailwind CSS v4, shadcn/ui, lucide-react
- Language: TypeScript (strict)
- Database: PostgreSQL
- Backend interface: route handlers / API routes
- Tooling: ESLint, Prettier, Husky, lint-staged
termwise/
app/
layout.tsx
page.tsx
api/* (route handlers)
components/
theme-provider.tsx
ui/*
features/
planner/*
courses/*
plans/*
sections/*
majors/*
departments/*
lib/
db/*
utils.ts
README.md
SETUP.md
INSTALLATION.md
Typical request lifecycle:
- UI initiates data fetch or mutation.
- Request hits a route handler.
- Route validates input and applies business rules.
- Route reads/writes PostgreSQL.
- Route returns JSON response.
- UI updates local state and renders the latest plan view.
Environment variables should be scoped by runtime:
- Server-only variables for database credentials and connection strings.
- Public variables only when truly required in browser code.
Use .env.local for local development and keep secrets out of version control.
From root package.json:
npm run dev- start local Next.js dev servernpm run build- build production appnpm run start- run built appnpm run type-check- TypeScript checknpm run lint:check- strict lint passnpm run format:check- formatting validationnpm run validate- type + lint + format checks
SETUP.md- developer setup and day-to-day runbookINSTALLATION.md- installation and bootstrap guide