A powerful AI-driven story writing web application built with Express, React, and TypeScript.
The Story Nexus is a local-first web application designed for writers who want to leverage AI to enhance their creative writing process. It provides a comprehensive environment for creating, organizing, and developing stories with the assistance of AI-powered tools. Run it on your local machine or deploy it via Docker to access from any device on your network.
Based on work started by Vijaykumar Bhattacharji; now extensively rewritten, reworked and reimagined.
I wasn't happy with the IndexedDB-based database because I couldn't share data between devices, and I wanted a more robust backend architecture. So I rewrote the backend using Express.js and SQLite with Drizzle ORM.
I didn't like Tauri because I wanted a web app that could run on any device without installing a desktop app, and possibly from a Docker container on my home server. So it was goodbye Tauri.
The code quality has been improved significantly too, and I'm gradually ripping out custom code in favor of established libraries and patterns.
The UI is a writer-first workspace: the manuscript in front, AI machinery behind it.
- Stories, chapters and series: chapters with outlines, POV and summaries; stories grouped into series that share a bible
- Writer-first editor: Lexical-based, autosaving, with AI woven in rather than bolted on
- Scene beats with takes: describe a beat (Alt/Option+S or
/), generate as many takes as you like, flip between them and accept the best — no generation is ever lost - Inline Continue, selection actions and Ask: greyed ghost continuations you keep or dismiss; rework/expand/shorten/free-form instructions on a selection, from the toolbar or the right-click menu
- Story bible: characters, locations, items and more at story, series or global level; extract entries from a chapter, pasted text or the whole story; merge duplicates; continuity checking
- Brainstorm: a critical development-editor chat that has read your story; replies become notes, bible entries or chapter outlines
- Import your manuscript: .txt, .md, .docx or .epub, single or multi-file, with automatic chapter splitting and clean-up of email/usenet headers and Project Gutenberg boilerplate
- AI actions, not prompts: built-in actions with optional per-action overrides (model, sampler settings, template), globally or per story; per-story voice and framing
- Transpose a story: rewrite a copy of a whole story in another time, place or background — brief, synopsis, bible, then each chapter part by part, every layer reviewed before the next
- AI providers: OpenAI, Google Gemini, OpenRouter, or local models (Ollama, LM Studio)
- Local-first: everything lives in a SQLite database on your own machine
- Backend: Express.js, SQLite, Drizzle ORM, better-sqlite3
- Frontend: React, TypeScript, Vite, Tailwind CSS, Shadcn UI
- State Management: TanStack Query v5
- Routing: React Router v7
- Database: SQLite with Drizzle ORM
- Text Editor: Lexical (0.50+)
- UI Components: Shadcn UI, Lucide React icons
- Notifications: React Toastify
- Development: tsx watch (backend), Vite HMR (frontend), concurrently
- Node.js 20+
- npm or yarn
-
Clone the repository
-
Install dependencies:
npm install
-
Start both backend and frontend servers:
npm run dev
This runs both:
- Backend API server on
http://localhost:3001 - Frontend dev server on
http://localhost:5173(with proxy to backend)
- Backend API server on
-
Open
http://localhost:5173in your browser
npm run dev:server # Backend only (Express + SQLite)
npm run dev:client # Frontend only (Vite)-
Build both backend and frontend:
npm run build
-
Start production server:
npm start
App runs on
http://localhost:3000(configurable viaPORTenvironment variable)
npm run db:generate # Generate migration from schema changes
npm run db:migrate # Apply migrations to databasePull and run the latest published image from Docker Hub:
docker-compose up -dSupports linux/amd64, linux/arm64, and linux/arm/v7 architectures.
Access on http://localhost:3000 or from any device on your network using your machine's IP address.
Database persists in ./data/storynexus.db (mounted volume).
Version pinning:
# docker-compose.yml
services:
storynexus:
image: jonsilver/storynexus:0.6.0 # Pin to specific version
# or: jonsilver/storynexus:0.6 # Auto-update patches
# or: jonsilver/storynexus:latest # Latest releaseBuild and run from source:
docker-compose -f docker-compose.dev.yml up --buildNew releases are published via GitHub Releases, which automatically builds and pushes multi-architecture Docker images to Docker Hub.
Creating a release:
Using the PowerShell script (Windows):
.\release.ps1 patch # 0.6.0 → 0.6.1
.\release.ps1 minor # 0.6.0 → 0.7.0
.\release.ps1 major # 0.6.0 → 1.0.0The script automatically bumps the version, pushes to GitHub, and opens the release page in your browser.
Manual process:
- Bump version:
npm version <patch|minor|major> - Push:
git push && git push --tags - Create GitHub release from the tag (via GitHub UI)
Result - Workflow automatically builds and pushes Docker images with tags:
jonsilver/storynexus:0.7.0(specific version)jonsilver/storynexus:0.7(minor version)jonsilver/storynexus:0(major version)jonsilver/storynexus:latestjonsilver/storynexus:sha-abc1234(commit hash)
Note: Docker images are only built on releases, not on every commit to main.
server/- Express.js API serverdb/- Database schema, client, migrations, and seedingroutes/- API route handlers (stories, chapters, series, lorebook, notes, brainstorm, ai, actions, generate, ingest, assets, admin)services/- Action registry and context assembly, AI providers, manuscript ingest, backupsindex.ts- Server entry point
src/v2/- The app: shell, screens, editor (Lexical composition, nodes, plugins), AI actions, bible flows, exportsrc/features/- TanStack Query hooks per domain, plus the settings, series, guide and reader pagessrc/components/- Shared UI components (Shadcn)src/services/- API client and AI settings facadesrc/types/- TypeScript type definitionssrc/lib/- Utility functions and helpers
Settings → Backup → Download backup produces a consistent snapshot of the entire database using SQLite's online backup API — safe to take while you're writing. Images live separately under data/assets/; copy that directory too. Don't copy storynexus.db on its own while the app is running: the database runs in WAL mode and recent writing may only exist in storynexus.db-wal.
Story → Export → JSON (backup) downloads one story with its chapters, story bible, notes, brainstorm chats, per-story AI overrides, images and any transposition in progress. Restore it from Story → Switch story → JSON; it comes back as a new story titled "… (Imported)", restored all-or-nothing. To copy a story without the round trip, Story → Duplicate this story… makes the same copy in one step and keeps it in the story's series.
Settings → Series exports and imports a whole series: its series-level bible plus a complete backup of every story in it.
- Replace the component-based guide with markdown-driven documentation presented by a small set of components.






