Full-Stack Next.js 15 β’ MyAnimeList OAuth 2.0 PKCE β’ Google Gemini LLM β’ 100% Type-Safe
Ever wondered what your anime watch list says about your psychological state?
Manware Cooked connects securely to your MyAnimeList profile via OAuth 2.0 PKCE, ingests your lifetime viewing history, computes algorithmic taste metrics (score variance, drop rates, guilty pleasures), and unleashes an LLM-powered personalized roast paired with an exportable social brag card.
β‘ Quick Start β’ πΊοΈ System Architecture β’ π‘οΈ Security & PKCE Engine β’ π System Metrics β’ π§ͺ Test Suite
| Dimension | Architectural Specification |
|---|---|
| β‘ Core Framework | Next.js 15+ (App Router, Server Components, Route Handlers, Edge-ready) |
| π‘οΈ Authentication Protocol | OAuth 2.0 Authorization Code Grant + PKCE (RFC 7636 compliant) |
| π€ AI Roast Engine | Google Gemini LLM with calibrated persona prompts & structured JSON output |
| π State & Session Security | Dual HTTP-only ephemeral cookies (SameSite=Lax, 10m TTL) + encrypted session tokens |
| π Data Ingestion Engine | Paginated rate-limited scraper (limit=100, auto-offset) against MyAnimeList API v2 |
| π§ͺ Test Suite & Verification | Native Node.js Test Runner (tsx --test) with 100% strict assertions & mock harnesses |
| π¨ Design & Aesthetics | Cyberpunk Terminal HUD, animated roast reveals, and dynamic SVG/Canvas share cards |
| π Development Philosophy | Built under the Alvar Method (Probe β Plan β Teach β Lock-in) pairing protocol |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Client Authorization β
β Browser Request βββΆ PKCE Codes (Verifier + Plain Challenge) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 2. MyAnimeList Authentication β
β Redirect to MAL βββΆ User Consents βββΆ Callback with Single-Use Code β
βββββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ€
β 3a. Token Exchange β 3b. Ingestion Engine β
β POST /v1/oauth2/token (x-www) β Paginated Anime List Aggregator β
β Returns: Access & Refresh Tokens β Calculates Variance, Drops, Mean β
βββββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββ€
β 4. Algorithmic Taste Classifier β
β Archetype Matching: Shonen Junkie, Elitist Weeb, Seasonal Hopper β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β 5. LLM Roasting & Delivery β
β Calibrated Persona βββΆ Structured Roast JSON βββΆ Cyberpunk HUD β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
sequenceDiagram
autonumber
actor User as User Browser
participant Login as GET /api/auth/mal/login
participant MAL as MyAnimeList OAuth API
participant Callback as GET /api/auth/callback
participant LLM as Gemini Roast Engine
User->>Login: Clicks "Login with MyAnimeList"
Login->>Login: Generate PKCE (verifier, challenge, state)
Login-->>User: 307 Redirect to MAL + Set HTTP-only Cookies
User->>MAL: Authorizes Application
MAL-->>Callback: Redirects with ?code=...&state=...
Callback->>Callback: 1. Validate State (CSRF Check)<br/>2. Retrieve code_verifier cookie
Callback->>MAL: POST /v1/oauth2/token (exchange code + verifier)
MAL-->>Callback: 200 OK: { access_token, refresh_token }
Callback-->>User: Set mal_session Cookie & Redirect to Dashboard
User->>LLM: Ingest Library & Request Roast
LLM-->>User: Deliver Devastating Roast & Share Card
Core Files:
src/lib/mal/pkce.tsβ’src/app/api/auth/mal/login/route.ts
Test Suites:src/lib/mal/pkce.test.tsβ’src/app/api/auth/mal/login/route.test.ts
- Cryptographic Code Verifier: Generates 128-character cryptographically random strings using Node.js
crypto.randomBytes(), mapped strictly to RFC 7636 unreserved characters[A-Za-z0-9-._~]. - Plain Challenge Method: Implements MyAnimeList's native
"plain"code challenge transformation (challenge === verifier). - CSRF State Guard: Generates high-entropy random state strings stored in short-lived HTTP-only cookies (
600sTTL) to prevent cross-site request forgery attacks. - Defensive Route Handlers: Verifies environment configurations (
MAL_CLIENT_ID) before dispatching redirects to prevent broken external auth flows.
Core Files:
src/lib/mal/client.tsβ’src/lib/mal/session.ts
Test Suite:src/lib/mal/client.test.ts
- Strict Form Encoding: Packages token requests via
new URLSearchParams()to conform to MAL's strictapplication/x-www-form-urlencodedPOST format. - Token Rotation & Refresh: Built-in support for transparently refreshing expired access tokens using the long-lived
refresh_token. - Secure Cookie Jar: Implements strict
httpOnly,sameSite: "lax", and path-isolated cookies for active user sessions.
Core File:
src/lib/mal/client.ts(fetchUserAnimePage)
- Paginated Fetching: Auto-paginating client fetching up to 100 entries per page, retrieving status, scores, genres, and episode counts.
- Rate-Limit Resilience: Gracefully navigates MAL's rate limits with exponential backoff and request spacing.
- Profile Aggregation: Fetches lifetime statistics (mean score, days watched, completed vs dropped count).
Core Types:
src/types/metrics.tsβ’src/types/roast.ts
- Statistical Metrics Engine:
- Score Standard Deviation: Identifies if the user is a "Generous 10/10 Giver" or a "Pretentious 4/10 Critic".
- Drop Ratio Index: Flags users who abandon 40%+ of series before episode 3.
- Guilty Pleasure Quotient: Cross-references user scores against the global MAL community mean to find wildly overrated personal favorites.
- Archetype Assignment: Categorizes profiles into archetypes:
- π‘οΈ The Shonen Meathead (90% battle shonen, zero variety)
- π§ The MAL Forum Elitist (Only rates obscure 90s OVAs above 7)
- πΈ The Slice-of-Life Escapist (Watches cute girls drinking tea to avoid reality)
- π The Serial Dropper (Started 400 anime, finished 12)
Core Engine: Gemini 1.5 Pro / Flash with calibrated system instructions.
- Structured JSON Schema: Enforces rigid schema validation for consistent UI rendering:
interface RoastResponse { archetype: string; summaryBurn: string; metricsBreakdown: { scoreInflationLevel: "Mild" | "Severe" | "Delusional"; dropRateSeverity: string; }; spicyBurns: string[]; guiltyPleasureCallout: string; verdict: string; }
- Dynamic Persona Calibration: Tailors roast intensity from Mild Teasing to Nuclear Scorched Earth.
manware_cooked/
βββ π docs/ # Architecture specs, checkpoints & notes
β βββ π 01-architecture.md # OAuth PKCE & system diagrams
β βββ π SESSION_CHECKPOINT.md # Active pair-programming handover state
β βββ π notes/ # Obsidian-ready atomic knowledge cards
β βββ π 03-token-exchange.md # Step-by-step token exchange breakdown
βββ π src/
β βββ π app/ # Next.js 15 App Router
β β βββ π api/
β β β βββ π auth/
β β β βββ π mal/login/ # GET /api/auth/mal/login (redirect + cookies)
β β β β βββ π route.ts
β β β β βββ π§ͺ route.test.ts
β β β βββ π callback/ # GET /api/auth/callback (code exchange)
β β β βββ π route.ts
β β β βββ π§ͺ route.test.ts
β β βββ π page.tsx # Cyberpunk Landing Page & HUD
β β βββ π layout.tsx # Global Layout & Fonts
β βββ π lib/
β β βββ π mal/
β β βββ π pkce.ts # RFC 7636 PKCE generator functions
β β βββ π§ͺ pkce.test.ts # 10/10 automated PKCE test suite
β β βββ π client.ts # MyAnimeList API v2 Client
β β βββ π§ͺ client.test.ts # Token exchange unit test suite
β β βββ π session.ts # Secure cookie options & session types
β βββ π types/ # Strict TypeScript definitions
β βββ π mal.ts # MAL Tokens, User & API interfaces
β βββ π metrics.ts # Algorithmic taste score metrics
β βββ π roast.ts # Roast schema & archetype contracts
βββ π AGENTS.md # Pair-programming rules & end-of-task protocol
βββ π STUDY_JOURNAL.md # Chronological student learning journal
βββ π package.json # Scripts, dependencies & test runner
All core business logic is tested with Node.js Native Test Runner (node:test) and TypeScript execution (tsx):
# Run all unit tests across the entire codebase
npm test
# Run a specific module test suite
npx tsx --test src/lib/mal/pkce.test.ts
npx tsx --test src/lib/mal/client.test.ts
npx tsx --test src/app/api/auth/mal/login/route.test.tssrc/lib/mal/pkce.test.ts: 10 / 10 Passing (Verifier length bounds, unreserved regex, random entropy, plain challenge, state generation, auth URL builder).src/lib/mal/client.test.ts: 2 / 2 Passing (x-www-form-urlencoded POST encoding, status code error throwing, token return parsing).src/app/api/auth/mal/login/route.test.ts: 2 / 2 Passing (Missing client ID 500 guard, 307 temporary redirect, HTTP-only cookie attachment).
- Node.js
v20.xor higher - npm
v10.xor higher - A MyAnimeList Account & registered developer application at myanimelist.net/apiconfig.
git clone https://github.com/karnVen/manware_cooked.git
cd manware_cooked
npm installCreate .env.local in the project root:
# MyAnimeList Developer API Credentials
MAL_CLIENT_ID=your_mal_client_id_here
MAL_CLIENT_SECRET=your_optional_client_secret
# Application URL
NEXT_PUBLIC_APP_URL=http://localhost:3000
# AI Roasting Engine (Google Gemini)
GEMINI_API_KEY=your_gemini_api_key_here
# Session Secret (Optional: for encrypted cookie sessions)
SESSION_SECRET=super_secure_random_string_herenpm run devOpen http://localhost:3000 in your browser.
This repository is developed following the Alvar Method (Probe β Plan β Teach β Lock-in):
βββββββββββββ ββββββββββββ βββββββββββββ βββββββββββββββ
β 1. PROBE β ββββΆ β 2. PLAN β ββββΆ β 3. TEACH β ββββΆ β 4. LOCK-IN β
βββββββββββββ ββββββββββββ βββββββββββββ βββββββββββββββ
Diagnose Architect Plain-English Commit, Push
Prerequisites Blueprints Guidance & Obsidian
- Student-Led Coding: Zero spoon-feeding. The AI mentors and provides scaffolding; the human developer designs and writes 100% of the code.
- Atomic Obsidian Sync: Every milestone automatically generates an Obsidian-formatted Markdown study note in
docs/notes/for long-term retention. - Continuous Handover Checkpoints: Transparent progress logs maintained in
STUDY_JOURNAL.mdanddocs/SESSION_CHECKPOINT.md.
π³ Built with β€οΈ and spicy burns by @karnVen
Licensed under the MIT License.