From 97f6e253f742be7fc2b56ebd335c4b99a300dda4 Mon Sep 17 00:00:00 2001 From: fegger Date: Tue, 19 May 2026 16:08:20 +0200 Subject: [PATCH] Create README.md --- README.md | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..00e6bb0 --- /dev/null +++ b/README.md @@ -0,0 +1,204 @@ +# Loam — MTB Build & Tune + +A Next.js web app for mountain bike riders to configure builds, get manufacturer-verified suspension and tire setup starting points, save post-ride reviews, and receive AI-powered tuning recommendations based on personal preference history. + +Built with Next.js App Router, Prisma/PostgreSQL, and Ollama for local LLM inference. The API layer is designed for reuse in a future React Native/Android client. + +--- + +## Tech stack + +| Layer | Tech | +|---|---| +| Framework | Next.js 16 (App Router) | +| Language | TypeScript | +| Database | PostgreSQL | +| ORM | Prisma | +| Auth | bcryptjs + jose (JWT in HTTP-only cookies) | +| Images | sharp (layer compositing) | +| AI | Ollama (local LLM) | +| Validation | Zod | + +--- + +## Features + +- **Catalog** — Curated frames, forks, shocks, and tires with real-world setup ranges +- **Setup verification** — Every product carries a research audit trail (manufacturer docs, community sources, confidence levels) +- **Build composer** — Layered bike image generation from selected components +- **Per-user learning** — Builds, reviews, and learned preferences are scoped to authenticated users +- **AI recommendations** — Ollama-powered tuning advice that incorporates the rider's own review history +- **Post-ride reviews** — Rate suspension feel, grip, rolling speed, and report issues (bottom-outs, harsh hits, wallow, small-bump harshness) + +--- + +## Getting started + +### Prerequisites + +- Node.js 20+ +- PostgreSQL running locally (or a remote instance) +- Ollama installed and running (optional, for AI recommendations) + +### 1. Install dependencies + +```bash +npm install +``` + +### 2. Configure environment variables + +```bash +cp .env.example .env.local +``` + +Edit `.env.local`: + +``` +DATABASE_URL=postgresql://user:password@localhost:5432/loam +JWT_SECRET=change-this-to-a-long-random-string-in-production + +# Optional — defaults shown +OLLAMA_URL=http://localhost:11434 +OLLAMA_MODEL=llama3.1:8b +``` + +### 3. Set up the database + +```bash +# Create and apply migrations +npm run db:migrate + +# Seed product catalog +npm run db:seed +``` + +### 4. Pull an Ollama model (optional) + +```bash +ollama pull llama3.1:8b +``` + +### 5. Run the dev server + +```bash +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000). + +--- + +## Project structure + +``` +prisma/ + schema.prisma # User, BikeBuild, RideReview, RiderPreference, Product + seed.ts # Seeds catalog into Product table +src/ + app/ + api/ + auth/ # register, login, me, logout + builds/ # list / create builds (scoped to user) + reviews/ # create reviews (scoped to user + build ownership) + ai/recommend # Ollama recommendation prompt + images/compose # sharp layer compositing + catalog/ # public catalog + setupVerification + setup-audit/ # research audit endpoint + components/ + BikeBuilderApp.tsx + lib/ + auth.ts # bcrypt, JWT cookie session, requireAuth + db.ts # per-user Prisma queries + catalog.ts # static product data with citations + recommendations.ts # setup math by rider profile + setupVerification.ts # research audit metadata + types.ts # shared TypeScript types +public/ + images/ # product assets + user-generated builds +``` + +--- + +## API routes + +| Route | Method | Auth | Description | +|---|---|---|---| +| `/api/auth/register` | POST | No | Create account, set session cookie | +| `/api/auth/login` | POST | No | Log in, set session cookie | +| `/api/auth/me` | GET | No | Return current session user | +| `/api/auth/logout` | POST | No | Clear session cookie | +| `/api/builds` | GET | Yes | List current user's builds | +| `/api/builds` | POST | Yes | Save a new build | +| `/api/reviews` | POST | Yes | Review a build (must own it) | +| `/api/ai/recommend` | POST | Yes | AI tuning advice with user preferences | +| `/api/images/compose` | POST | No | Compose build image from layers | +| `/api/catalog` | GET | No | Full catalog + setupVerification | +| `/api/setup-audit` | GET | No | Research audit report | + +--- + +## Auth system + +- Passwords hashed with bcrypt (12 rounds) +- Sessions are JWTs stored in HTTP-only `loam-session` cookies (7-day expiry) +- `requireAuth()` guards data-modifying routes +- All builds, reviews, and preferences are scoped to the authenticated `userId` + +--- + +## Data model overview + +- **User** — email (unique), passwordHash, name +- **BikeBuild** — belongs to User; stores component IDs, rider profile, setup JSON, image path +- **RideReview** — belongs to User + BikeBuild; ratings and issue flags +- **RiderPreference** — one per User; aggregated from review history (harsh/soft tendency, grip preference) +- **Product** — seeded catalog of frames, forks, shocks, tires with specs and sources JSON + +--- + +## Research & citations + +Every product entry includes a `sources` array and a `SetupVerification` record: + +- `manufacturer` — official setup guides, owner manuals, product pages +- `community` — Pinkbike reviews, Reddit discussions, Blister/MTBR test notes +- Status levels: `verified` → `manufacturer-guided` → `community-informed` → `estimated` + +The `/api/setup-audit` endpoint returns a full breakdown of confidence levels and missing sources. + +--- + +## Notes on Android reuse + +The API surface is plain JSON over HTTP with cookie-based auth. A React Native or Android client can reuse the same endpoints by: + +1. Implementing cookie jar storage for the `loam-session` cookie +2. Calling `/api/auth/login` or `/api/auth/register` to obtain a session +3. Reusing `/api/builds`, `/api/reviews`, `/api/ai/recommend`, and `/api/catalog` as-is + +The image composition endpoint (`/api/images/compose`) returns a PNG path; clients can either request server-side composition or replicate the layer-stacking logic locally. + +--- + +## Scripts + +| Command | Purpose | +|---|---| +| `npm run dev` | Start Next.js dev server | +| `npm run build` | Production build | +| `npm run db:migrate` | Run Prisma migrations | +| `npm run db:seed` | Seed product catalog | +| `npm run db:studio` | Open Prisma Studio | +| `npm run lint` | Run ESLint | + +--- + +## Environment variables + +| Variable | Required | Default | Description | +|---|---|---|---| +| `DATABASE_URL` | Yes | — | PostgreSQL connection string | +| `JWT_SECRET` | Yes | — | Secret for signing session JWTs | +| `OLLAMA_URL` | No | `http://localhost:11434` | Ollama server base URL | +| `OLLAMA_MODEL` | No | `llama3.1:8b` | Model name for recommendations |