Stack: React 18 ยท Vite ยท TipTap ยท dnd-kit ยท Tailwind CSS ยท Supabase ยท Vercel
A polished, production-grade novel writing application. Manage multiple novel projects, write with a rich text editor, plan scenes on a corkboard, export your manuscript, and sync everything to the cloud.
See it in action here: https://chapterflow-liard.vercel.app/
- Authentication โ Email/password sign up, login, and password reset via Supabase Auth
- Cloud Sync โ All projects, chapters, and scenes sync to Supabase with a 1-second debounced autosave
- Project Management โ Create and manage multiple novel projects with title, author, genre, synopsis, and accent color
- Chapter Management โ Add, edit, delete, and drag-to-reorder chapters
- Rich Text Editor โ TipTap-powered editor with formatting toolbar (bold, italic, headings, lists, blockquote, alignment, highlight)
- Notes Panel โ Per-chapter notes/outline panel that slides in alongside the editor
- Word Count Tracking โ Live word count, reading time estimate, per-chapter and per-project totals
- Scene Board โ Drag-and-drop scene cards per chapter (like Scrivener's corkboard)
- Export โ PDF (with title page, TOC, page numbers), HTML/Word, and Plain Text
- Autosave โ Persists to both localStorage (fast) and Supabase (cloud)
- Search & Filter โ Search chapter content/notes, filter by status
- Dark Mode โ Full dark/light mode toggle
- Responsive โ Collapsible sidebar, mobile-friendly layout
git clone https://github.com/your-username/chapterflow.git
cd chapterflow
npm installIn your Supabase project, go to SQL Editor and run:
-- PROJECTS
create table public.projects (
id uuid primary key,
user_id uuid references auth.users not null,
title text not null,
author text,
genre text,
synopsis text,
cover_color text default '#d4a853',
created_at timestamptz default now(),
updated_at timestamptz default now()
);
-- CHAPTERS
create table public.chapters (
id uuid primary key,
project_id uuid references public.projects(id) on delete cascade,
user_id uuid references auth.users not null,
title text not null,
content text,
notes text,
status text default 'draft',
word_count integer default 0,
"order" integer default 0,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
-- SCENES
create table public.scenes (
id uuid primary key,
chapter_id uuid references public.chapters(id) on delete cascade,
user_id uuid references auth.users not null,
title text not null,
description text,
color text,
"order" integer default 0
);
-- Row Level Security
alter table public.projects enable row level security;
alter table public.chapters enable row level security;
alter table public.scenes enable row level security;
create policy "Users manage own projects"
on public.projects for all using (auth.uid() = user_id);
create policy "Users manage own chapters"
on public.chapters for all using (auth.uid() = user_id);
create policy "Users manage own scenes"
on public.scenes for all using (auth.uid() = user_id);Then go to Authentication โ URL Configuration and add your allowed redirect URLs:
http://localhost:5173(development)https://your-app.vercel.app(production)
Create a .env.local file in the project root (never commit this):
VITE_SUPABASE_URL=https://your-project-id.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key-hereGet these values from your Supabase dashboard under Settings โ API.
npm run devOpen http://localhost:5173.
- Push your repo to GitHub
- Import the project in Vercel
- Go to Project Settings โ Environment Variables and add:
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY- Set both for Production, Preview, and Development
- Deploy โ Vercel auto-deploys on every push to
main
Vite environment variables must be prefixed with
VITE_to be available in the browser bundle.
| Layer | Technology |
|---|---|
| Framework | React 18 + Vite |
| Auth & Database | Supabase |
| State | React Context + useReducer |
| Rich Text | TipTap 2 |
| Drag & Drop | @dnd-kit |
| Styling | Tailwind CSS |
| Icons | Lucide React |
| Export (PDF) | jsPDF |
| Local Persistence | localStorage |
| Fonts | Playfair Display, Crimson Text, Courier Prime |
| Hosting | Vercel |
chapterflow/
โโโ .env.local # Your Supabase keys (never commit)
โโโ index.html
โโโ vite.config.js
โโโ tailwind.config.js
โโโ src/
โโโ App.jsx # Root component, auth gate, sync wiring
โโโ main.jsx
โโโ index.css # Global styles + TipTap styles
โโโ lib/
โ โโโ supabase.js # Supabase client instance
โโโ context/
โ โโโ AppContext.jsx # Global state (projects, user, UI)
โโโ hooks/
โ โโโ useSupabaseSync.js # Load from + debounced save to Supabase
โโโ utils/
โ โโโ wordCount.js # Word counting & text utilities
โ โโโ exportUtils.js # PDF, HTML, TXT export logic
โโโ components/
โโโ Auth/
โ โโโ AuthScreen.jsx # Login, signup, password reset UI
โโโ Layout/
โ โโโ Sidebar.jsx # Navigation sidebar with sign out
โ โโโ Header.jsx # Breadcrumb & autosave indicator
โโโ Projects/
โ โโโ ProjectDashboard.jsx
โ โโโ ProjectCard.jsx
โ โโโ CreateProjectModal.jsx
โโโ Chapters/
โ โโโ ChapterList.jsx # Sortable chapter list
โ โโโ ChapterItem.jsx # Draggable chapter row
โ โโโ ChapterEditor.jsx # Editor + notes panel
โโโ Editor/
โ โโโ RichTextEditor.jsx # TipTap editor with toolbar
โโโ Scenes/
โ โโโ SceneBoard.jsx # Corkboard scene card organizer
โโโ Export/
โ โโโ ExportModal.jsx # PDF / HTML / TXT export
โโโ UI/
โโโ Button.jsx
โโโ Modal.jsx
โโโ Badge.jsx
โโโ SearchBar.jsx
โโโ Notifications.jsx
Project {
id, title, author, genre, synopsis, coverColor,
chapters: Chapter[],
createdAt, updatedAt
}
Chapter {
id, title, content (HTML), notes (HTML),
status, wordCount, order,
scenes: Scene[],
createdAt, updatedAt
}
Scene {
id, title, description, color, order
}
Data is stored in Supabase (source of truth) and mirrored to localStorage for fast initial load and offline resilience.
- User lands on app โ
supabase.auth.getSession()checks for an existing session - No session โ
AuthScreenrenders (login / signup / reset) - On login โ session stored by Supabase client automatically
onAuthStateChangelistener keeps the app in sync with token refresh and sign out- On sign out โ state cleared, user returned to
AuthScreen
The app uses a Literary Noir aesthetic โ deep slate backgrounds, warm amber accents, Playfair Display headings, and Crimson Text for body content. The full editor experience is distraction-free with an optional slide-in notes panel.
- Deletion sync to Supabase (currently handled locally only)
- Version snapshots / chapter history with rollback
- AI writing suggestions
- Collaboration / shared projects
- PWA offline support
- DOCX export
- Chapter templates
MIT