Two-phase review via apps-review-submissions.yml (AI evidence + human decision). Source of truth: operations/app-management/app.json.
Flow: user opens an APP-SUBMISSION issue → AI checks the live app and optional repository → APP-NEEDS-INFO or APP-REVIEW → maintainer adds APP-APPROVED → apps-publish-submissions.yml validates the issue again, prepends the app to operations/app-management/app.json, and opens an auto-merge PR that closes the issue via Fixes #NNN.
APP-SUBMISSION is the persistent type label. APP-NEEDS-INFO, APP-REVIEW, and APP-APPROVED describe review state. Quest rewards are detected separately from the merged catalog and are not announced by the submission workflows.
Manual edits: edit operations/app-management/app.json, then run node operations/app-management/app.js validate.
Catalog fields: emoji, name, url, description, language (ISO code), category, platform, githubUsername (without @), githubUserId (string), repositoryUrl, repositoryStars (number or null), discordUsername, other, submittedDate, issueUrl, approvedDate, byop (boolean), requests24h (number).
Platforms (auto-detected; comma-separated for multi): web (default w/ URL), android, ios (App Store or routinehub.co), windows, macos, desktop (cross-platform), cli, discord, telegram, whatsapp, library (npm/PyPI/SDK), browser-ext, roblox, wordpress, api (default w/o URL).
Categories: image, video_audio, writing, chat, games, learn, bots, build, business.
Guild ID 885844321461485618 (https://discord.gg/pollinations-ai-885844321461485618) — use for Discord MCP tools.
enter.pollinations.ai/— Auth gateway + billing (Cloudflare Worker)gen.pollinations.ai/— Edge router + text generation Workeroperations/infrastructure/gpu/— Image GPU backends, fleet inventory, and deployment toolingpollinations.ai/— React frontendpackages/sdk/—@pollinations/sdk(client + React hooks)packages/mcp/—@pollinations/mcp(MCP server; seepackages/mcp/AGENTS.md)shared/— auth, registry, IP queue;shared/registry/holds model registriesapps/— Applications maintained in this repositoryoperations/app-management/— Community app catalog and automationoperations/— Internal dashboards, monitoring, economics, and infrastructureoperations/social/— Discord/Reddit/GitHub automation
Primary: https://gen.pollinations.ai → routes to enter.pollinations.ai for auth/billing.
- Auth:
pk_(frontend),sk_(backend). Keys: https://enter.pollinations.ai/keys - Billing: Pollen credits ($1 ≈ 1 Pollen). Full docs:
./APIDOCS.md - Pack checkout: Stripe. Polar is retired from runtime; do not add Polar SDKs,
Worker bindings, webhooks, or automated writes. Historical Polar handling
(pre-Stripe pack revenue, Nov 2025–Jan 2026) lives in the Economics provider
collection skill (
.claude/skills/economics-provider-collection/). - Services: Text (Portkey, multi-provider), Image (gen Worker dispatch to providers/GPU backends), Video (Wan/Veo/LTX), Audio (ElevenLabs, TTM)
- Wallet: Pollen is earned by completing Quests; balances live in the
tier_balance(shown as Quest Pollen) andpack_balance(Paid) buckets. The legacytierD1 column andtier_balancewire name are kept for compatibility; seeshared/db/better-auth.ts. - Referral links must use the canonical landing page with a short
?ref=value; record analytics behind the page instead of exposing a tracking API as the destination URL.
Ports: enter 3000 (API at /api/*), gen 8788. Run npm run dev per service.
Image generation now runs inside gen.pollinations.ai; local image API tests should target the gen worker on port 8788.
Local API test:
curl "http://localhost:8788/image/test?model=flux" -H "Authorization: Bearer $TOKEN"
curl "http://localhost:8788/v1/chat/completions" -H "Authorization: Bearer $TOKEN" ...- Image:
GET gen.pollinations.ai/image/{prompt}(bearer token) - Text (OpenAI):
POST gen.pollinations.ai/v1/chat/completionswith{model, messages}(bearer token) - Simple text:
GET gen.pollinations.ai/text/{prompt}?key=... - Audio:
GET gen.pollinations.ai/audio/{text}?voice=nova&key=... - Models:
/image/models,/v1/models - See
./APIDOCS.md,.claude/skills/enter-services/SKILL.md
- Media generation uses the durable generation coordinator and supports request lifetimes up to 300 seconds. Do not reject a route solely because it exceeds 120 seconds or polls an asynchronous provider internally.
- Prove identical-request disconnect/rejoin, one upstream execution, completed R2 cache retrieval, one wallet debit, and one billed Tinybird event.
- Test behavior just below, at, and above 300 seconds. A route expected to exceed 300 seconds requires a separately approved asynchronous public contract.
Follow YAGNI religiously:
- Only implement what's needed now. Remove unused functions.
- No speculative abstractions, "just in case" helpers, preemptive test utils/wrappers.
- No backward-compat fallbacks — clean breaks beat bloat. When changing tokens/headers/APIs, update all consumers at once.
- When user says "keep it simple" — one function, one price, one config. Simplest thing that works.
- Registry-declared fallback pairs are maintainer-owned; do not add runtime price, compatibility, target availability/privacy, or parameter-normalization guards unless a concrete declared pair requires one.
CRITICAL — never mutate a secret without the user's separate, explicit, scoped approval.
- A secret mutation includes creating, replacing, rotating, revoking, regenerating, synchronizing, or deploying a credential, token, API key, certificate, GitHub secret, provider secret, or encrypted SOPS value.
- Before any mutation, stop and state the exact secret name (never its value), environments, reason, expected impact, execution order, verification, and rollback.
- Require a new approval in the current conversation after presenting that plan. General instructions such as “go ahead,” “fix it,” “deploy,” “continue,” or approval for the surrounding model/task work do not count.
- For a first-time secret addition, require:
Yes, you can add <SECRET_NAME> to <ENVIRONMENTS> now. - For replacing an existing secret, require:
Yes, you can rotate <SECRET_NAME> in <ENVIRONMENTS> now. - Approval is valid only for the named secret, environments, and one described operation. Never reuse or broaden it.
- Do not edit a secret file, change provider/GitHub secret state, or open or push a secret-change PR before receiving that approval.
- If exposure is suspected, report it immediately and stop. Do not revoke or rotate until the explicit approval is received.
- Read-only inspection may continue, but never print, echo, log, or otherwise expose secret values.
- Encrypted secret-file changes must use a dedicated PR. Never bundle them into a model, feature, pricing, or refactor PR.
- Never synchronize production secrets from an unmerged commit or a branch other than
production. - For rotation, add and verify the replacement first, merge the encrypted update, deploy from
production, run live tests for every affected service, and only then revoke the previous credential.
CRITICAL — production Cloudflare deployments must always run through GitHub Actions:
- Use the production deployment workflow
Deploy / Cloudflare production; useworkflow_dispatch(and itsserviceinput to target one worker) when path filters do not trigger it. - Dispatch production workflows only from the
productionbranch. Select a secret-synchronization input only after the Secret Mutation Safety approval gate. - Never run
wrangler deploy --env production, a production deployment npm script, or a direct production Worker upload from a local machine or agent session. - If CI credentials lack a required permission, follow the Secret Mutation Safety approval gate before updating the scoped GitHub Actions secret and rerunning the workflow. Never bypass CI with a local Cloudflare OAuth session.
- After the workflow succeeds, verify the active Worker version and required bindings before testing production traffic.
CRITICAL — These rules apply whenever deploying to Tinybird:
- Two workspaces:
pollinations_enter(prod) andpollinations_enter_staging(staging + dev + local). Pipes and datasources must be deployed to both — no CI auto-deploy yet, tracked in #11127. - Use the Tinybird Forward CLI as
tb(not Classic). - Do not rely on
.tinybfor workspace selection. Always pass an explicit workspace-scopedTB_TOKENwithWORKSPACE:DEPLOYand--host https://api.europe-west2.gcp.tinybird.co; never source deploy credentials from Enter runtime secrets. - Always validate and deploy to staging first, verify, then prod only when requested.
- Validate first:
tb --cloud --host "$TB_HOST" deployment create --check --no-allow-destructive-operations - Deploy staging:
tb --cloud --host "$TB_HOST" deployment create --wait --no-allow-destructive-operations - Verify staging:
tb --staging --cloud --host "$TB_HOST" endpoint lsandtb --cloud --host "$TB_HOST" deployment ls - Never
--allow-destructive-operationswithout explicit permission - Never
tb push(deprecated). Avoidtb deploy; use explicitdeployment createcommands so promotion is never accidental. - Never use
--autoordeployment promotewithout explicit permission. - Always
--cloud(otherwise CLI hits Tinybird Local/Docker) - Run from
enter.pollinations.ai/observability - Verify all consumers within a workspace before modifying a pipe (pipes are NOT cross-workspace; each workspace has its own copy)
- If validation reports datasource or pipe deletion, stop. Restore the missing definition or ask before deleting; do not override with destructive flags.
- Forward materialized views cannot use
UNION; split sources into separate materialized pipes writing to the same datasource. - Timeouts: use
uniq()notuniqExact(); avoid CTE+JOIN; single-pass queries; for large time ranges usestart_dateparameter week-by-week - Full procedure:
.claude/skills/tinybird-deploy/SKILL.md
operations/economics/weblocal development must read Tinybird staging (pollinations_enter_staging) throughoperations/economics/secrets/web.dev.json.- Production Economics deployments read
operations/economics/secrets/web.json. Never decrypt that production file directly into the local.dev.varsfile. - After switching, merging, or rebasing an Economics branch, rerun
npm run decrypt-varsbefore trusting the local dashboard. The generated.dev.varsmust combine the shared password with the staging-only read token viascripts/write-dev-vars.mjs. - A local dashboard showing production-only or stale provider rows is an environment-routing failure; fix the local reader before changing ledger data or publishing another correction.
- Modern JS/TS, ES modules (all
.jsare ESM). Follow existing formatting. Comment complex logic. - Run
npx biome check --write <file>after edits and before commits. - Before implementing: verify assumptions on web (APIs change), read related files, check related PRs/issues, check existing utilities in
shared/before writing new ones (auth, queue, registry, SSE parsing, retry wrappers), confirm branch viagit branch --show-current. - When continuing prior work: read relevant code first; identify clear next steps.
- Don't reimplement existing logic — search first.
- When adding a React browser/IIFE bundle, grep bundled dependencies'
published dist for
react/jsx-runtimeandreact-domimports before choosing shim vs external; transitive deps such as@ark-ui/reactPortal can reintroduce externals the package source does not import.
IMPORTANT — Agents often make these mistakes (learned from session history):
- Don't use
cdin bash; usecwdparameter. - Don't run
pytest; usenpm run testornpx vitest run. - Don't create
.mddocs unless asked. - Always use absolute paths.
- Don't edit files manually during a Claude Code session (busts cache).
- Don't run
/compactunless necessary (busts cache). - Don't let searches run wild — use targeted paths.
- Don't modify test files to make tests pass — fix the code.
- Run
npm run decrypt-varsbefore tests in enter.pollinations.ai. - Test API keys in
enter.pollinations.ai/.testingtokens. - Before model changes, read and follow
.claude/skills/model-management/SKILL.md. - Don't request PR reviews or comment
polliunless the user explicitly asks. - Model descriptions must describe only capabilities or differentiators; never repeat the model title or name.
packages/sdkkeeps its ownpackage-lock.jsonbecause it is published standalone. After changingpackages/sdk/package.json, regenerate it withnpm install --prefix packages/sdk --workspaces=false --package-lock-only; a plain workspace install updates only the root lockfile.
Commands:
- enter.pollinations.ai:
cd enter.pollinations.ai && npm run test(vitest + CF Workers pool) - gen.pollinations.ai:
cd gen.pollinations.ai && npm run test(vitest + CF Workers pool)
Run individually — full suite is slow:
npx vitest run --testNamePattern="name"
npx vitest run test/file.test.ts- Test real code, not mocks — use direct imports. Don't create mock infrastructure.
- Read existing tests before adding; prefer extending existing files; follow existing conventions.
- Snapshots (enter): VCR-style, replayed by default.
TEST_VCR_MODE=recordto record; defaultreplay-or-record. .testingtokenscontains:ENTER_API_TOKEN_LOCAL,ENTER_API_TOKEN_REMOTE,ENTER_TOKEN,GITHUB_TOKEN.- Production API tests should hit
gen.pollinations.ai.
- Frontend →
pollinations.ai/; image/text/gen gateway →gen.pollinations.ai/; image GPU backends →operations/infrastructure/gpu/; SDK/React →packages/sdk/; MCP →packages/mcp/. - Text models: add config in
gen.pollinations.ai/src/text/configs/modelConfigs.ts, entry ingen.pollinations.ai/src/text/availableModels.ts. Provider configs (Portkey/Bedrock/OpenAI-compat) ingen.pollinations.ai/src/text/configs/providerConfigs.ts. - Image models: handler in
gen.pollinations.ai/src/image/, register inshared/registry/image.ts. - Update the model registry and OpenAPI source schemas/routes for new models.
- API changes: maintain backward compatibility; document; handle errors.
- Never edit or regenerate
APIDOCS.mdin a feature PR. It is generated from the live OpenAPI schema after a successful production deploy by.github/workflows/docs-regenerate-api-reference.yml, which opens a separate docs PR. Make documentation changes in the source schemas, routes, introductions, or recipes instead. - API docs source text: strictly technical, no marketing; link dynamic endpoints (e.g.
/models) vs hardcoded lists; no internal impl/env vars; minimal examples for both simplified and OpenAI-compatible endpoints. - Security: never expose keys/secrets; use env vars; validate input.
- Temp scratch files go in
temp/clearly labeled. - Shrinking large snapshots: video/image snapshots can be 10–30 MB because stream chunks store raw binary as text (
TextDecoderoutput invcr.ts:289). To shrink: replaceresponse.body.dataarray with one tiny chunk[{"data": "<minimal-bytes>", "delay": 1}]. For mp4, a valid 20-byte ftyp box is\x00\x00\x00\x14ftypisom\x00\x00\x00\x00isom(usebytes.decode('latin-1')in Python). Tests only check headers/status, not media content.
- Plan mode for any non-trivial task (3+ steps or architectural). If things go sideways, STOP and re-plan. Write specs upfront.
- Delegate to a subagent only for large, genuinely independent tracks of work (e.g. a wide multi-file investigation). Don't delegate what you can finish in a handful of tool calls, and don't use subagents to verify your own work.
- After user correction: propose an AGENTS.md update capturing the pattern; iterate until mistake rate drops.
- Bug reports: just fix them — point at logs/errors/failing tests and resolve. Fix failing CI without being asked how.
Preserve during compaction: modified files + line numbers, all code/diffs/impl details, test output + errors + command results, full plan + progress + pending, user preferences/corrections this session, architectural decisions + rationale.
- Stay on the current user-approved branch and its single PR. Never create, checkout, switch to, or work from another branch or worktree unless the user explicitly approves that branch change first.
- Integrate follow-up work directly on the active branch. If continuing would require a new branch or PR, stop and ask before creating it.
- Feature branches target
main. Promotemaintoproductiononly through a separate promotion PR; never targetproductiondirectly with feature or fix work. - "send to git" = git status, diff, branch, commit all, push, PR description.
- Verify branch:
git branch --show-currentand confirm if unsure (branch mix-ups are a recurring mistake). - Avoid force pushes (
--force,--force-with-lease) — prefer follow-up commits. - Run biome check before committing.
- If the active PR is already merged, ask before opening a follow-up branch or PR.
Be concise. PRs/comments/issues: bullets, <200 words, no fluff.
-
Pollinations.ai is the product brand. Use
hello@pollinations.aifor public support, privacy, legal, and general customer contact, andbilling@pollinations.aifor billing contact. -
Myceli.AI OÜ is the registered legal entity and data controller. Preserve its legal name, copyright and ownership attribution, contributor identities, provider-account identities, infrastructure hostnames, and entity-specific operational contacts.
-
Never replace Myceli entity or infrastructure references merely because they differ from the Pollinations product brand. Change them only as part of an explicitly requested legal-entity or infrastructure migration.
-
PRs: "- Adds X", "- Fix Y"; 3-5 bullets; titles "fix:"/"feat:"/"Add"; no marketing.
-
Issue comments: bullets only; facts not opinions; link code; be direct (no "I think"/"maybe").
-
Code reviews: focus on what needs improving; link specific lines; don't praise fine code or repeat obvious things.
Only use established labels (check with mcp1_list_issues). Don't create new labels ad-hoc; keep names consistent.
Commit format:
feat: add feature
Co-authored-by: username <user_id+username@users.noreply.github.com>
Fixes #issue
- Use "Fixes #issue" or "Addresses #issue" in PRs.
- Email:
{username} <{user_id}+{username}@users.noreply.github.com>(user_id from issue API). - For publisher-allowlist PRs prompted by an access-request issue, add the requester as a
Co-authored-bycontributor using their numeric GitHub ID.