An innovative AI-powered fanfiction writing platform built with Next.js 16, CopilotKit, and LangGraph.js.
Create amazing fanfiction with an AI assistant that understands your characters, respects canon, and helps bring your stories to life.
Featuring smart editing, creative wizard, fandom research, and Human-in-the-Loop approval workflows.
Live Demo Β· Report Bug Β· Request Feature
Share FanFic Lab
Pioneering the future of AI-assisted creative writing. Built for the fanfiction community.
Tech Stack
Important
FanFic Lab combines cutting-edge AI technology with a deep understanding of fanfiction culture. It features CopilotKit for real-time AI suggestions, LangGraph.js for intelligent agent workflows, Tavily for fandom research, and a beautiful "Literary Atelier" design system with Teal + Amber color palette.
Table of Contents
FanFic Lab is designed for the fanfiction community, providing:
- Smart Editor - AI-powered writing assistance with inline suggestions
- Creative Wizard - Conversational story setup with Human-in-the-Loop (HITL) forms
- Fandom Research - Tavily-powered research for characters, ships, and world-building
- Fandom Feed - Discover and filter stories by fandom, ships, and tags
- Character Management - Track characters and detect out-of-character moments
- Image Gallery - AI-generated character portraits and scene illustrations (coming soon)
graph TB
subgraph "User Interface"
A[Homepage] --> B[Creative Wizard]
A --> C[Smart Editor]
A --> D[Fandom Feed]
B --> C
end
subgraph "AI Layer"
E[CopilotKit Provider]
F[LangGraph Agent]
G[OpenAI GPT-4o]
H[Tavily Search]
end
subgraph "Backend"
I[Next.js API Routes]
J[Prisma ORM]
K[Neon PostgreSQL]
L[Redis Cache]
end
C --> E
B --> E
E --> I
I --> F
F --> G
F --> H
I --> J
J --> K
I --> L
Experience next-generation writing with AI-powered inline suggestions. The Smart Editor integrates CopilotKit for real-time assistance, helping you write better fanfiction faster.
| Feature | Description |
|---|---|
| CopilotTextarea | Inline AI suggestions while typing |
| Magic Continue | AI writes the next 200-300 words naturally |
| Expand Text | Enhance selected text with more dialogue/description/emotion |
| Polish Prose | Improve writing quality at light/medium/deep levels |
| Autosave | Automatic saving with debounce to localStorage |
| HITL Approval | Review and approve/edit AI-generated content |
Revolutionary story setup wizard that researches your fandom using Tavily API, understands your characters, and generates story outlines for your approval.
| Feature | Description |
|---|---|
| Fandom Selector | Browse popular fandoms or enter custom |
| Source Research | Tavily-powered research for characters, ships, world-building |
| Ship Builder | Define romantic pairings with AI suggestions |
| Character Setup | Add characters with AI-enhanced profiles |
| Outline Generation | AI creates story outline for HITL approval |
| Step Progress | Visual progress tracking through wizard |
Intelligent character management with out-of-character detection to keep your characters authentic.
| Feature | Description |
|---|---|
| Character Sidebar | Add/manage characters with personality traits |
| OOC Detection | AI checks for out-of-character moments |
| Character Profiles | Name, fandom, personality, speech patterns |
| Original Characters | Support for OCs with custom definitions |
| Dialogue Suggestions | In-character dialogue generation |
Discover and filter stories by fandom, ships, tags, rating, and status.
| Feature | Description |
|---|---|
| Story Cards | Display story info with cover images and metadata |
| Tag Filtering | Filter by relationship, setting, tone, content |
| Fandom Tabs | Quick navigation between fandoms |
| Rating/Status Filters | Filter by age rating and completion status |
| Sorting | Sort by recent, popular, comments, word count |
| Infinite Scroll | Load more stories seamlessly |
- π¨ Quick Setup: Deploy in under 5 minutes with Railway deployment
- π Responsive Design: Beautiful UI on desktop and mobile
- π Authentication: Stack Auth for secure user management
- π Literary Atelier Design: Teal + Amber color palette with elegant typography
- π£οΈ Real-time AI: Live AI suggestions and generation
- π Research Cache: Redis caching for Tavily search results (30-day TTL)
- π Extensible: Plugin-ready architecture for custom functionality
- βοΈ Cloud Storage: Cloudinary integration for image hosting
β¨ More features are continuously being added as the project evolves.
| Layer | Technology | Deployment |
|---|---|---|
| Framework | Next.js 16 (App Router, Turbopack) | Railway |
| UI | React 19, TailwindCSS 4, shadcn/ui | Railway |
| AI Runtime | CopilotKit 1.x | Railway |
| AI Agent | LangGraph.js 1.0 | Railway |
| LLM | OpenAI GPT-4o / GPT-4o-mini | OpenAI API |
| Search | Tavily API | Tavily |
| Database | Neon PostgreSQL + Prisma 7 | Neon |
| Cache | Redis (ioredis) | Upstash |
| Auth | Stack Auth | Stack Auth Cloud |
| Storage | Cloudinary | Cloudinary |
Tip
FanFic Lab uses a unified Railway deployment: Both the Next.js frontend and LangGraph agent run on Railway, communicating via private networking for low latency and no timeout limits.
graph TB
subgraph "Railway (Web Service)"
A[Next.js 16] --> B[React 19]
B --> C[CopilotKit 1.x]
C --> D[API Routes]
D --> E[Prisma 7]
end
subgraph "Railway (Agent Service)"
F[LangGraph.js 1.0] --> G[chat_node]
F --> H[research_node]
F --> I[outline_node]
F --> J[tool_node]
end
subgraph "External Services"
K[OpenAI API]
L[Tavily API]
M[LangSmith]
end
subgraph "Data Layer"
N[Neon PostgreSQL]
O[Redis Cache]
P[Cloudinary]
end
D -->|Private Network| F
G --> K
H --> L
F --> M
E --> N
D --> O
D --> P
The agent uses dedicated graph nodes for HITL operations instead of tools. This is a workaround for the CopilotKit/LangGraph.js ToolMessage format incompatibility.
graph TD
A[START] --> B{routeFromStart}
B -->|Research Request| C[research_node]
B -->|Outline Request| D[outline_node]
B -->|Default| E[chat_node]
C --> F[Tavily Search x4]
F --> G[LLM Aggregation]
G --> H[Emit State with researchData]
H --> I[Return AIMessage]
D --> J[Generate Outline]
J --> K[Set pendingContent]
K --> L[Emit State for HITL]
L --> I
E --> M{Has Tool Call?}
M -->|Yes| N[tool_node]
M -->|No| I
N --> O[Execute Tool]
O --> I
I --> P[END]
sequenceDiagram
participant U as User
participant FE as Frontend
participant CK as CopilotKit
participant Agent as LangGraph Agent
Agent->>CK: copilotkitEmitState(pendingContent)
CK->>FE: State Update
FE->>FE: useCoAgentStateRender detects pendingContent
FE->>U: Render Approval Card
U->>FE: Approve/Edit/Reject
FE->>CK: respond({ data })
CK->>Agent: Continue with user input
Important
Ensure you have the following installed:
- Node.js 20.9.0+ (required by Prisma 7.2.0)
- npm/yarn/pnpm package manager
- Git
- PostgreSQL database (Neon recommended)
- OpenAI API key
1. Clone Repository
git clone https://github.com/ChanMeng666/fanfic-lab.git
cd fanfic-lab2. Install Dependencies
npm install3. Environment Setup
cp .env.example .env.local
# Edit .env.local with your values4. Database Setup
# Generate Prisma client
npx prisma generate
# Run database migrations
npx prisma migrate dev5. Start Development
# Start both Next.js and LangGraph agent
npm run dev:allπ Success! Open http://localhost:3000 to view the application.
npm run dev # Start Next.js dev server only
npm run dev:agent # Start LangGraph agent only
npm run dev:all # Start both services (recommended)
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint# Database (Neon PostgreSQL)
DATABASE_URL=postgresql://user:pass@host.neon.tech/fanficlab?sslmode=require
# Stack Auth
STACK_SECRET_SERVER_KEY=ssk_...
NEXT_PUBLIC_STACK_PROJECT_ID=...
NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=pck_...
# OpenAI (required for AI features)
OPENAI_API_KEY=sk-...
# LangGraph (local development)
LANGGRAPH_URL=http://localhost:8123
# Redis (for research caching)
REDIS_URL=redis://localhost:6379
# Cloudinary (for image hosting)
CLOUDINARY_CLOUD_NAME=...
CLOUDINARY_API_KEY=...
CLOUDINARY_API_SECRET=...
# Optional: Together AI for image generation (currently disabled)
TOGETHER_API_KEY=...
# Optional: LangSmith for tracing
LANGSMITH_API_KEY=lsv2_...
# Optional: Admin endpoint protection
ADMIN_SECRET=...| Variable | Description | Required |
|---|---|---|
DATABASE_URL |
Neon PostgreSQL connection string | β |
STACK_SECRET_SERVER_KEY |
Stack Auth server key | β |
NEXT_PUBLIC_STACK_PROJECT_ID |
Stack Auth project ID | β |
NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY |
Stack Auth client key | β |
LANGGRAPH_URL |
Railway agent URL | β |
OPENAI_API_KEY |
OpenAI API key | β |
REDIS_URL |
Redis connection string | β |
CLOUDINARY_* |
Cloudinary credentials | β |
LANGSMITH_API_KEY |
LangSmith API key | πΆ |
TAVILY_API_KEY |
Tavily API key (Railway) | β |
ADMIN_SECRET |
Admin endpoint protection | πΆ |
β Required, πΆ Optional
erDiagram
User ||--o{ Story : writes
User ||--o{ Character : creates
User ||--o{ Draft : has
User ||--|| UserPreferences : configures
User ||--o{ Follow : follows
Story ||--o{ Chapter : contains
Story ||--o{ StoryCharacter : features
Story ||--o{ Like : receives
Story ||--o{ Comment : has
Character ||--o{ StoryCharacter : appears_in
Story ||--o{ Image : includes
User {
string id PK
string stackAuthId UK
string email UK
string username UK
string displayName
string avatarUrl
string bio
}
Story {
string id PK
string title
string summary
string fandom
string[] ships
string[] tags
enum rating
enum status
int wordCount
string coverImageUrl
}
Character {
string id PK
string name
string fandom
string[] personalityTraits
string speechPatterns
boolean isOriginal
string portraitUrl
}
SourceResearchCache {
string id PK
string sourceName
string sourceType
string normalizedName UK
json researchData
int searchCount
datetime lastAccessedAt
}
fanfic-lab/
βββ src/
β βββ app/ # Next.js App Router
β β βββ api/ # API routes
β β β βββ copilotkit/ # CopilotKit runtime
β β β βββ research-cache/ # Redis caching
β β β βββ health/ # Health check
β β β βββ admin/cache-stats/ # Cache analytics
β β β βββ upload/cover/ # Cover upload
β β βββ (main)/ # Main routes
β β β βββ (protected)/ # Auth required
β β β β βββ editor/ # Smart Editor
β β β β βββ wizard/ # Creative Wizard
β β β β βββ profile/ # User Profile
β β β βββ feed/ # Fandom Feed (public)
β β βββ handler/[...stack]/ # Stack Auth
β β
β βββ components/ # React components
β β βββ ui/ # shadcn/ui components
β β βββ editor/ # Editor components
β β βββ wizard/ # Wizard components
β β βββ feed/ # Feed components
β β βββ hitl/ # HITL approval cards
β β βββ layout/ # Layout components
β β βββ providers/ # Context providers
β β
β βββ agent/ # LangGraph agent
β β βββ agent.ts # Workflow definition
β β βββ state.ts # State annotation
β β βββ tools/ # Agent tools
β β
β βββ lib/ # Utilities
β βββ hooks/ # Custom hooks
β βββ actions/ # Server actions
β βββ types/ # TypeScript types
β βββ db.ts # Database client
β βββ redis.ts # Redis client
β βββ cloudinary.ts # Cloudinary client
β
βββ prisma/
β βββ schema.prisma # Database schema
β βββ migrations/ # Migrations
β
βββ docs/
β βββ COPILOTKIT_LANGGRAPH_HITL_GUIDE.md
β
βββ public/ # Static assets
CopilotKit runtime endpoint that routes requests to the LangGraph agent.
const runtime = new CopilotRuntime({
agents: {
fanfic_agent: new LangGraphAgent({
deploymentUrl: process.env.LANGGRAPH_URL,
graphId: "fanfic_agent",
}),
},
});Research results caching endpoint (Redis).
| Method | Query/Body | Description |
|---|---|---|
| GET | ?sourceName=X&sourceType=Y |
Check if cached research exists |
| POST | { sourceName, sourceType, researchData } |
Save research results (30-day TTL) |
| DELETE | ?sourceName=X |
Clear cache (requires ADMIN_SECRET) |
Service health check endpoint.
{
"status": "healthy",
"services": {
"redis": { "status": "up", "latency": 5 },
"database": { "status": "up", "latency": 12 }
}
}Cover image upload endpoint.
- Validates user authentication and story ownership
- Accepts: jpeg, png, webp (max 5MB)
- Uploads to Cloudinary
- Returns: URL, publicId, dimensions
FanFic Lab runs entirely on Railway with two services communicating via private networking.
Railway Services:
| Service | Config File | Start Command |
|---|---|---|
| Web (Next.js) | railway.json + nixpacks.toml |
npm run start |
| Agent (LangGraph) | railway-agent.json + nixpacks-agent.toml |
npm run start:agent |
| Service | URL |
|---|---|
| Frontend | https://www.fanfic-lab.tech |
| Agent (Internal) | http://fanfic-lab.railway.internal:8123 |
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Railway Project β
β βββββββββββββββββββββββ βββββββββββββββββββββββ β
β β Web Service β β Agent Service β β
β β (Next.js 16) β β (LangGraph.js) β β
β β β β β β
β β β’ React 19 β β β’ chat_node β β
β β β’ CopilotKit 1.x β β β’ research_node β β
β β β’ Prisma 7 β β β’ outline_node β β
β β β’ Stack Auth β β β’ tool_node β β
β ββββββββββββ¬βββββββββββ ββββββββββββ¬βββββββββββ β
β β Private Network β β
β ββββββββββββββ¬ββββββββββββ β
ββββββββββββββββββββββββββββΌβββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββ ββββββββββββ ββββββββββββ
β Neon β β Upstash β βCloudinaryβ
βPostgreSQLβ β Redis β β Images β
ββββββββββββ ββββββββββββ ββββββββββββ
We welcome contributions! Here's how you can help improve FanFic Lab:
1. Fork & Clone
git clone https://github.com/ChanMeng666/fanfic-lab.git
cd fanfic-lab2. Create Branch
git checkout -b feature/your-feature-name3. Make Changes
- Follow our coding standards in CLAUDE.md
- Add tests for new features
- Update documentation as needed
4. Submit PR
- Provide clear description
- Reference related issues
- Ensure CI passes
Chan Meng Creator & Lead Developer |
Chan Meng
LinkedIn: chanmeng666
GitHub: ChanMeng666
Email: chanmeng.dev@gmail.com
Website: chanmeng.live
This project is licensed under the MIT License - see the LICENSE file for details.
Open Source Benefits:
- β Commercial use allowed
- β Modification allowed
- β Distribution allowed
- β Private use allowed