Project Info
Project Story
Inspiration
We didn't start with a noble idea about education. We started with a confession. One of us had a shelf. Real books, bought with real intent, all of them stopped somewhere around page 40. The other had a screen-time report that said four hours a day on reels. Same person, roughly. Same evening, usually. The book lost every single night — not because it was worse, but because it asked for something the phone never asks for: a running start. Reading is a cold engine. You have to rebuild the world in your head every time you open the cover — who these people are, where we left off, why any of it matters. Reels ask for nothing. You arrive mid-thought, you're already inside, and the next one is already loading. It isn't a discipline problem. It's an interface problem. One medium front-loads all the cost and back-loads all the payoff, and the other does the exact opposite. Then we noticed the thing we both actually did finish: manga. Hundreds of pages, in one sitting, no willpower involved. Manga is not a lighter version of a book. It's a book that solved the cold-start problem — panels give you the world instantly, faces carry the emotion, and your eye pulls you down the page faster than you decided to go. We had never once "tried" to read manga. We just read it. So the question stopped being how do we make people read more and became something much more fun: What if the book you never finished came to you as the thing you always finish? That's ScrollStack. You hand it a PDF — a novel, a biography, a dense thing your friend keeps recommending — and it comes back as a manga edition you can actually sit and read. Chapters, recurring characters that look like themselves on page 3 and page 30, panels that hold a beat, pages that turn. And the parts that hit hardest get cut into short vertical reels, so the same scroll reflex that used to cost you an evening now spends it on something that stays with you. We were deliberate about one thing: this is not a study tool. No quizzes, no streaks, no progress bar guilting you. It's entertainment that happens to be made of good books. If it feels like homework, we built the wrong thing.
What it does
You give ScrollStack a book and choose how much of it you want. It produces a manga edition — ordered, composed, lettered pages you read like any manga — and stores it in your library so you can reopen it, keep going, or ask for more. Under the surface the product runs one honest pipeline: The surfaces a reader actually touches: /books/new — drop in a PDF, watch the stages move. /library — every manga edition you've made, reopenable. /manga/{edition} — the reader itself. Reels — vertical cuts derived from the manga you already accepted, played through a real Remotion player and exportable as deterministic H.264/AAC MP4. Two product rules we refused to bend: Source-grounded, not vibes-grounded. Every panel traces back to specific source units in the actual PDF. The system holds a versioned context pack so a character can't quietly become someone else forty pages later. Editions are immutable. When you accept an edition, it's frozen — pages, panel images, hashes, lineage, accepted and rejected attempts, and the exact cost. What you read today is byte-identical to what you read next month.
How we built it
Shape of the system. A FastAPI + Pydantic control plane owns truth and contracts. MongoDB (via Beanie) owns durable state — projects, runs, artifacts, memory. Celery + Redis own the workflow and retry lifecycle, because a manga run is a long chain of steps where any one of them can fail and none of them should take the whole run down. The frontend is Next.js 15 / React 19 with Tailwind and shared design tokens. Deterministic video is Remotion, run headless in a dedicated renderer package. One seam, generated in both directions. The single cross-language boundary is packages/contracts/. Pydantic models are canonical; JSON Schema and TypeScript types are generated from them and committed with the source change. Generated files are never hand-edited. That one rule is why two people could build the manga lane and the reel lane in parallel worktrees without a week of integration pain — the reel player consumed manga-manifest.v1 and reel-spec.v1 off fixtures long before the backend could emit real ones. Three boundaries carry the whole product: Determinism as a feature, not a nicety. Generation is expensive and non-deterministic; reading must not be. So the model touches the run only inside bounded creative sessions, and everything downstream — composition, lettering, page assembly, reel rendering — is deterministic given accepted artifacts. Re-run a run ID and you get the same pages back, no new spend. Cost as a first-class model. Image generation dominates. If a page holds $n_p$ panels and $r$ is the fraction of attempts we reject on quality, the expected image spend for a $P$-page edition is $$ C \;=\; c_{\text{img}} \sum_{p=1}^{P} \frac{n_p}{1 - r} $$ which makes the two levers obvious: cut panels per page, or cut the rejection rate. Rejections are the silent budget killer — in our demo edition, accepted panels cost \( \$0.4319757 \) while total image spend including three rejected attempts was \( \$0.549321 \). That's \( \approx 21\% \) burned on output nobody ever sees. Every rejected attempt is stored with its receipt precisely so that number stays visible instead of hiding inside a total. The demo edition, honestly. For the hackathon slice we ran pages 1–15 of a real PDF through the pipeline with zero new text-model calls — reusing an accepted context pack — producing an immutable edition of five composed 1200×1800 pages from ten accepted panel images, one accepted character reference, and full lineage. One rejected panel was retried once; no accepted panel was ever regenerated. How the two of us worked. Hard ownership lines, written down before any code: one lane owns the backend, contracts, manga surfaces, and the shared visual system; the other owns the Remotion renderer, reel components, and reel routes. Separate git worktrees driven by separate Codex sessions, PR-only into a shared dev, and a standing rule that no PR is complete without its contract fixture and visual evidence. Every handoff in NEXT_SESSION.md states what passed, what's still broken, and who moves next. The full agent workflow is documented in CODEX_USAGE.md.
Challenges we ran into
Character continuity is the whole ballgame. A model asked twice for "the same person" gives you two people. Manga dies instantly if the protagonist's face drifts between pages — the reader doesn't consciously notice, they just stop believing it. We solved it by treating a character as an accepted, hashed reference artifact that every later panel is anchored to, rather than as a sentence in a prompt. Text inside generated images. We explicitly instructed no embedded text and got back a panel with an English heading burned into the artwork, plus pseudo-lettering scribbled around the speech balloons. That output was technically a beautiful monochrome manga render and we rejected it anyway, because lettering has to come from the deterministic renderer or it can never be edited, translated, or trusted. We still ship a known limitation here: OCR finds no letters in accepted image layers, but some accepted panels contain empty balloon shapes the model drew unprompted. Real words are renderer output; those hollow shapes are on the list. Front matter is not a story. Our parser stores one source unit per PDF page, and the first fifteen pages of a real book are title pages, copyright, and a table of contents. Source-correct, dramatically worthless. It taught us that selection — which part of the book — is a product decision, not a preprocessing detail. Latency vs. iteration speed. Mid-build, the text model was slow enough that a single full run ate the feedback loop. Rather than fake it, we cut scope on purpose: prioritize a small page range, reuse accepted upstream artifacts, spend zero new text tokens, and get something real on screen. Constrain the run, not the honesty. Two people, one repo, no stomping. Avoided almost entirely by the generated contract seam and worktree isolation. The one place we did collide was NEXT_SESSION.md — and since each lane appended its own dated section, even that merged cleanly. Infrastructure honesty. A Mongo 7 archive is currently being served by Mongo 8.2.3. It works. We wrote the cross-major restore warning into the handoff anyway, because a demo that succeeds doesn't retroactively make the setup correct.
Accomplishments we're proud of
A real, immutable manga edition generated from a real PDF — five composed pages, ten accepted panels, complete hashes, lineage, receipts, and exact cost. A single generated contract seam that let two people build in parallel from day one and merge additively, with no breaking contract change to date. Determinism end to end — the same run ID reproduces the same pages, and ReelSpec drives both the live player and the exported MP4 from one source. Rejections are visible. Failed attempts and their costs are stored, not swallowed. We can tell you exactly what the waste was. We shipped what actually worked. Nothing is marked complete without its fixture and visual evidence — a rule we enforced against ourselves more than once.
What we learned
The bottleneck was never comprehension — it was cold start. Books ask you to rebuild a world before they give you anything. Panels hand you the world free. That one asymmetry explains the entire shelf of unfinished books. Consistency beats beauty. A merely-good panel of a character who looks right lands harder than a gorgeous panel of a stranger. Readers forgive rough art; they do not forgive a face that changed. Push non-determinism to the edges. Let the model be creative inside bounded sessions, then make every downstream step deterministic. It's the difference between a demo and a product. Generated contracts are a collaboration technology. They weren't a typing convenience — they were the reason two lanes never blocked each other. Cutting scope honestly beats faking scope. "Pages 1–15, zero new text calls, here's the receipt" got us further than a broad claim we couldn't stand behind.
What's next
for ScrollStack Kill the empty balloons and finish the lettering pass so every visible word is deterministic renderer output. Smarter source selection — skip front matter, find the scenes worth drawing instead of walking the PDF linearly. The full reel loop in production, with signed media delivery, thumbnails, and persisted render receipts. Reader-side continuity — progress that survives a reload, a library that remembers where the good part was. Director's cut. Let a reader reorder panels, retitle a chapter, add a line of commentary, and share their own edition of a book. The scroll becomes authorship. Cost transparency for readers — show what an edition cost to make. Nobody else does this. We think people would rather know.
ScrollStack
ScrollStack turns a selected part of a book into a source-grounded manga, then derives short vertical reels from the accepted manga. The product is designed as entertainment-first media: readers see chapters, characters, continuity, and cuts rather than internal generation terminology.
Architecture
The implementation follows technical-imp.md:
PDF and selected source units
-> versioned context pack
-> typed manga direction and composition artifacts
-> RenderedPage and MangaManifest
-> ReelSpec
-> deterministic manga and Remotion renderers
- MongoDB owns durable project, memory, run, and artifact truth.
- Celery owns the workflow and retry lifecycle.
- Pi runs bounded creative sessions behind one internal adapter.
- Pydantic models generate JSON Schema and TypeScript contracts.
RenderedPageis the manga reader boundary.MangaManifestis the manga-to-reel handoff.ReelSpecdrives both live playback and deterministic export.
Architecture decisions live in docs/adr/.
Repository lanes
- Mrigesh owns
backend/, canonical contracts and fixtures, manga surfaces, global styling, root workspace configuration, and the shared visual system. - Utkarsh owns
reel-renderer/,packages/reel-components/, reel routes, andfrontend/components/ReelFeed/.
See AGENTS.md before changing shared paths.
Local development
Requirements:
- Node.js 22.19 or later
- pnpm 10.15.1 through Corepack
- Python 3.12 and
uv - Docker with Compose
zshfor thestart.shandstop.shhelper scripts- Chromium and FFmpeg/ffprobe for local Remotion export smoke tests
Install JavaScript dependencies once:
corepack enable
corepack prepare pnpm@10.15.1 --activate
corepack pnpm install
Full Docker stack
Run the local app stack:
cp .env.example .env
./start.sh
./start.sh creates .env from .env.example if it is missing, then runs:
docker compose --profile agent up -d
The core services expose:
- Frontend:
http://localhost:3000 - Backend:
http://localhost:8000 - MongoDB:
mongodb://localhost:27017 - Redis:
redis://localhost:6379
Stop the stack with:
./stop.sh
The agent profile is enabled by start.sh. The reels Compose profile is
reserved for the render-worker container; it should not be treated as ready
until reel-renderer/Dockerfile exists.
Important local flags in .env.example:
AGENTIC_MANGA_PIPELINE_V1=true
REELS_ENABLED=false
REEL_EXPORT_ENABLED=false
Reel playback/export is disabled by default for the full app until the backend
produces accepted MangaManifest and ReelSpec records.
Frontend-only development
Use this when working on UI against the configured backend URL:
corepack pnpm --filter @scrollstack/frontend dev
Reel fixture export
The reel renderer can export the committed preview fixture without a backend. Use absolute output paths:
SCROLLSTACK_BROWSER_EXECUTABLE=/usr/bin/chromium \
corepack pnpm --filter @scrollstack/reel-renderer render -- --still --frame 0 --out /tmp/scrollstack-reel.png
SCROLLSTACK_BROWSER_EXECUTABLE=/usr/bin/chromium \
corepack pnpm --filter @scrollstack/reel-renderer render -- --out /tmp/scrollstack-reel.mp4
SCROLLSTACK_BROWSER_EXECUTABLE is optional if Remotion can find a supported
browser automatically. ffprobe must be available on PATH for media
verification.
Verification
corepack pnpm check
docker compose --env-file .env.example config --quiet
zsh -n start.sh
zsh -n stop.sh
git diff --check
Lane-specific checks:
(cd backend && uv run pytest tests/ -q)
corepack pnpm --filter @scrollstack/frontend typecheck
corepack pnpm --filter @scrollstack/frontend build
corepack pnpm --filter @scrollstack/reel-renderer typecheck
corepack pnpm --filter @scrollstack/reel-renderer test
AI-assisted engineering provenance
ScrollStack was built with OpenAI Codex and GPT-5.6 used as engineering assistants during planning, implementation, review, and documentation. Their role was to accelerate repository setup, coordinate the two-contributor work split, draft implementation plans, inspect diffs, and produce scoped code changes under human direction.
The project keeps AI assistance separate from product runtime behavior:
- Codex helped maintain the collaboration guide in
AGENTS.md, plan ownership boundaries, and keep Mrigesh's core/manga lane separate from Utkarsh's reel-rendering lane. - GPT-5.6-assisted coding was used for targeted implementation work such as contract-aware reel playback, deterministic Remotion rendering, progress integration, tests, and handoff notes.
- Runtime creative generation is intentionally constrained by typed artifacts.
Models may propose manga or reel data, but the application accepts only
schema-validated outputs such as
RenderedPage,MangaManifest, andReelSpec. - Deterministic renderers, tests, and visual evidence are used to verify the accepted artifacts instead of trusting model output directly.
Human contributors remain responsible for product decisions, final code review, accepted contracts, submitted PRs, and release readiness. Commit history, PR descriptions, test output, and evidence files are the source of truth for what was implemented and validated.
Build Week notes
ScrollStack is a new repository created for OpenAI Build Week. Before submission this section should include the primary feedback session ID, golden demo source license, exact setup instructions, and final validation evidence.
Analysis
View
Metric
- 27
- 14
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- FastAPIIn code
- JavaScriptIn code
- Next.jsIn code
- PythonIn code
- ReactIn code
- Tailwind CSSIn code
- TypeScriptIn code
8 of 8 appear in the indexed code.
AI coding agents
- CodexConfig
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
1.8 MB
Source files
272
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
Legend101Zz/ScrollStack
404 files · 42.9 MB · @ 562ebdc
Structure
Interface
86 files · 21%Screens, components and styles rendered to the user.
API & routing
9 files · 2%Request entry points: routes, handlers and controllers.
Application logic
97 files · 24%Domain rules, services and shared utilities.
+5 moreBackground jobs
4 files · 1%Work run outside a request: tasks, workers and schedules.
Data & schema
30 files · 7%Schema definitions, migrations and data access.
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python36%
- TypeScript34%
- YAML16%
- Markdown14%
- CSS0%
- Shell0%
- Other (1)0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
frontend/package.json
npm · 22- @phosphor-icons/react
- @radix-ui/react-slot
- @radix-ui/react-toggle-group
- @remotion/player
- @remotion/preload
- @scrollstack/contracts
- @scrollstack/design-tokens
- @scrollstack/reel-components
- motion
- next
- react
- react-dom
- zustand
- +9 more
packages/reel-components/package.json
npm · 12- @remotion/media
- @scrollstack/contracts
- @scrollstack/design-tokens
- remotion
- +8 more
reel-renderer/package.json
npm · 12- @remotion/bundler
- @remotion/renderer
- @scrollstack/reel-components
- react
- react-dom
- remotion
- +6 more
apps/agent-worker/package.json
npm · 8- @scrollstack/agent-runtime
- @scrollstack/contracts
- @sinclair/typebox
- fastify
- +4 more
backend/pyproject.toml
pypi · 8- beanie
- celery[redis]
- fastapi
- httpx
- pydantic
- pymupdf
- python-multipart
- uvicorn[standard]
packages/agent-runtime/package.json
npm · 6- @earendil-works/pi-coding-agent
- @scrollstack/contracts
- typebox
- +3 more
packages/contracts/package.json
npm · 6- ajv
- ajv-formats
- +4 more
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.