Run your Effing functions and video renders in the cloud, hosted by the OGs. Access controls, analytics, diagnostics — it’s all built in and ready to go.
Just effing-cloud deploy and you’re up in the cloud, with all of the usual perks that brings. And you get to:
Write an fn module once in TypeScript, then drop whatever props you want into the URL. Ten variants or ten thousand, it doesn't matter. One image or video per row of a huge product catalog? No biggie.
Tag every render and function run with whatever matters to you — customer, campaign, experiment, locale. Everything in the console can then be sliced by tag, so you can see exactly what's going on for each slice.
We scale down as well as up. When nothing is rendering, you're not paying. It's completely possible to burst out a campaign's worth of images and videos all at once, then back to zero until the next push.
From an empty project to a rendered video in five simple steps. No infrastructure, no Docker, no YAML.
It’s an npm package. Drop it into your project, then authenticate by running npx effing-cloud login. It’ll open a browser tab where you can authorize the device.
$ npm i -D effing-cloud
$ npx effing-cloud login
✓ logged in as [email protected]An effie is a TypeScript module that returns a video composition. Same shape as images and annies — a Zod props schema, sample preview props, and an async runner. Read the Effing tutorial for the full anatomy.
import { z } from "zod";
import { effieData, effieSegment } from "@effing/effie";
import type { RunnerArgs, EffieRunnerReturn } from "@effing/fn";
export const propsSchema = z.object({
imageUrl: z.string().url(),
duration: z.number().default(5),
});
type Props = z.infer<typeof propsSchema>;
export const previewProps: Props = {
imageUrl: "https://static.effing.dev/picsum/1080/1920/sky.jpg",
duration: 5,
};
export async function runner({
props: { imageUrl, duration },
bounds: { width, height },
}: RunnerArgs<Props>): EffieRunnerReturn {
return effieData({
width,
height,
fps: 30,
segments: [
effieSegment({
duration,
layers: [{ type: "image", source: imageUrl }],
}),
],
});
}The config file lists your module globs. effing-cloud deploy bundles them and ships them. Projects scaffolded with npm create @effing come with both pre-wired — an effing.config.ts and a cloud:deploy npm script.
import { defineConfig } from "@effing/dev";
export default defineConfig({
project: "posters",
effies: "app/effies/*.fn.tsx",
});$ npx effing-cloud deploy
✓ posters v3 — 1 effie modulePass your props to the official JS/TS or Python SDK to get a tamper-proof signed URL. For images, use the URL directly. Effies need to be rendered first to produce a video — that’s the final step.
import { EffingCloudClient } from "effing-cloud-sdk";
// secret is printed by `effing-cloud url-secret`
const client = new EffingCloudClient({
tenant: "acme",
project: "posters",
secret: process.env.EFFING_URL_SECRET!,
});
const posterUrl = await client.mintSignedUrl({
kind: "effie",
id: "poster",
props: { imageUrl: "https://cdn.example.com/sky.jpg", duration: 5 },
bounds: { width: 1080, height: 1920 },
});
// https://fn.effing.dev/acme/posters/effie/<segment>POST your signed effie URL to ffs.effing.dev/render with an API key. The SSE progress stream walks warmup and fires ready with a video URL — GET that, and the MP4 streams back live as it gets rendered. Or pass a pre-signed S3 URL as upload and video gets pushed straight to your bucket. See the @effing/ffs README for the full API.
# 1. Create a render job. FFS fetches the effie URL during warmup.
$ curl -X POST https://ffs.effing.dev/render \
-H "Authorization: Bearer $EFFING_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "effie": "https://fn.effing.dev/acme/posters/effie/eyJ0..." }'
{ "id": "550e8400-…", "progressUrl": ".../progress" }
# 2. Stream progress (effie → warmup → ready). The `ready` event hands you a video URL.
$ curl https://ffs.effing.dev/render/550e8400-…/progress
# 3. GET that URL — the render runs now, MP4 bytes stream back as ffmpeg produces them.
$ curl https://ffs.effing.dev/render/550e8400-…/video -o poster.mp4