Studio composer with live reveal
Prompt, negative prompt, FLUX schnell/dev/pro, size preset and a 1-4 image count, all on one /studio screen. The generating card polls every second and reveals each image the moment fal finishes — no refresh.
Describe your app, pick a style, and get a crisp, modern, full-bleed 1024px icon master in seconds — powered by the latest image model. Built for indie makers and studios who need great icons fast, without the design-agency price tag.
A credit-metered FLUX pipeline with a live render reveal — the prompt types itself, the canvas resolves out of noise, and one credit clicks off the meter. Every result is re-fetched into storage you own.
Type a prompt, pick a FLUX model and size, spend a credit per image. Results land in a composer and gallery you own — keys, billing and storage all included.
Prompt, negative prompt, FLUX schnell/dev/pro, size preset and a 1-4 image count, all on one /studio screen. The generating card polls every second and reveals each image the moment fal finishes — no refresh.
A /gallery masonry grid with likes, folders you create and rename, and a lightbox that does prev/next, copy-prompt and download. Filter by liked or collection; move images between folders.
/studio and /gallery live in the member sidebar app and open for any signed-in user — no hard paywall. Each generation spends 1 credit up front; hit zero and you're routed to top-up. If fal fails or the submit throws, the credits are refunded automatically.
Hit Remix on a gallery image and its prompt, model, seed and size load straight back into the studio. Lock the seed or randomise it.
Every image is downloaded from fal and uploaded into your private Cloudflare R2 bucket. No SDK — a plain cURL S3 Sig V4 signer in bootstrap.php.
The whole pipeline is dormant until FAL_KEY and your R2 keys are set, so the rest of the stack runs clean without it. A built-in dev mock paints gradient PNGs so you can click through the full studio and gallery before you spend a penny on fal.
Type a prompt, pick a FLUX model, spend a credit per image — and every result is re-fetched server-side and self-hosted in your private R2 before it hits the grid.
fal → your private R2 (S3 Sig V4 PUT) → presigned GET, expires in hours
Every figure here is how the pipeline actually behaves — not a sales number.
The bit other starters hand-wave: getting an async render from fal onto your own storage, reliably, without a queue or a worker process.
On submit we pass fal a webhook URL derived from APP_URL. The browser also polls generation_status every second for up to 60. The webhook (push) and the poll (pull) both finish the job; storing images is idempotent, so the loser is a harmless no-op. On localhost there's no public webhook — the poll covers it.
Whichever path completes, image_gen_reconcile re-fetches the authoritative result from fal server-side with your key. A spoofed webhook payload can't inject an image, because the payload is never the source of truth.
On completion each image is pulled from fal and PUT into your own R2 bucket via a hand-rolled S3 Sig V4 signer — no AWS SDK, no S3 client. The bucket stays private; nothing is left sitting on fal's CDN.
Image rows are served through presigned GET URLs that expire in a couple of hours, floored to the hour so the same URL is cacheable within that window. The bytes are a capability that lapses, not a public ACL — and every query is user-scoped, so other people's image IDs 404.
fal.ai FLUX in, your own private R2 out, credits metered per image and a gallery you own — every subsystem of the studio hangs off one app core.
Every install ships with this. Search users, replay webhooks, inspect billing and revoke keys — server-rendered, access-gated, no second app.
| User | Plan | Status | Joined |
|---|---|---|---|
| ada@example.com | Pro | active | 2d ago |
| grace@example.com | Scale | active | 5d ago |
| linus@example.com | Starter | past due | 3w ago |
| margaret@example.com | Pro | active | 1mo ago |
| blocked@example.com | Free | blocked | 1mo ago |
invoice.paidevt_1Q8x…a3customer.subscription.updatedevt_1Q8w…f1checkout.session.completedevt_1Q8w…7cinvoice.payment_failedevt_1Q8v…02charge.refundedevt_1Q8u…9dcurl -H "Authorization: Bearer ss_live_••••" \ https://app.yoursaas.com/api.php?resource=notes { "ok": true, "data": [ "note_18f2", "note_18f9" ], "rate_limit": "58/60", "credits_left": 1840 }
copy a template folder
composer install · Stripe + SES
rebrand · plans · run doctor
NGINX + PHP-FPM · take cards
unzip → live on a VPS — one afternoon.
Most SaaS dies of complexity, not competition.
| daily_hits | 100,000+ |
| cost / 10k logins | $1 |
| whole_stack / month | < $10 |
| reads_block_writes | never · WAL mode |
Define plans in app/subscriptions.php, attach Stripe price IDs, and the checkout flow stays generic across every project.
Sign in free and browse — buy credits to generate.
For indie makers shipping a few apps.
For studios iterating on lots of icons.
For agencies producing icons at volume.
Whatever you decide — a generation, an API call, an export, a render minute. Plans grant credits; each action spends them through one ledger via consume_credits_for_action().
Your call per plan. Period credits top up to a fresh allowance each period by default, and you can switch to rollover in the plan config.
Yes — combine recurring plans that grant credits with one-time purchases for top-up packs.
Yes — parameterised SQL throughout, signed Stripe webhooks, CSRF, rate limiting and session hardening, all security-reviewed. Real plumbing, not a toy.
One small VPS runs the whole stack for a few dollars a month, and passwordless login emails on Amazon SES are about $1 per 10,000 sign-ins. Prefer Apple or Google sign-in? Both are built in with no per-login cost — Google's is free, and Apple's only needs an Apple Developer account ($99/yr) you likely already have to ship an app — so you can skip login emails entirely. No per-seat platform bills.
Passwordless sign-in, Stripe billing, credits and admin — already wired. Copy a folder, rename it, start charging.