Open-source project
openstory-so/openstory avatar
openstory-so/openstory

OpenStory and a script-to-video pipeline built on the Cloudflare stack

Open-source AI-powered video sequence platform built with TanStack Start

687 stars109 forksTypeScriptMIT

At a glance

What is it?
OpenStory is an open-source platform that turns a script into a sequence of AI-generated frames with consistent styling, built on TanStack Start and deployed to Cloudflare Workers. Its most interesting engineering decision is that the entire platform, database, storage, workflows and email, runs locally inside Workerd with no Cloudflare account required.
Who is it for?
OpenStory is a good fit for a small team that wants to produce short stylised video from a written script without a pipeline of their own, since the platform handles the scene breakdown, the prompt engineering, the generation calls and the compositing, and it ships a Deploy to Cloudflare button.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the platform actually does with a script

OpenStory takes a script and produces a sequence of AI-generated frames, images, motion video and audio, with consistent style across every scene. The stated line is that teams collaborate on shared libraries of characters, locations and visual styles, and the platform handles the heavy lifting of prompt engineering, generation and compositing.

The feature list breaks that down into concrete stages.

Script analysis takes a pasted script and produces an automatic scene breakdown with camera angles, mood treatments and continuity tracking. That is the step that turns prose into a production plan, and continuity tracking is the part that matters most for the output looking coherent, since a scene that ignores what happened two scenes earlier is the usual failure of naive image generation pipelines.

AI image generation runs through Fal.ai with multiple model options. Image-to-video motion turns still frames into motion video clips. Style consistency means characters, locations, colour palettes and lighting carry across scenes automatically, which is the whole reason a platform like this exists rather than a script that calls an image API per prompt.

Publishing to social is optional and works with your own Upload-Post key, posting a finished render to TikTok, Instagram, YouTube, LinkedIn, X and more. That design choice is notable: the distribution step is delegated to a third-party service you authenticate yourself, rather than implemented as a set of platform integrations.

The audience is a team making short stylised video, and the audience for the workspace feature, shared libraries of styles, characters, VFX and audio, is marked as coming soon.

One command to get the whole stack running locally

The prerequisites are unusually short. The only requirement is Bun 1.3.9 or later, and the README is emphatic about what is not needed: no Docker, no external database, no Cloudflare account, because local dev runs the full stack, including D1, R2, Workflows, Durable Objects and email, inside Workerd via Miniflare.

The quick start is three commands:

bash
git clone https://github.com/openstory-so/openstory.git
cd openstory
bun install
bun dev

And then the application is at http://localhost:3000.

What bun dev does is the part worth knowing. It generates .env.local with auth and encryption secrets on first run, it migrates and seeds the local database, and it starts the dev server. So the difference between a fresh clone and a running application is one command, and the database is not something you have to set up first.

The AI features need two API keys. You can add them interactively with bun setup, or paste them into .env.local: FAL_KEY for fal.ai, used for image, video and audio generation, and OPENROUTER_KEY for OpenRouter, used for LLM script analysis.

That is a real constraint worth noting before you start. Script analysis and generation are two separate paid services, and the platform is a front end for them rather than a model of its own.

The conditional import map is how one codebase runs in three places

The package.json is where the architecture becomes clear, and the interesting part is the imports field, which maps module specifiers to different files depending on the environment.

There are five conditional groups. The #env specifier points at a Cloudflare environment module under workerd and a default one otherwise. The #db-client specifier has three variants, a D1 client under workerd, a stub under storybook, and a Node client as the default. The #storage specifier chooses a Cloudflare storage module or a stub. The #flush-scheduler picks a Cloudflare observability scheduler or a default one. And #actions/* maps to mocked action implementations under storybook and the real ones otherwise.

The effect is that the same application code runs in three contexts: the real Cloudflare Worker in production, a Node-backed development server, and Storybook with stubbed actions. The storybook branch in particular is what lets a component library or a UI tour run with no backend at all.

There is a parallel set of Drizzle configurations, drizzle.config.d1.ts, drizzle.config.local.ts and drizzle.config.test.ts, matching the three environments, and the database client selection is the same story in the type system.

There is also a Docker-based layer for the e2e directory with a compose file, a Postgres service and a fake OpenAI service, and the e2e run instructions point at it. So the isolated test environment is a containerised stack, while the developer's own machine needs nothing at all.

Cloudflare primitives doing the heavy lifting

The tech stack table is a good summary of what the platform depends on, and four entries carry most of the design.

Cloudflare Workflows provides the durable execution for asynchronous AI generation runs. A video generation is a multi-step process that can take minutes, and durable execution is the right primitive for that: the workflow survives a worker restart and resumes where it left off rather than being retried from the start.

Cloudflare Durable Objects handle realtime, with SSE progress updates. So a client watching a render sees progress as it happens rather than a spinner and a finished file, and the Durable Object holds the per-render session state.

Cloudflare R2 is the storage layer, an S3-compatible object store, and the environment file notes that remote R2 is an optional configuration alongside the local one.

Drizzle ORM with Cloudflare D1 is the database, and D1 is SQLite, which is why the Drizzle configuration is called drizzle.config.d1.ts and why there is a separate Node client.

The AI layer is TanStack AI with Fal.ai for generation and OpenRouter for the LLM work, plus PostHog for LLM observability. Better Auth handles passkey authentication, and the feature list describes it as passwordless sign-in.

Around that, TanStack Start and TanStack Router with Vite for the application, Tailwind v4 and shadcn/ui for styling, and Vitest plus Playwright for testing. There is also a chromatic.config.json, which suggests visual regression testing on components.

The scripts table shows how the team works

The scripts tables in the README are unusually revealing, because they document the team's own workflow rather than just the product.

On the development side, bun dev bootstraps the environment, migrates and seeds the database and starts the server. bun setup adds AI keys interactively, with a --prod flag for deployments. bun tunnel prints this laptop's hostname map, and bun tunnel:provision is an optional command that provisions ten random public HTTPS names for ports 3000 to 3009, which is what you need for a device to reach your local server over HTTPS. bun storybook starts Storybook on port 6006.

The secret handling is the part that matters for anyone deploying this. The package.json has secrets:pull, which runs the doppler CLI to download secrets for the openstory project in the dev config and write them into .env.local, plus secrets:push:prd and secrets:check:prd, which run a script to push or verify secrets for the production config. There are also r2:cors commands with env variants for prd and stg, which set the CORS policy on the bucket.

So the deployment story is: Doppler holds the secrets, a script pushes them to the Cloudflare side, and a separate script configures the R2 bucket for browser access. It is more moving parts than a typical open-source demo, and it is the clearest signal in the repository that this is a product being built rather than a weekend project.

Where the platform is not ready yet

Three limits are visible in the documentation.

The first is the workspace feature. Team workspaces with shared libraries of styles, characters, VFX and audio are marked as coming soon, and the marketing sentence about teams collaborating on shared libraries describes something that is not shipped yet. Until it is, the consistency that makes the platform interesting is per-project rather than per-team.

The second is that generation cost is front-loaded and external. Script analysis goes through OpenRouter and every frame goes through Fal.ai, so a long video is a long series of paid API calls, and a platform that generates images can fail halfway through a render with money already spent. The Cloudflare Workflows durable execution helps with resuming the work, but not with the cost.

The third is the deployment target. D1, R2, Workflows and Durable Objects are the storage and execution model, not optional extras, so running this on another platform is not a configuration change. The local development experience is unusually good precisely because Miniflare emulates all of it, but that emulation is not the same as running on another cloud.

On maintenance, the repository is not archived and the last push was on 2026-10-19, with the @openstory/stitch package released at 0.3.0 the same day and 0.2.0 on 2026-10-14. The licence is MIT, so the code can be read, modified and self-hosted without restriction.

Editorial conclusion

OpenStory is a good fit for a small team that wants to produce short stylised video from a written script without a pipeline of their own, since the platform handles the scene breakdown, the prompt engineering, the generation calls and the compositing, and it ships a Deploy to Cloudflare button. It is a poor fit if you need team workspaces today, since the shared libraries of styles, characters and VFX are marked as coming soon, and a poor fit if your deployment cannot live on Cloudflare, because D1, R2, Workflows and Durable Objects are the storage and execution model rather than an optional extra. Before adopting, run bun setup and add the FAL_KEY and OPENROUTER_KEY, try a single scene on the local stack before deploying, and read the AGENTS.md architecture document, which the readme points to as the full description of server handlers, workflow patterns and React conventions.

Frequently asked questions

What are the prerequisites for running OpenStory locally?

Bun 1.3.9 or later is the only requirement. The README states there is no Docker, no external database and no Cloudflare account needed, because local dev runs the full stack including D1, R2, Workflows, Durable Objects and email inside Workerd via Miniflare.

How do I set up OpenStory and add the AI keys?

Run bun install and then bun dev, which generates .env.local with auth and encryption secrets, migrates and seeds the local database, and starts the server on port 3000. For AI features, run bun setup to add FAL_KEY for fal.ai and OPENROUTER_KEY for OpenRouter, or paste them into .env.local yourself.

Which Cloudflare services does OpenStory use?

Cloudflare Workflows for durable execution of asynchronous AI generation runs, Durable Objects for realtime SSE progress updates, R2 for S3-compatible storage of media, and D1 with SQLite for the database through Drizzle ORM.

Can OpenStory publish a finished render to social platforms?

Yes, optionally, using your own Upload-Post key to post to TikTok, Instagram, YouTube, LinkedIn, X and more. It is listed as an optional feature in the README.

Official sources

  1. License: MIT
  2. openstory-so/openstory on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/openstory-so-openstory.svg)](https://hysenlabs.com/projects/openstory-so-openstory)

Was this useful?