Build and Host Programmatic Videos with Remotion on Railway (Starter Template)
If you’ve ever wished you could generate videos from code, Remotion makes it possible by combining React with a video renderer. This article walks you through a production-ready starter that hosts a Remotion project behind an Express API on Railway. You’ll be able to trigger renders via HTTP, track progress, and optionally deliver finished videos via Telegram.
What You’ll Get
- A Railway-ready Node/Express server that renders Remotion videos
- A vertical sample composition (1080x1920) with an intro and quiz-style frames
- HTTP endpoints for creating, polling, and canceling render jobs
- Optional Telegram delivery when a
chatId
and bot token are provided
Why Remotion?
Remotion lets you author motion graphics in React. Instead of a timeline UI, you build components and animations (springs, sequences, interpolations) and render them to video via CLI or a server. This is perfect for:
- Automated social clips and stories
- Personalized onboarding/recap videos
- Dynamic course explainers or quizzes generated from JSON
Why Railway?
Railway is a developer-friendly platform for hosting apps and infrastructure. Push your repo, and Railway builds and runs it with sensible defaults. You can scale horizontally, manage env vars, and keep your render server alive without managing VMs or containers.
One-Click Deploy
This button provisions your service and sets the PORT
env automatically. After deploy, copy your public URL (e.g. https://your-app.up.railway.app
).
Local Development
1) Clone the repo and install dependencies
npm install
2) Create a .env
based on .env.example
cp .env.example .env
3) Start the server in watch mode
npm run dev
4) Open Remotion Studio (optional, for previewing compositions)
npm run remotion:studio
Environment Variables
Create .env
(or configure in Railway) using .env.example
as a reference:
-
PORT
: Server port. Railway injects this automatically in production. -
REMOTION_SERVE_URL
(optional): If you host a pre-bundled Remotion project elsewhere, point to it here to skip bundling on boot. -
TELEGRAM_BOT_TOKEN
(optional): Enables sending the finished video to the providedchatId
.
Note: In this starter, a chatId
is required in the request body (see API) because Telegram delivery is enabled by default. If you don’t use Telegram, you can remove the chatId
requirement in server/index.ts
.
API Endpoints
Base URL: Your Railway service URL (local: http://localhost:3000
).
- POST
/renders
- Starts a render job.
- Body shape:
{
"quizData": {
"questions": [
{"question":"Sample question?","options":["A","B","C","D"],"correctAnswerIndex":0}
]
},
"chatId": "123456789" // required in this template if Telegram is enabled
}
-
GET
/renders/:id
- Returns job status:
queued
,in-progress
(withprogress
),failed
(witherror
), orcompleted
.
- Returns job status:
-
DELETE
/renders/:id
- Cancels a
queued
orin-progress
job.
- Cancels a
Example start request:
curl -X POST https://<your-app>.railway.app/renders \
-H 'Content-Type: application/json' \
-d '{
"quizData": {
"questions": [
{"question":"Sample question?","options":["A","B","C","D"],"correctAnswerIndex":0}
]
},
"chatId": "123456789"
}'
What’s Inside the Template
-
server/index.ts
: Express app, queues jobs, exposes REST endpoints, bundles Remotion on boot (or usesREMOTION_SERVE_URL
). -
server/render-queue.ts
: In-memory queue +@remotion/renderer
integration, renders theQuizVideo
composition, and optionally posts the finished video to Telegram ifTELEGRAM_BOT_TOKEN
andchatId
are provided. -
remotion/
: The Remotion project with compositions.-
remotion/Root.tsx
: Registers compositions, includingQuizVideo
with default props. -
remotion/QuizVideo.tsx
: Vertical composition with an intro text and aHeroLogo
, timed quiz questions, and a countdown. -
remotion/HeroLogo.tsx
: Simple animated logo that slides in/out; image comes frompublic/
viastaticFile(...)
. -
public/
: Assets such aslogo-placeholder.webp
,countdown.mp3
, and optionalrailway-light.png
.
-
Customizing the Video
- Replace the logo: swap
public/logo-placeholder.webp
with your own asset and keep the same filename, or updateHeroLogo
to reference yours. - Change the intro text: see
remotion/IntroText.tsx
andremotion/QuizVideo.tsx
. - Edit questions:
remotion/Root.tsx
defines default props forQuizVideo
; you can also pass customquizData
in your POST request. - Add new compositions: create components and register them in
remotion/Root.tsx
as newComposition
entries.
Optional: Telegram Delivery
If you want the server to send completed renders to a Telegram chat:
1) Create a bot with BotFather and copy the bot token.
2) Set TELEGRAM_BOT_TOKEN
in your environment.
3) Find your chat ID (send a message to the bot and use a Telegram API helper or a bot to retrieve your chat_id
).
4) When starting a render, include chatId
in the request body.
If you don’t need Telegram, you can:
- Remove the
chatId
requirement inserver/index.ts
(adjust the validation), and - Keep
TELEGRAM_BOT_TOKEN
unset.
Troubleshooting
- Build stalls on bundling: Ensure the project compiles locally (
npm run remotion:studio
) and your Node version matches Railway’s image. - 404 on
/renders/:id
: Confirm you used thejobId
returned byPOST /renders
. - No video sent to Telegram: Verify
TELEGRAM_BOT_TOKEN
and that yourchatId
is correct. Check logs for the Telegram API response. - Asset not found: Assets must live under
public/
and be referenced withstaticFile('filename')
.
Costs and Performance Tips
- Rendering is CPU-intensive. Railway Hobby tier is fine for testing; scale up for production.
- Use H.264 (
codec: "h264"
) as in this template for broad compatibility. - Shorter compositions and fewer effects render faster.
Wrap-Up
This starter gives you a fast path to shipping code-driven video rendering. Deploy to Railway, hit an endpoint to generate a video, and iterate on your compositions just like any React app. Swap assets, change default props, or wire it into your own backend to automate content at scale.
Top comments (3)
link leads to another template
no any code or github? missed something?
Hi there - I think you've linked the wrong template to Railway. Would you be able to update the link to your Remotion template?