- System Overview
- Installation
- Pipeline Workflow
- Node UI Guide
- Notebook Editor
- AI Agents
- API Reference
ScriptED is an AI-powered screenplay enhancement tool that uses a 3-stage pipeline:
- STAGE 1: Upload & Parse - Convert messy text into Hollywood format
- STAGE 2: Analyze & Review - Add sentiment analysis, review in notebook
- STAGE 3: AI Enhancement - Use specialized agents to enhance specific elements
- LLM: Local Llama-3.1-8b running on CPU (fully offline)
- Vector DB: ChromaDB for semantic search
- Sentiment Analysis: DistilBERT
- NLP: spaCy for text processing
- Frontend: Next.js 16 with Framer Motion
- Backend: FastAPI with Python 3.13
- Python 3.10+
- Node.js 18+
- 4GB RAM minimum
- Windows 10/11 (or WSL2)
# Navigate to backend
cd backend
# Create virtual environment
python -m venv venv
# Activate
.\venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Download spaCy model
python -m spacy download en_core_web_sm
# Test backend
python main.pyExpected Output:
π Booting up ScriptED Backend (Local Mode)...
Loading spaCy NLP engine...
Loading local ChromaDB Client...
Loading DistilBERT Sentiment Analyzer...
Loading Local LLM Model...
INFO: Uvicorn running on http://127.0.0.1:8080
# Navigate to frontend
cd scripted
# Install dependencies
npm install
# Run development server
npm run devExpected Output:
β² Next.js 16.1.6
- Local: http://localhost:3000
- Turbopack: β Enabled
Open browser: http://localhost:3000/pipeline
You should see a single blue node labeled "Upload Script".
Option A: Text Input
- Click the blue "Upload Script" node
- Paste screenplay text:
INT. SUBWAY CAR - MIDNIGHT The fluorescent lights flicker wildly, casting eerie shadows on the walls. ELIAS sits in the corner, clutching a black briefcase to his chest. He's sweating profusely and scanning the car nervously. MARA walks down the aisle and sits beside him. MARA Why are you sweating so much, Elias? ELIAS I think they're following us. They know about the drive. - Click "Process Script"
Option B: File Upload
- Click "Upload File (PDF, DOCX, TXT)"
- Select your screenplay file
- Click "Process Script"
What Happens:
- Local LLM cleans and formats the text
- Parser extracts scenes, dialogues, and actions
- ChromaDB creates vector embeddings
- Sentiment analysis adds emotion tags
- New "Stage 1: Parse" node appears
- Click the Purple "Stage 1: Parse" node
- Notebook UI opens with two panels:
- Left Panel: Formatted preview
- Right Panel: Editable JSON
- Edit the JSON if needed:
- Fix character names
- Adjust scene headings
- Modify dialogue
- Click "Save Changes"
- Click "Download" to export
JSON Structure:
{
"scenes": [
{
"scene_id": 1,
"location": "INT. SUBWAY CAR",
"time": "MIDNIGHT",
"actions": [
"The fluorescent lights flicker wildly..."
],
"dialogues": [
{
"character": "MARA",
"text": "Why are you sweating so much, Elias?",
"emotion": "NEGATIVE"
}
],
"pacing": "Character-Driven / Dialogue-Heavy"
}
],
"metadata": {
"total_word_count": 87
}
}Use the API to enhance specific elements:
# Example: Rewrite dialogue as comedy
curl -X POST http://localhost:8080/api/v1/pipeline/stage3-agent-handoff `
-H "Content-Type: application/x-www-form-urlencoded" `
-d "session_id=session_123&persona=writer_comedy"
# Example: Add horror atmosphere
curl -X POST http://localhost:8080/api/v1/pipeline/stage3-agent-handoff `
-H "Content-Type: application/x-www-form-urlencoded" `
-d "session_id=session_123&persona=director_horror&user_feedback=Make it terrifying"
# Note: All processing happens locally on your machine| Color | Stage | Description |
|---|---|---|
| π΅ Blue | Upload | File/text input |
| π£ Purple | Stage 1 | Parsing complete |
| π‘ Pink | Stage 2 | Analysis complete |
| π Orange | Stage 3 | AI enhancement |
| π’ Green | Final | Output ready |
Hover on Node β See 3 buttons:
- Green +: Add child node (next stage)
- Red Γ: Delete node + children
- Blue "Connect": Link to another node
Click Node β Opens Notebook UI (if data available)
Drag Node β Move anywhere on canvas
- Click "Connect" button on source node
- Click on target node
- Purple dashed line appears
- Target node becomes child of source
- Bottom Right β Trash icon with counter
- Click β See deleted nodes
- Click "Restore" β Bring back node (if parent exists)
+------------------+------------------+
| Preview Panel | Edit Panel |
| (Formatted) | (JSON Editor) |
+------------------+------------------+
| Metadata Bar |
+-------------------------------------+
-
Preview Panel:
- Shows formatted screenplay
- Scene headings in bold
- Character names in CAPS
- Actions in regular text
-
Edit Panel:
- Editable JSON
- Syntax highlighting
- Auto-validation
-
Toolbar:
- Back to Pipeline: Return to node view
- Save Changes: Update session
- Download: Export JSON
-
Metadata:
- Session ID
- Scene count
- Word count
- Processing status
Transforms: Serious β Sarcastic & Witty
Before: "We need to leave now."
After: "Oh sure, let's just casually waltz out the door with half the city's goons on our tail. Great plan, Einstein."
Transforms: Modern β 1940s Hardboiled
Before: "I don't trust you."
After: "You're trouble, doll. The kind that wears lipstick and leaves a trail of broken hearts."
Adds: Subtext & Hidden Motivations
Before: "I'm fine."
After: "I'm fine. (beat) Though 'fine' is what you say when the truth would crack you open."
Adds: Dynamic Camera Moves
Before: "He runs down the hallway."
After: "WHIP PAN - He EXPLODES down the hallway, camera TRACKING at dutch angle, fluorescent lights STROBING overhead."
Adds: Dread & Suspense
Before: "She walks into the room."
After: "She crosses the threshold. The door creaks shut behind her. In the corner, something shifts in the shadows."
Adds: Lens & Lighting Details
Before: "They sit at the table."
After: "85mm lens, f/2.8. Chiaroscuro lighting carves their faces in half. The table sits in a pool of amber tungsten."
Adds: Production Design
Before: "A messy apartment."
After: "The apartment reeks of stale cigarettes. Peeling wallpaper. A vintage rotary phone on a water-stained side table. Dust motes swim in slatted light."
Adds: Auditory Details
Before: "The train stops."
After: "The train SCREECHES to a halt, metal-on-metal SCREAMING. Low-frequency rumble fades. Distant drip. Eerie silence."
Provides: Pacing Critique
Output: "Scene drags in Act 2. Stakes unclear. Protagonist passive. CUT 30 seconds or add conflict beat."
Finds: Logic Errors
Output: "Timeline issue: Character mentions 'tomorrow' but next scene shows '3 days later'. Spatial error: Gun disappears from table between cuts."
# Rewrite all dialogue as noir
curl -X POST http://localhost:8080/api/v1/pipeline/stage3-agent-handoff \
-d "session_id=session_123" \
-d "persona=writer_noir"
# Add horror atmosphere with custom feedback
curl -X POST http://localhost:8080/api/v1/pipeline/stage3-agent-handoff \
-d "session_id=session_123" \
-d "persona=director_horror" \
-d "user_feedback=Focus on psychological terror, not jump scares"http://localhost:8080/api/v1
GET /healthResponse:
{
"status": "healthy",
"model": "llama-3.1-8b-local",
"local_llm_loaded": true,
"spacy_loaded": true,
"sentiment_loaded": true
}POST /upload-script
Content-Type: multipart/form-data
file: <PDF/DOCX/TXT>
session_id: "session_123"POST /process-text
Content-Type: application/x-www-form-urlencoded
raw_text: "INT. SUBWAY CAR - MIDNIGHT..."
session_id: "session_123"POST /pipeline/stage3-agent-handoff
Content-Type: application/x-www-form-urlencoded
session_id: "session_123"
persona: "writer_comedy"
user_feedback: "Make it funnier!" (optional)GET /session/{session_id}| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad Request (invalid persona, missing fields) |
| 404 | Session Not Found |
| 500 | Server Error (LLM failure, parsing error) |
- Use proper scene headings:
INT. LOCATION - TIME - Character names in ALL CAPS on separate line
- One blank line between paragraphs
- Use unique session IDs
- Sessions are in-memory (restart clears them)
- Download JSON after each stage
- Start with one agent per session
- Review output before applying next agent
- Use
user_feedbackfor specific requests
- Files > 10MB may be slow
- Use text input for faster processing
- All processing happens locally (no internet required)
Error: ModuleNotFoundError: No module named 'transformers'
pip install -r requirements.txtError: Can't find model 'en_core_web_sm'
python -m spacy download en_core_web_smError: Module not found: Can't resolve '@/lib/api'
npm installError: 404 Session Not Found
- Check session ID is correct
- Restart backend (sessions are in-memory)
Error: 500 LLM Loading Error
- Ensure you have at least 8GB RAM free
- Local LLM model takes 30-60 seconds to load on first run
Problem: Nodes not draggable
- Refresh page
- Clear localStorage:
localStorage.clear()in console