AI Image Generator — JavaScript source
Turn a text prompt into a 1024×1024 image with FLUX.1 [schnell] on Cloudflare Workers AI. No account, no API key — rate-limited for fair use. Your prompt goes to the model through our Worker; we store no prompts and no images.
This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
/**
* AI Image Generator — prompt validation, D1 usage-gate verdicts, and
* ?prompt= URL state for FLUX.1-schnell image generation.
*
* Language: JavaScript (ES2022, standard library only)
* Source: CosmoDev polyglot showcase port of the AI Image Generator tool,
* from src/lib/image-gen.ts (the canonical TypeScript implementation).
*/
export const MODEL = '@cf/black-forest-labs/flux-1-schnell';
export const STEPS = 4; // flux-1-schnell's design point -> 57.6 neurons/image
export const PROMPT_MAX_CHARS = 600; // UX clamp, below the model's 2048 limit
export const IP_HOUR_CAP = 10;
export const DAILY_CAP = 100;
/** Control chars except \n: C0 minus U+000A, DEL, and C1. */
const CONTROL_CHARS = /[\x00-\x09\x0B-\x1F\x7F-\x9F]/;
export function validatePrompt(raw) {
// Normalize CRLF/CR first so pasted text keeps its line structure.
const prompt = raw.replace(/\r\n?/g, '\n').trim();
if (prompt.length === 0) return { ok: false, reason: 'empty' };
if (prompt.length > PROMPT_MAX_CHARS) return { ok: false, reason: 'tooLong' };
if (CONTROL_CHARS.test(prompt)) return { ok: false, reason: 'controlChars' };
return { ok: true, prompt };
}
/** Minutes (>= 1) until the next UTC midnight — the daily window reset. */
function minutesToUtcMidnight(now) {
const d = new Date(now);
const nextMidnight = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate() + 1);
return Math.max(1, Math.ceil((nextMidnight - now) / 60_000));
}
export function checkGate(ipCount, dailyCount, now = Date.now()) {
if (dailyCount >= DAILY_CAP) {
return {
ok: false,
error: 'RATE_LIMITED_DAILY',
retryAfterMinutes: minutesToUtcMidnight(now),
};
}
if (ipCount >= IP_HOUR_CAP) {
return { ok: false, error: 'RATE_LIMITED_IP', retryAfterMinutes: 60 };
}
return { ok: true };
}
/** Encode the shareable state: '' when there is nothing to share. */
export function encodeUrlState(prompt) {
return prompt ? `?prompt=${encodeURIComponent(prompt)}` : '';
}
/** Inverse of encodeUrlState — a missing param decodes to ''. */
export function decodeUrlState(search) {
return new URLSearchParams(search).get('prompt') ?? '';
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →