Console

Effing up in the cloud?Leave it to us. We made it.

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.

cloud.effing.dev/console
ffs
Overview
Filter by tags
Renders
12,847
Errors
23
Avg render time
32s
P95 render time
57s
Renders and errors
Render time
Average video duration

What do you get?Big deploy energy.

Just effing-cloud deploy and you’re up in the cloud, with all of the usual perks that brings. And you get to:

TEMPLATE

Template like crazy

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.

TRACK

Track with tags

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.

SCALE

Scale to zero

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.

How does it work?npx and chill.

From an empty project to a rendered video in five simple steps. No infrastructure, no Docker, no YAML.

  1. 1

    Install and log in

    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.

    terminal
    $ npm i -D effing-cloud
    $ npx effing-cloud login
    logged in as [email protected]
  2. 2

    Write an effie module

    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.

    app/effies/poster.fn.tsx
    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 }],
          }),
        ],
      });
    }
  3. 3

    Point at it, deploy

    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.

    effing.config.ts
    import { defineConfig } from "@effing/dev";
    
    export default defineConfig({
      project: "posters",
      effies: "app/effies/*.fn.tsx",
    });
    terminal
    $ npx effing-cloud deploy
    posters v3 — 1 effie module
  4. 4

    Mint signed URLs

    Pass 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.

    server.ts
    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>
  5. 5

    Render videos

    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.

    terminal
    # 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