{
  "catalog_version": "2.0.0",
  "prompt_version": "v2",
  "site": {
    "name": "0saas",
    "home": "https://0saas.pages.dev/",
    "thesis": "Cancel the subscription. Ally with a free-tier inference model. Keep the output.",
    "generated_at": "2026-09-17",
    "staleness_window_days": 30,
    "staleness_owner": "workers/pricing-cron (Cloudflare Cron Trigger, weekly) detects drift and writes receipts; scripts/check-drift.mjs is the same logic for a human pre-publish run; republishing a corrected number is always a human §New-2 re-extraction. See Master Prompt v2 §New-2b.",
    "allies_ref": "data/allies.json",
    "unlock_status_global": "not_yet_live — no Stripe Payment Link exists yet, so no price, buy button, or paywall may render anywhere on the site (§New-2c). Every tool is currently unlimited and free.",
    "prompt_standard": "Master-Generation-Prompt-v2 §New-7 (prompt pack), §New-8 (ally register), §New-9 (zero backend)"
  },
  "tools": [
    {
      "id": "417263",
      "slug": "canva-alternative",
      "title": "Free Alternative to Canva: Pull Social Graphics Off Your Own Free-Tier Model",
      "tier": "consumer",
      "status": "live",
      "published": "2026-09-17",
      "path": "consumer/canva-alternative.html",
      "url": "https://0saas.pages.dev/consumer/canva-alternative",
      "incumbent": "Canva",
      "incumbent_feature_displaced": "Canva Free's template-and-AI route to a finished social graphic: up to 20 Standard/Premium AI uses on a shared allowance, 1 Brand Kit limited to 3 colors, and no Magic Resize (Pro-only) — replaced by three reusable prompts that drive a local riso-press renderer.",
      "incumbent_free_limit": "US$0 plan: 1.6M+ templates, 4.7M+ assets, 1 Brand Kit (3 colors only), 5GB storage, and up to 20 Standard or Premium AI uses on a shared allowance with no Ultra AI. Canva Pro is US$144/year for one person.",
      "displacement_brief": "Canva's free tier still makes you the template's tenant: the AI allowance stops at about 20 uses, your brand kit stops at 3 colors, and resizing one graphic into three formats is a Pro feature. This tool gives you the three prompts that do that job on a free-tier inference model — layout direction, headline variants, and multi-format reflow — and renders the result as a real 1080px PNG/SVG in your own browser. Nothing is uploaded, nothing is metered by us, and the prompts are yours to keep and edit.",
      "disqualification_gate": {
        "requires_cross_session_persistence": "no — brand kit is optional and stored in the reader's own localStorage",
        "requires_third_party_auth": "no — the reader pastes their own free-tier key; OAuth never happens",
        "requires_realtime_multiparty_sync": "no — single-user, single-session",
        "verdict": "pass — full scope, no narrowing required",
        "narrowing_applied": null,
        "checked_at": "2026-09-17"
      },
      "pricing": {
        "source_url": "https://www.canva.com/pricing/",
        "checked_at": "2026-09-17",
        "next_check_due": "2026-10-17",
        "free_tier_limit": "US$0 — 1.6M+ templates, 1 Brand Kit (3 colors), 5GB storage, up to 20 Standard or Premium AI uses",
        "paid_tier_name": "Canva Pro",
        "paid_tier_price": "US$144/year for one person",
        "paid_tier_price_monthly": null,
        "field_confidence": {
          "free_tier_limit": "verified",
          "paid_tier_price": "verified",
          "paid_tier_price_monthly": "unconfirmed",
          "ai_allowance_reset_period": "unconfirmed"
        },
        "extraction_artifact": "data/pricing/canva.json",
        "receipts": []
      },
      "allies": [
        {
          "ally_id": "gemini-free",
          "role": "primary",
          "why": "Native strict-JSON output (responseMimeType) means the layout spec parses on the first try; long enough context to hold the schema plus a 600-char brief."
        },
        {
          "ally_id": "groq-free",
          "role": "secondary",
          "why": "Headline variants are a re-run-it-ten-times job. 30 RPM / 1,000 RPD base limits make iteration free."
        },
        {
          "ally_id": "openrouter-free",
          "role": "tertiary",
          "why": "Fallback if a reader already has an OpenRouter key and no Google or Groq account."
        },
        {
          "ally_id": "copy-paste-relay",
          "role": "floor",
          "why": "Mandatory. A reader with zero keys still gets a finished graphic by pasting the prompt into any free chat model."
        }
      ],
      "prompt_pack": [
        {
          "prompt_id": "riso-layout-director",
          "version": "1.0.0",
          "label": "1. Layout director",
          "displaces": "Canva's template picker + Magic Design: turning a one-line brief into a finished, on-brand graphic layout.",
          "best_ally": "gemini-free",
          "best_model_hint": "gemini-2.5-flash-lite",
          "why_this_model": "The output is a render spec, not prose. Strict-JSON mode on Gemini removes the parse-repair loop entirely; a lite model is enough because the schema, not the reasoning, carries the quality.",
          "fallback_ally": "groq-free",
          "system": "You are a risograph print-shop art director. You compose social graphics as machine-readable print instructions, never as prose.\n\nReturn ONLY one JSON object that matches this schema exactly. No markdown fences, no commentary before or after.\n\n{\n  \"format\": \"square-1080\" | \"portrait-1350\" | \"landscape-630\" | \"story-1920\",\n  \"layout\": \"editorial-stack\" | \"split-diagonal\" | \"corner-bracket\" | \"band-top\" | \"grid-2x2\",\n  \"ink\": { \"paper\": \"#rrggbb\", \"ink1\": \"#rrggbb\", \"ink2\": \"#rrggbb\", \"accent\": \"#rrggbb\" },\n  \"kicker\": string (max 6 words) or null,\n  \"headline\": { \"text\": string (max 8 words), \"case\": \"upper\" | \"lower\" | \"title\", \"weight\": 700 | 900, \"scale\": number 0.8 to 1.4 },\n  \"subhead\": { \"text\": string (max 22 words) },\n  \"cta\": { \"text\": string (max 5 words) } or null,\n  \"stat\": { \"value\": string (max 12 chars), \"label\": string (max 8 words) } or null,\n  \"motif\": \"halftone-dots\" | \"registration-marks\" | \"ink-swatch-bars\" | \"ruled-grid\" | \"overprint-blot\",\n  \"type_notes\": string (max 30 words),\n  \"alt_text\": string (max 125 chars)\n}\n\nHard rules:\n1. Two-ink riso palette. \"paper\" is never #ffffff and never black. \"ink1\" and \"ink2\" must differ by at least 60 degrees of hue. \"accent\" must contrast against \"paper\" at 4.5:1 or better because headline text is set in it.\n2. If brand colors are supplied, use them for ink1/accent and pick paper and ink2 around them. Never return a palette that is only greys.\n3. The headline must be a claim, not a label. Banned openings: \"Introducing\", \"Tips for\", \"How to\", \"Unlock\", \"Discover\". No exclamation marks anywhere.\n4. Never invent a number. If the brief contains no figure, \"stat\" is null. If it does, \"stat.value\" must be copied from the brief.\n5. Respect every max length. Truncating with an ellipsis is a failure, not a workaround.\n6. Write all copy in the language of the brief.\n7. \"alt_text\" describes both what the graphic looks like and what it says.",
          "user_template": "Brief: {{brief}}\nPlatform: {{platform}}\nAudience: {{audience}}\nBrand colors to respect (may be empty): {{brand_colors}}\nTone: {{tone}}\nFormat preference (choose one yourself if empty): {{format}}",
          "variables": [
            {
              "key": "brief",
              "label": "What is the post about?",
              "type": "textarea",
              "max_chars": 600,
              "sample": "Our 12-person studio cancelled Canva Pro in March. US$144/year per seat, 9 seats, and we only ever used templates and Magic Resize. We rebuilt both out of prompts and a free-tier model."
            },
            {
              "key": "platform",
              "label": "Platform",
              "type": "select",
              "options": [
                "Instagram feed",
                "LinkedIn",
                "X / Twitter",
                "Threads",
                "Pinterest",
                "Newsletter header"
              ],
              "sample": "LinkedIn"
            },
            {
              "key": "audience",
              "label": "Who is it for?",
              "type": "text",
              "max_chars": 120,
              "sample": "freelance designers who bill hourly and resent per-seat pricing"
            },
            {
              "key": "brand_colors",
              "label": "Brand colors (optional)",
              "type": "text",
              "max_chars": 60,
              "sample": "#1B4D3E"
            },
            {
              "key": "tone",
              "label": "Tone",
              "type": "text",
              "max_chars": 80,
              "sample": "dry, specific, receipts-first, zero hype"
            },
            {
              "key": "format",
              "label": "Format (optional)",
              "type": "select",
              "options": [
                "",
                "square-1080",
                "portrait-1350",
                "landscape-630",
                "story-1920"
              ],
              "sample": ""
            }
          ],
          "output_schema": {
            "type": "object",
            "required": [
              "format",
              "layout",
              "ink",
              "headline",
              "subhead",
              "motif",
              "alt_text"
            ],
            "properties": {
              "format": {
                "enum": [
                  "square-1080",
                  "portrait-1350",
                  "landscape-630",
                  "story-1920"
                ]
              },
              "layout": {
                "enum": [
                  "editorial-stack",
                  "split-diagonal",
                  "corner-bracket",
                  "band-top",
                  "grid-2x2"
                ]
              },
              "ink": {
                "type": "object",
                "required": [
                  "paper",
                  "ink1",
                  "ink2",
                  "accent"
                ]
              },
              "kicker": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "headline": {
                "type": "object",
                "required": [
                  "text"
                ]
              },
              "subhead": {
                "type": "object",
                "required": [
                  "text"
                ]
              },
              "cta": {
                "type": [
                  "object",
                  "null"
                ]
              },
              "stat": {
                "type": [
                  "object",
                  "null"
                ]
              },
              "motif": {
                "enum": [
                  "halftone-dots",
                  "registration-marks",
                  "ink-swatch-bars",
                  "ruled-grid",
                  "overprint-blot"
                ]
              },
              "type_notes": {
                "type": "string"
              },
              "alt_text": {
                "type": "string"
              }
            }
          },
          "decoding": {
            "temperature": 0.95,
            "max_output_tokens": 1200,
            "response_mime_type": "application/json"
          },
          "render_target": "#press-stage",
          "token_budget": "~700 in / ~450 out per run",
          "free_tier_cost_note": "1 request. On Groq's published base limits that is 1/1000th of the daily allowance; on OpenRouter's free variants it is 1/50th."
        },
        {
          "prompt_id": "headline-press-run",
          "version": "1.0.0",
          "label": "2. Headline press run",
          "displaces": "Canva's Magic Write for social copy — the paid-side text generation the free allowance runs out on after ~20 uses.",
          "best_ally": "groq-free",
          "best_model_hint": "openai/gpt-oss-120b",
          "why_this_model": "Headline work is iterative and latency-sensitive; you want ten attempts in the time one Canva AI use would take. Groq's 30 RPM base limit makes that free.",
          "fallback_ally": "gemini-free",
          "system": "You are a headline writer at a risograph print shop. You write short, factual, un-hyped lines for social graphics.\n\nReturn ONLY one JSON object. No markdown fences, no commentary.\n\n{\n  \"variants\": [\n    { \"text\": string, \"chars\": integer, \"angle\": \"number\" | \"contrarian\" | \"how-it-works\" | \"confession\", \"risk\": string (max 15 words) }\n  ],\n  \"recommended\": integer (0-based index into variants),\n  \"rejected_cliches\": [ string ]\n}\n\nHard rules:\n1. Exactly 4 variants. Each max 60 characters including spaces. \"chars\" must be the true character count of \"text\".\n2. At most one variant may contain a number, and only if the brief contains that exact number. Never invent a figure.\n3. Banned: emoji, exclamation marks, \"game-changer\", \"unlock\", \"secrets\", \"you won't believe\", colon-then-listicle (\"X: 5 ways to Y\").\n4. List in \"rejected_cliches\" the three most obvious generic headlines a marketing tool would have produced for this brief, so the writer can see what was avoided.\n5. Write in the language of the brief.",
          "user_template": "Brief: {{brief}}\nPlatform: {{platform}}\nExisting headline (may be empty): {{current_headline}}",
          "variables": [
            {
              "key": "brief",
              "label": "Brief",
              "type": "textarea",
              "max_chars": 600,
              "inherits_from": "riso-layout-director:brief"
            },
            {
              "key": "platform",
              "label": "Platform",
              "type": "select",
              "options": [
                "Instagram feed",
                "LinkedIn",
                "X / Twitter",
                "Threads",
                "Pinterest",
                "Newsletter header"
              ],
              "inherits_from": "riso-layout-director:platform"
            },
            {
              "key": "current_headline",
              "label": "Current headline (optional)",
              "type": "text",
              "max_chars": 120,
              "sample": ""
            }
          ],
          "output_schema": {
            "type": "object",
            "required": [
              "variants",
              "recommended",
              "rejected_cliches"
            ],
            "properties": {
              "variants": {
                "type": "array",
                "minItems": 4,
                "maxItems": 4
              },
              "recommended": {
                "type": "integer"
              },
              "rejected_cliches": {
                "type": "array"
              }
            }
          },
          "decoding": {
            "temperature": 1.0,
            "max_output_tokens": 700,
            "response_mime_type": "application/json"
          },
          "render_target": "#headline-rack",
          "token_budget": "~350 in / ~300 out per run",
          "free_tier_cost_note": "1 request per press run."
        },
        {
          "prompt_id": "magic-reflow",
          "version": "1.0.0",
          "label": "3. Reflow to another size",
          "displaces": "Canva Pro's Magic Resize — a paid-only feature. One spec in, the same graphic re-composed for a different canvas out.",
          "best_ally": "gemini-free",
          "best_model_hint": "gemini-2.5-flash-lite",
          "why_this_model": "It must preserve a JSON spec while changing only what the aspect ratio forces. Structured-output models drift less on that task than chat-tuned ones.",
          "fallback_ally": "copy-paste-relay",
          "system": "You are the same risograph art director, now re-imposing an existing print spec onto a different canvas.\n\nYou receive a JSON spec and a target format. Return ONLY the re-imposed JSON spec, same schema, no markdown fences, no commentary.\n\nHard rules:\n1. Copy \"ink\", \"motif\", \"stat\" and the wording of \"headline\"/\"subhead\"/\"cta\" unchanged unless the target canvas cannot physically hold them.\n2. If the text will not fit the new canvas, shorten it by cutting whole words, never mid-word, and never by adding an ellipsis. Report every shortening in \"changes\".\n3. \"layout\" must change if the aspect ratio changed orientation (square to story, landscape to square). \"headline.scale\" must be adjusted so the headline still occupies 40-70% of the canvas width.\n4. \"format\" must equal the target format.\n5. \"changes\" lists what you altered and why, max 6 items, each max 20 words. If nothing changed, return an empty array.\n6. Keep \"alt_text\" accurate for the new composition.\n\nSchema of the returned object: the input schema plus one extra key \"changes\": [ string ].",
          "user_template": "Target format: {{target_format}}\n\nCurrent spec:\n{{spec_json}}",
          "variables": [
            {
              "key": "target_format",
              "label": "Reflow to",
              "type": "select",
              "options": [
                "square-1080",
                "portrait-1350",
                "landscape-630",
                "story-1920"
              ],
              "sample": "story-1920"
            },
            {
              "key": "spec_json",
              "label": "Current spec",
              "type": "readonly-json",
              "auto_from": "riso-layout-director:last_output",
              "sample": "{\"format\":\"square-1080\",\"layout\":\"editorial-stack\",\"ink\":{\"paper\":\"#F4EFE6\",\"ink1\":\"#1B4D3E\",\"ink2\":\"#E4572E\",\"accent\":\"#111111\"},\"headline\":{\"text\":\"We cancelled Canva Pro\",\"case\":\"upper\",\"weight\":900,\"scale\":1.1},\"subhead\":{\"text\":\"Nine seats, US$144 a year each, and we only used templates and resize.\"},\"stat\":{\"value\":\"US$1,296\",\"label\":\"a year, back in the studio budget\"},\"motif\":\"registration-marks\",\"alt_text\":\"Riso-style square graphic in forest green and orange on cream paper.\"}"
            }
          ],
          "output_schema": {
            "type": "object",
            "required": [
              "format",
              "layout",
              "ink",
              "headline",
              "subhead",
              "motif",
              "alt_text",
              "changes"
            ]
          },
          "decoding": {
            "temperature": 0.4,
            "max_output_tokens": 1200,
            "response_mime_type": "application/json"
          },
          "render_target": "#press-stage",
          "token_budget": "~900 in / ~500 out per run",
          "free_tier_cost_note": "1 request per size. Reflowing one graphic into four formats costs 4 requests — still under Groq's published 1,000 RPD base limit."
        }
      ],
      "substantiation": {
        "status": "INSPECTED",
        "checked_at": "2026-09-17",
        "method": "Static construction + local render harness, plus an executed headless check: scripts/smoke-test.mjs assembles every prompt in this pack with its sample values and asserts the relay block carries the system prompt, the reader's input, the output schema and the JSON-only instruction, and that model output that arrives fenced, prose-wrapped or brace-corrupted is still parsed or honestly rejected. No live free-tier key was available in this build session, so the inference calls are labelled INSPECTED, not EXECUTED (§New-1a).",
        "claims": [
          {
            "claim": "A one-line brief produces a finished 1080px social graphic without a Canva account.",
            "verdict": "pass-with-caveat",
            "evidence": "Renderer draws any schema-valid spec to SVG and exports PNG client-side (consumer/canva-alternative.html, drawSpec()). Exercised with the sample spec; export verified by code path, not by a live model round-trip.",
            "caveat": "End-to-end run against a live Gemini/Groq free key must be recorded before this claim is upgraded to EXECUTED.",
            "label": "INSPECTED"
          },
          {
            "claim": "Reflowing one spec into four formats replaces Canva Pro's Magic Resize.",
            "verdict": "pass-with-caveat",
            "evidence": "The renderer re-composes for all four canvases from one spec; the prompt only changes what the aspect ratio forces.",
            "caveat": "Requires a live model round-trip to confirm the model preserves 'ink' and wording as instructed.",
            "label": "INSPECTED"
          },
          {
            "claim": "Nothing is uploaded to 0saas; the reader's key and output stay in their browser.",
            "verdict": "pass",
            "evidence": "assets/0saas-runtime.js only ever POSTs to the ally endpoints listed in data/allies.json; keys are stored under localStorage '0saas:v1:key:<ally_id>' and there is no 0saas endpoint that accepts a key.",
            "caveat": null,
            "label": "INSPECTED"
          },
          {
            "claim": "With no API key at all, every prompt still runs through a free chat product via the copy-paste relay.",
            "verdict": "pass",
            "evidence": "scripts/smoke-test.mjs executes ZeroSaas.assemblePrompt against all three prompts in this pack: the relay text contains the system prompt verbatim, a separated INPUT section, the output schema, and the 'reply with ONLY the JSON object' instruction; required variables left blank are reported to the reader instead of being silently blanked; input over its max_chars is refused rather than truncated. extractJson is executed against fenced, prose-wrapped, escaped-quote and truncated payloads.",
            "caveat": "A live relay round-trip through one free chat product, screenshot recorded, would upgrade this to EXECUTED end-to-end.",
            "label": "EXECUTED"
          }
        ]
      },
      "unlock": {
        "status": "not_yet_live",
        "price_display": null,
        "price_source": "unreconciled — no Stripe Payment Link exists",
        "reconciled_at": null,
        "stripe_payment_link": "PLACEHOLDER_FILL_AFTER_CREATING_PAYMENT_LINK",
        "stripe_price_id": null,
        "unlock_protocol": "v20-client-side-reveal",
        "free_preview_runs": null,
        "free_features": [
          "All three prompts, unlimited runs",
          "PNG export at 1080px square, 1080x1350, 1200x630 and 1080x1920",
          "SVG export of the same composition",
          "Copy any prompt to use in any model, forever"
        ],
        "planned_paid_features_not_yet_sold": [
          "Saved brand kits (multiple, not Canva Free's one 3-color kit)",
          "Batch press run: one brief, four formats, one click",
          "Print-ready PDF/X export with bleed and crop marks"
        ],
        "note": "Per §New-2c no price or buy control renders until stripe_payment_link is a real URL AND price_source is 'stripe_api'. Until then this tool is unlimited."
      },
      "seo": {
        "title_tag": "Free Canva Alternative: AI Social Graphics, No Pro Plan",
        "meta_description": "Canva Free caps you at ~20 AI uses and one 3-color Brand Kit, and Magic Resize costs US$144/year. Run these three prompts on a free-tier model instead.",
        "canonical": "https://0saas.pages.dev/consumer/canva-alternative",
        "primary_query": "canva alternative free",
        "secondary_queries": [
          "free canva alternative no watermark",
          "canva magic resize free alternative",
          "ai social media graphic generator free"
        ],
        "schema_types": [
          "SoftwareApplication",
          "FAQPage",
          "BreadcrumbList"
        ],
        "internal_links": [
          "/",
          "/consumer/grammarly-alternative",
          "/prompts/"
        ],
        "og_image": null
      },
      "design_fingerprint": "risograph proof sheet — the page is a press bed: ink swatch bar as the header, registration marks in the corners of the stage, the generate action is 'pull a proof', and a finished graphic is stamped with a misregistered overprint blot.",
      "centerpiece": "a live press bed that draws the model's JSON spec as a real riso-style graphic and exports it to PNG/SVG without a server",
      "neurochem_mechanism": "ownership-transfer-loop",
      "perspective_shift": "Before: the reader thought the template library was the product. After: they hold the three prompts that make the template library unnecessary, and the file is on their own disk.",
      "share_triggers": [
        "I made this in a browser with a free API key and no Canva account — the prompt is on the page"
      ],
      "retirement_flag": null,
      "performance_signal": null
    },
    {
      "id": "893104",
      "slug": "grammarly-alternative",
      "title": "Free Alternative to Grammarly: Change the Tone, Not Just the Typos",
      "tier": "consumer",
      "status": "live",
      "published": "2026-09-17",
      "path": "consumer/grammarly-alternative.html",
      "url": "https://0saas.pages.dev/consumer/grammarly-alternative",
      "incumbent": "Grammarly",
      "incumbent_feature_displaced": "Grammarly Pro's tone adjustment and full-sentence rewrites, plus the 100-AI-prompts-per-month generation allowance on Grammarly Free — replaced by three prompts that mark up a galley proof, shift tone without inventing facts, and draft replies.",
      "incumbent_free_limit": "US$0 plan: spelling and grammar correction, 'see your writing tone' (detection only), and 100 AI prompts/month. Excluded on Free: adjust tone, rewrite full sentences, fluency, inclusive language, citation consistency, AI-text and plagiarism detection. Grammarly Pro is US$12 (period not printed on the Pro card).",
      "displacement_brief": "Grammarly Free tells you your tone is defensive and then sells you the fix: adjusting tone and rewriting whole sentences are Pro features, and generative AI is metered at 100 prompts a month. This tool runs the same two jobs — a blue-pencil markup of your draft and a tone shift that refuses to invent facts — on a free-tier model you control, with no per-month cap from us and no text stored anywhere but your browser.",
      "disqualification_gate": {
        "requires_cross_session_persistence": "no — draft history, if the reader turns it on, lives in their own localStorage",
        "requires_third_party_auth": "no — reader-owned key or copy-paste relay",
        "requires_realtime_multiparty_sync": "no — it is an editor, not a collaboration surface; we do not claim to replace Grammarly's team features",
        "verdict": "pass — narrowed: plagiarism and AI-text detection are explicitly out of scope and the page says so",
        "narrowing_applied": "Out of scope, stated on page: plagiarism detection (needs a corpus), AI-generated-text detection (not reliable enough to sell), and the browser-extension everywhere-you-write surface (needs an extension, not a web app).",
        "checked_at": "2026-09-17"
      },
      "pricing": {
        "source_url": "https://www.grammarly.com/plans",
        "checked_at": "2026-09-17",
        "next_check_due": "2026-10-17",
        "free_tier_limit": "US$0 — spelling/grammar fixes, tone detection only, 100 AI prompts/month",
        "paid_tier_name": "Grammarly Pro",
        "paid_tier_price": "US$12 (billing period not printed on the Pro card)",
        "paid_tier_price_monthly": null,
        "field_confidence": {
          "free_tier_limit": "verified",
          "free_ai_prompt_cap": "verified",
          "paid_tier_price": "partial",
          "paid_tier_price_period": "unconfirmed"
        },
        "extraction_artifact": "data/pricing/grammarly.json",
        "receipts": []
      },
      "allies": [
        {
          "ally_id": "gemini-free",
          "role": "primary",
          "why": "A 600-word draft plus a strict schema plus exact-substring quoting needs context discipline and reliable JSON. Gemini's responseMimeType is the safest first ally."
        },
        {
          "ally_id": "groq-free",
          "role": "secondary",
          "why": "Tone shifting is re-run-until-it-sounds-right work. 30 RPM makes iteration free."
        },
        {
          "ally_id": "openrouter-free",
          "role": "tertiary",
          "why": "Reader preference; :free variants work with the same chat/completions adapter."
        },
        {
          "ally_id": "copy-paste-relay",
          "role": "floor",
          "why": "The most private path of all: the draft never leaves the reader's machine except by their own hand."
        }
      ],
      "prompt_pack": [
        {
          "prompt_id": "galley-line-edit",
          "version": "1.0.0",
          "label": "1. Blue-pencil markup",
          "displaces": "Grammarly's whole suggestion layer — but aimed at what Free cannot do: tone judgement plus full-sentence rewrites, not just typos.",
          "best_ally": "gemini-free",
          "best_model_hint": "gemini-2.5-flash",
          "why_this_model": "Exact-substring quoting is the failure point of every markup tool. A strict-JSON model with a large enough window to hold the draft twice (once to read, once to quote) keeps anchors findable.",
          "fallback_ally": "groq-free",
          "system": "You are a line editor marking up a galley proof with a blue pencil. You annotate the writer's text. You never rewrite it wholesale and you never add facts.\n\nReturn ONLY one JSON object matching this schema. No markdown fences, no commentary.\n\n{\n  \"tone\": {\n    \"detected\": string (2-5 words),\n    \"confidence\": number 0.0 to 1.0,\n    \"dimensions\": { \"formal\": 0-10, \"confident\": 0-10, \"warm\": 0-10, \"concise\": 0-10 }\n  },\n  \"issues\": [\n    {\n      \"quote\": string,\n      \"category\": \"grammar\" | \"clarity\" | \"tone\" | \"concision\" | \"punctuation\",\n      \"severity\": \"must-fix\" | \"worth-it\" | \"style\",\n      \"why\": string (max 25 words),\n      \"fix\": string\n    }\n  ],\n  \"rewrites\": [\n    { \"quote\": string, \"rewrite\": string, \"goal\": string (max 12 words) }\n  ],\n  \"summary\": string (max 40 words),\n  \"score\": { \"overall\": 0-100, \"breakdown\": { \"correctness\": 0-100, \"clarity\": 0-100, \"tone_fit\": 0-100 } }\n}\n\nHard rules:\n1. Every \"quote\" must be an EXACT substring of the draft, copied character for character, 3 to 90 characters long, and unique within the draft. If you cannot copy it exactly, do not report the issue. An unfindable quote is worse than no quote.\n2. Report at most 12 issues. Rank by severity and cut the rest. An empty array is the correct answer for clean text.\n3. \"fix\" replaces only that substring. It must never change a name, number, date, or claim. If a claim looks unsupported, raise a \"clarity\" issue whose fix keeps the claim and softens its certainty — never delete it.\n4. \"rewrites\" holds 1 to 3 full-sentence rewrites. Each \"quote\" there is one complete sentence, 20 to 200 characters, exact.\n5. Judge \"tone_fit\" against the target tone given in the user message, not against a house style.\n6. Never praise the draft. \"summary\" names the single biggest problem, or states that there is none.\n7. Write your output in the language of the draft.",
          "user_template": "Target tone: {{target_tone}}\nIntended reader: {{audience}}\n\nDraft:\n\"\"\"\n{{text}}\n\"\"\"",
          "variables": [
            {
              "key": "text",
              "label": "Your draft",
              "type": "textarea",
              "max_chars": 8000,
              "sample": "Hi Dana, I just wanted to quickly circle back on the invoice for the Meridian rebrand, which was sent over on August 14th for $4,850. I completely understand if things are busy on your end, but I was wondering if maybe there might possibly be an update on when payment could potentially be processed? Sorry to be a pain about it — I know these things happen. Thanks so much!"
            },
            {
              "key": "target_tone",
              "label": "Target tone",
              "type": "text",
              "max_chars": 80,
              "sample": "calm, direct, collegial — no apologising for existing"
            },
            {
              "key": "audience",
              "label": "Who reads it",
              "type": "text",
              "max_chars": 120,
              "sample": "a client's accounts payable lead who is three weeks late and has been emailed twice already"
            }
          ],
          "output_schema": {
            "type": "object",
            "required": [
              "tone",
              "issues",
              "rewrites",
              "summary",
              "score"
            ],
            "properties": {
              "tone": {
                "type": "object",
                "required": [
                  "detected",
                  "confidence",
                  "dimensions"
                ]
              },
              "issues": {
                "type": "array",
                "maxItems": 12
              },
              "rewrites": {
                "type": "array",
                "minItems": 1,
                "maxItems": 3
              },
              "summary": {
                "type": "string"
              },
              "score": {
                "type": "object",
                "required": [
                  "overall",
                  "breakdown"
                ]
              }
            }
          },
          "decoding": {
            "temperature": 0.3,
            "max_output_tokens": 2000,
            "response_mime_type": "application/json"
          },
          "render_target": "#galley-stage",
          "token_budget": "~1,400 in / ~1,100 out for a 200-word draft",
          "free_tier_cost_note": "1 request per markup. A 1,000-word draft is roughly 3 requests' worth of tokens at Groq's published 8K TPM."
        },
        {
          "prompt_id": "tone-shift",
          "version": "1.0.0",
          "label": "2. Tone shift",
          "displaces": "Grammarly Pro's 'Adjust your writing tone' and 'Rewrite full sentences with a click' — both explicitly unavailable on Grammarly Free.",
          "best_ally": "groq-free",
          "best_model_hint": "openai/gpt-oss-120b",
          "why_this_model": "Tone shifting is a tight, constrained rewrite you will re-run several times. Low latency at 30 RPM beats a bigger model you will only run once.",
          "fallback_ally": "gemini-free",
          "system": "You shift the tone of a passage without changing what it says.\n\nReturn ONLY one JSON object. No markdown fences, no commentary.\n\n{\n  \"rewritten\": string,\n  \"preserved_facts\": [ string ],\n  \"changes\": [ { \"from\": string, \"to\": string, \"dimension\": \"formality\" | \"confidence\" | \"warmth\" | \"concision\" } ],\n  \"refusals\": [ string ]\n}\n\nHard rules:\n1. Preserve every number, name, date, currency amount, and factual claim exactly. List each in \"preserved_facts\".\n2. If the target tone cannot be reached without inventing a fact, omit that move and describe what you would have had to invent in \"refusals\".\n3. Length stays within +/-20% of the input unless the target tone asks for concision, in which case shorter is fine.\n4. \"changes\" quotes the exact original substring in \"from\". Max 8 changes; report the ones that carry the tone shift, not every comma.\n5. Never add an exclamation mark, an emoji, or a greeting that was not in the original.\n6. Output language = input language.",
          "user_template": "Target tone: {{target_tone}}\nSelection to shift:\n\"\"\"\n{{selection}}\n\"\"\"",
          "variables": [
            {
              "key": "selection",
              "label": "Selection",
              "type": "textarea",
              "max_chars": 4000,
              "auto_from": "galley-line-edit:current_selection",
              "sample": "I completely understand if things are busy on your end, but I was wondering if maybe there might possibly be an update on when payment could potentially be processed? Sorry to be a pain about it."
            },
            {
              "key": "target_tone",
              "label": "Target tone",
              "type": "text",
              "max_chars": 80,
              "inherits_from": "galley-line-edit:target_tone"
            }
          ],
          "output_schema": {
            "type": "object",
            "required": [
              "rewritten",
              "preserved_facts",
              "changes",
              "refusals"
            ]
          },
          "decoding": {
            "temperature": 0.6,
            "max_output_tokens": 900,
            "response_mime_type": "application/json"
          },
          "render_target": "#shift-stage",
          "token_budget": "~500 in / ~350 out per run",
          "free_tier_cost_note": "1 request per shift."
        },
        {
          "prompt_id": "reply-drafter",
          "version": "1.0.0",
          "label": "3. Reply drafter",
          "displaces": "Grammarly Free's generative allowance — 100 AI prompts per month — with an unmetered equivalent for the job most people actually spend those prompts on.",
          "best_ally": "gemini-free",
          "best_model_hint": "gemini-2.5-flash-lite",
          "why_this_model": "Drafting three variants of a short reply is a schema-shaped task; a lite model in strict-JSON mode is cheaper on quota and indistinguishable here.",
          "fallback_ally": "copy-paste-relay",
          "system": "You draft replies to a message the user has pasted in.\n\nReturn ONLY one JSON object. No markdown fences, no commentary.\n\n{\n  \"incoming_read\": { \"what_they_want\": string (max 20 words), \"tone_detected\": string (2-5 words), \"risk\": string (max 20 words) },\n  \"drafts\": [\n    { \"angle\": \"accept\" | \"decline\" | \"negotiate\", \"subject\": string (max 60 chars) or null, \"body\": string, \"words\": integer }\n  ],\n  \"do_not_say\": [ string ]\n}\n\nHard rules:\n1. Exactly 3 drafts, one per angle. Each body is 40 to 120 words unless the user asks for shorter.\n2. Never invent a commitment, price, date, or availability the user did not supply. If an angle requires one, write the draft with a single [BRACKETED SLOT] the user must fill, and list it in \"do_not_say\" as a thing not to guess.\n3. No exclamation marks. No \"I hope this email finds you well\". No apology for the delay unless the user says there was one.\n4. \"do_not_say\" lists three phrases that would make the reply worse and why, each max 20 words.\n5. Output language = the language of the incoming message.",
          "user_template": "What I want out of the reply: {{intent}}\nFacts I can commit to (may be empty): {{facts}}\n\nIncoming message:\n\"\"\"\n{{incoming}}\n\"\"\"",
          "variables": [
            {
              "key": "incoming",
              "label": "The message you received",
              "type": "textarea",
              "max_chars": 4000,
              "sample": "Hey — love the rebrand direction but we need to stretch the budget. Could you do the whole thing for $3,600 instead of $4,850? We'd pay upfront. Let me know by Friday."
            },
            {
              "key": "intent",
              "label": "What you want out of the reply",
              "type": "text",
              "max_chars": 200,
              "sample": "hold the price, offer a smaller scope instead, keep the relationship warm"
            },
            {
              "key": "facts",
              "label": "Facts you can commit to (optional)",
              "type": "textarea",
              "max_chars": 400,
              "sample": "I can drop the style-guide PDF and one revision round to reach $3,900. I cannot go below that. Delivery stays at October 3."
            }
          ],
          "output_schema": {
            "type": "object",
            "required": [
              "incoming_read",
              "drafts",
              "do_not_say"
            ],
            "properties": {
              "drafts": {
                "type": "array",
                "minItems": 3,
                "maxItems": 3
              }
            }
          },
          "decoding": {
            "temperature": 0.8,
            "max_output_tokens": 1400,
            "response_mime_type": "application/json"
          },
          "render_target": "#draft-rack",
          "token_budget": "~600 in / ~800 out per run",
          "free_tier_cost_note": "1 request per draft set. Grammarly Free meters the same job at 100 prompts/month."
        }
      ],
      "substantiation": {
        "status": "INSPECTED",
        "checked_at": "2026-09-17",
        "method": "Static construction plus an executed headless harness: scripts/smoke-test.mjs loads the shipped assets/0saas-runtime.js into a bare VM and runs ZeroSaas.anchorQuotes / ZeroSaas.applyQuoteFix against the SAMPLE_DRAFT that ships in consumer/grammarly-alternative.html, using an 8-issue model response that deliberately contains a duplicate quote, a paraphrased (unfindable) quote and an overlapping quote. 26 assertions pass. No live free-tier key was available in this build session, so the inference round-trips stay INSPECTED (§New-1a).",
        "claims": [
          {
            "claim": "The markup lands on the exact words in the reader's draft, not approximate offsets.",
            "verdict": "pass",
            "evidence": "scripts/smoke-test.mjs executes the shipped anchoring code headlessly: every anchored range slices back to its own quote verbatim; a quote missing one comma is reported as unanchored rather than approximated; a second issue quoting the same words reports 'already marked'; an overlapping quote is dropped; model-invented start/end/offset fields are ignored; and the anchor → accept fix → re-anchor loop still points at the exact words after the draft changes. consumer/grammarly-alternative.html delegates to the same functions, so the tested code is the shipped code.",
            "caveat": "The DOM paint of those ranges (renderMarkup) and the live model round-trip remain INSPECTED; the anchoring algorithm itself is EXECUTED.",
            "label": "EXECUTED"
          },
          {
            "claim": "Tone can be changed, which is the specific thing Grammarly Free refuses to do.",
            "verdict": "pass-with-caveat",
            "evidence": "Prompt 2 returns a rewritten passage plus preserved_facts and refusals, and the UI shows refusals rather than hiding them.",
            "caveat": "Needs one live round-trip on a free-tier key to move from INSPECTED to EXECUTED.",
            "label": "INSPECTED"
          },
          {
            "claim": "The draft is never stored by 0saas.",
            "verdict": "pass",
            "evidence": "No POST to any 0saas route occurs in the editor path; the only network calls are to the ally endpoint the reader chose, plus the optional /api/refresh-pricing GET for the comparison table. scripts/smoke-test.mjs asserts headlessly that no client file references a 0saas inference endpoint and that no secret-shaped string appears in client code.",
            "caveat": "Server-side log retention on the deployed Pages project was not audited in this session.",
            "label": "INSPECTED"
          }
        ],
        "out_of_scope_disclosed_on_page": [
          "Plagiarism detection (needs a corpus we do not have)",
          "AI-generated-text detection (not reliable enough to claim)",
          "An everywhere-you-write browser extension (this is a page, not an extension)"
        ]
      },
      "unlock": {
        "status": "not_yet_live",
        "price_display": null,
        "price_source": "unreconciled — no Stripe Payment Link exists",
        "reconciled_at": null,
        "stripe_payment_link": "PLACEHOLDER_FILL_AFTER_CREATING_PAYMENT_LINK",
        "stripe_price_id": null,
        "unlock_protocol": "v20-client-side-reveal",
        "free_preview_runs": null,
        "free_features": [
          "Unlimited markups of drafts up to 8,000 characters",
          "Tone shift on any selection",
          "Reply drafter with three angles",
          "Export the marked-up draft as Markdown or plain text",
          "All three prompts, copyable, forever"
        ],
        "planned_paid_features_not_yet_sold": [
          "Saved house style (a fourth prompt slot that every run inherits)",
          "Local draft history in your browser with named versions",
          "Bulk pass over a whole document, section by section"
        ],
        "note": "Per §New-2c no price or buy control renders until stripe_payment_link is a real URL AND price_source is 'stripe_api'."
      },
      "seo": {
        "title_tag": "Free Grammarly Alternative: Change Tone, Not Just Typos",
        "meta_description": "Grammarly Free shows your tone but cannot change it, and caps AI at 100 prompts/month. Mark up and rewrite your draft on a free-tier model, in your browser.",
        "canonical": "https://0saas.pages.dev/consumer/grammarly-alternative",
        "primary_query": "grammarly alternative free",
        "secondary_queries": [
          "free grammarly alternative tone",
          "grammarly free vs pro rewrite sentences",
          "ai writing editor no subscription"
        ],
        "schema_types": [
          "SoftwareApplication",
          "FAQPage",
          "BreadcrumbList"
        ],
        "internal_links": [
          "/",
          "/consumer/canva-alternative",
          "/prompts/"
        ],
        "og_image": null
      },
      "design_fingerprint": "printer's galley proof — newsprint column with a blue-pencil margin, the draft set in a paper column, issues filed as margin slips with a string-tied hole punch, and the accept action physically strikes the slip through with a rule.",
      "centerpiece": "an inline markup engine that anchors each model-reported issue to an exact substring of the reader's own draft and lets them accept or reject it in place",
      "neurochem_mechanism": "ownership-transfer-loop",
      "perspective_shift": "Before: the reader accepted that seeing their tone was free but changing it cost $12/month. After: they watch their own draft get rewritten by a prompt they can copy and keep.",
      "share_triggers": [
        "Grammarly Free would tell me my email sounded defensive and then charge me to fix it. This did it for nothing."
      ],
      "retirement_flag": null,
      "performance_signal": null
    }
  ]
}
