Skip to Content
FeaturesAI Generation

AI Generation

A generic, provider-agnostic generation pipeline lives in src/domains/generation/. Today it ships a Replicate runner; the pipeline executor itself is pure and accepts any RunStep.

Anatomy

src/lib/replicate.ts # root Replicate client (injected; never imported by domains) src/domains/generation/ ├── lib/ │ ├── runner.ts # RunStep type + createReplicateRunner (FileOutput normalization) │ └── pipeline.ts # executePipeline — sequential, chainAs injection, DI ├── schemas.ts # PipelineStepSchema, GenerateAIInputSchema └── components/ └── GenerateForm # client form (used on the test page)

The generateAI server action

Exposed to any interface (form, MCP tool, REST endpoint).

import { generateAI } from '@/actions/generate' // Single-step (most common) await generateAI({ steps: [ { model: 'black-forest-labs/flux-schnell', input: { prompt: 'a cat' } }, ], paywallConfig: { enableCredits: true, credits: 1 }, // or null for free }) // Multi-step with chaining await generateAI({ steps: [ { model: 'black-forest-labs/flux-schnell', input: { prompt: 'a cat' } }, { model: 'some/upscaler', input: { scale: 2 }, chainAs: 'image' }, ], paywallConfig: null, })

Returns: { success, results, finalOutput, creditsRemaining }.

chainAs — explicit step chaining

chainAs is the explicit key under which the previous step’s output gets injected into the next step’s input. It replaces any magic {ai_input} convention.

  • Model-specific and debuggable: chainAs: 'image', chainAs: 'init_image', chainAs: 'audio', etc.
  • Ignored on step 0.
  • Lets you compose any pair of Replicate models without a custom adapter per pair.

Paywall integration

The paywallConfig argument flows through the same paywall system used by gated content (see Monetization & Payments):

  • { enableCredits: true, credits: N } — require and decrement N credits per generation.
  • { enableSubscription: true, minimum_tier_rank: 2 } — gate behind a subscription tier.
  • null — free.

If the paywall check fails, generateAI returns { success: false, reason: 'paywall' } without calling Replicate.

On-demand vs. pre-generated

The pipeline supports both modes:

  • On-demand — user fills a form (or an agent calls generateAI), pays the credit cost, and the model runs. Output is returned and (optionally) persisted as a records row.
  • Pre-generated — a batch job runs the pipeline against a list of seed prompts/keywords overnight, writes outputs to records, and the /explore browse surface presents them at zero per-request cost.

The “AI Asset Library” shape uses both: a seed batch for SEO inventory, plus on-demand generation triggered by users via the credit system.

Next: aigenerator-section-block

A Payload block that stores model config + userInputs field definitions + paywallField. At render time it resolves {variableName} templates from user form input and calls generateAI with resolved steps. Template resolution is the block’s job — the pipeline always receives already-resolved inputs.

Provider-agnostic by design

executePipeline is pure and DI-driven. Adding another provider (OpenAI Images, Anthropic Files, fal.ai, …) is:

  1. Build a runner: createMyProviderRunner(client) → RunStep
  2. Register it alongside createReplicateRunner in src/lib/
  3. The pipeline doesn’t change.

Reference

  • Server action: src/actions/generate.ts
  • Replicate client: src/lib/replicate.ts
  • Runner factory: src/domains/generation/lib/runner.ts
  • Pipeline executor: src/domains/generation/lib/pipeline.ts
  • Schemas: src/domains/generation/schemas.ts