
- Claude Code
- Codex
- Cursor
- +1
Indigo SaaS Landing
A complete dark SaaS landing page from your product facts: hero, features, pricing, FAQ. Editable HTML, one run.
18 results

A complete dark SaaS landing page from your product facts: hero, features, pricing, FAQ. Editable HTML, one run.
Use case: Product teaser (template 1) | Element | Value | |---|---| | Subject | A matte black ceramic pour-over coffee dripper with a thin polished copper rim, sitting on a clear glass carafe | | Action | 1) A thin stream of dark coffee trickles from the dripper into the carafe while soft steam curls up from the rim; 2) the dripper and carafe turn a slow quarter turn; 3) the final second holds still on the dripper's front, copper rim catching the light | | Scene | A walnut kitchen counter by a window, early morning just after sunrise, a faint haze of steam in the air, uncluttered background | | Angle / Move | Vertical close-up at counter height, slightly above eye level / slow dolly in | | Lens | 85mm-style telephoto feel, shallow depth of field, kitchen background in soft bokeh | | Light / Palette / Mood | Soft low-angle morning sunlight from a window on the left with gentle fill and a warm rim on the copper / matte black, warm copper, honey-brown walnut, soft cream highlights / calm, quiet, unhurried | | Style / Time | Premium commercial look, photorealistic / real-time pace, steady trickle throughout, still hold in the last second | | Audio | Close, clear coffee trickling into glass, a faint soft drip, quiet low morning room tone, no music | | Negative | text, logos, letters, labels, hands, people, clutter, reflections of people, plastic look | Final prompt (paste into Veo / Gemini / Flow): Premium commercial look, photorealistic, vertical close-up at counter height of a matte black ceramic pour-over coffee dripper with a thin polished copper rim, sitting on a clear glass carafe on a walnut kitchen counter by a window in the early morning just after sunrise. A thin stream of dark coffee trickles from the dripper into the carafe while soft steam curls up from the rim, and the dripper and carafe turn a slow quarter turn. Slow dolly in, 85mm-style telephoto feel, shallow depth of field with the kitchen background in soft bokeh. Soft low-angle morning sunlight from a window on the left with gentle fill and a warm rim light catching the copper, palette of matte black, warm copper, honey-brown walnut and soft cream highlights, calm and quiet mood. Real-time pace; the final second holds still on the dripper's front. Audio: close, clear sound of coffee trickling into a glass carafe, a faint soft drip, quiet low morning room tone, no music. Negative prompt: text, logos, letters, labels, hands, people, clutter, reflections of people, plastic look Settings: 9:16, 8 seconds, audio on.
Use it to turn a rough video idea into a structured Veo prompt with a filled anatomy table, camera, lens, light, audio and a negative prompt.
> Assumption: signed-in users read their own orders and create their own orders as `pending`; every status change after that is made by your server with the `service_role` key, never by the browser. Audit: `public.orders` (about 1.8M rows) Rule files applied: `security-rls-basics`, `security-rls-performance`, `security-privileges`, `schema-foreign-key-indexes`, `query-missing-indexes`, `query-composite-indexes`, `schema-data-types`, `schema-constraints`, `lock-short-transactions`, `monitor-explain-analyze`. Findings, by rule (first 6 of 12) | # | Severity | Rule | Finding | |---|---|---|---| | 1 | CRITICAL | `security-rls-basics` | `orders_insert ... with check (true)` lets anyone who can insert write an order for any `user_id`. Combined with finding 2, an anonymous visitor holding only your public anon key can create orders on behalf of any user. | | 2 | CRITICAL | `security-privileges` | `grant select, insert, update ... to anon`. Orders belong to signed-in users, so `anon` needs no privilege at all. None of the three policies has a `to` clause, so each applies to every role, including `anon`. | | 3 | HIGH | `security-privileges` | `authenticated` can `update` every column of its own rows: the owner can still run `update orders set status = 'paid', total_cents = 1` from the browser. | | 4 | HIGH | `security-rls-basics` | The insert path also trusts `status`: a client can insert a row that is already `status = 'paid'`. | | 5 | HIGH | `security-rls-performance` | All policies call `auth.uid()` bare, so it is evaluated per row. Wrap it as `(select auth.uid())` so it is evaluated once per statement. | | 6 | HIGH | `schema-foreign-key-indexes`, `query-missing-indexes` | No index on `user_id`. It is the foreign key, the RLS filter column and the column every "my orders" query filters on. Each RLS-filtered select over 1.8M rows is a sequential scan. | Fixing migration (file 1 of 2, excerpt) ```sql set local lock_timeout = '5s'; revoke all on public.orders from anon; revoke update, delete, truncate, references, trigger on public.orders from authenticated; grant select, insert on public.orders to authenticated; drop policy if exists orders_select on public.orders; drop policy if exists orders_insert on public.orders; drop policy if exists orders_update on public.orders; create policy orders_select on public.orders for select to authenticated using ((select auth.uid()) = user_id); create policy orders_insert on public.orders for insert to authenticated with check ((select auth.uid()) = user_id and status = 'pending'); -- No update or delete policy: denied for every role except service_role. ``` File 2 holds only `create index concurrently if not exists orders_user_id_created_at_idx on public.orders (user_id, created_at desc);` because `concurrently` cannot run inside the transaction the Supabase CLI wraps around each migration. [The full answer continues with findings 7–12, the lock plan for 1.8M rows, the status and total_cents check constraints added `not valid` then validated, an `explain analyze` to run before and after, and one RLS test per role.]
Use it to make your coding agent follow Supabase's 31 Postgres rules for RLS, indexes, schema and migrations before it touches your database.
Settings: model `sora-2` · size `1280x720` · seconds `8` · characters: none Before A cool cinematic shot of a woman drinking coffee in a nice cafe, make it 10 seconds. After Style: Contemporary 35 mm film look, natural and understated, soft contrast, fine grain, warm-neutral grade. A small neighbourhood cafe on a quiet weekday morning. A woman in her early 30s with shoulder-length dark hair tied loosely back, wearing an oatmeal knit sweater, sits alone at a round marble table by a large street-facing window. In front of her: a white ceramic cup of black coffee on a matching saucer and a folded paper napkin. Behind her, out of focus, a wooden counter with an espresso machine and a barista moving between shelves of cups. Thin steam rises from the cup and catches the window light. Cinematography: Camera: medium close-up, eye level, from across the table at a slight angle; slow dolly-in Lens: 50 mm feel; shallow depth of field, sharp on her face and the cup, background soft Lighting: soft morning daylight through the window from camera left as key; warm tungsten pendant glow from the counter as background fill Palette anchors: cream, warm walnut brown, soft white, muted sage, coffee black Mood: calm, quiet, unhurried Actions: - She wraps both hands around the cup and lifts it slowly (first two seconds). - She blows lightly across the surface, then takes one small sip. - She lowers the cup to the saucer and looks out the window with a faint, relaxed smile (final two seconds). Background Sound: Low hiss of the espresso machine, soft clink of cups at the counter, muffled murmur of a few voices; no score. What changed and why - Removed "make it 10 seconds". Duration is an API parameter, not prose, and 10 is not a supported value (4, 8, 12, 16, 20). Set `seconds: 8` in the call; the prompt now fits 8 seconds of action. - "Cool cinematic shot" became a named style. A specific aesthetic instead of a vague adjective, set first so it frames everything else. - "Drinking coffee" became three timed beats. Lift, blow and sip, lower and look out. Beats with timing cues are far more reliable than a single vague verb. [five more changes in the full answer: subject anchors, concrete nouns, one camera move, named light sources, background sound]
Use it to write or rewrite Sora 2 prompts with the right settings, camera, timed action beats, light, dialogue and sound.

Use it to score a pricing page or in-app paywall on eleven criteria and get three ranked fixes with rewritten copy and one experiment to run.
Assumption: no n8n-MCP server is connected in this session, so I took the skill's fallback path: I wrote the workflow JSON directly from the bundled rules and checked it by review (a rule-check script plus a dry run of every expression). The real validator (`validate_workflow`) was not run, and nothing was deployed.
How the skill routed this
| Step | Sub-skill used | What it decided |
|---|---|---|
| Shape | `n8n-workflow-patterns` | Webhook processing pattern: Webhook, then Validate, then Action, then Respond |
| Node parameters | `n8n-node-configuration` | Slack post needs a channel and text. `responseMode: "responseNode"`. `options.responseCode` set on every Respond node. UUID node ids, no placeholder credentials |
| Expressions | `n8n-expression-syntax` | Webhook data lives under `.body`. Use `$('Webhook').item.json.body.*` once past the IF node. `=` prefix on every expression field |
| Error paths | `n8n-error-handling` | Slack gets `onError: "continueErrorOutput"` and its `main[1]` is wired to the 500 responder. `retryOnFail` is on. Bad input is caught upstream and gets a 400 |
| Validation | `n8n-validation-expert` | Runtime-profile checks done by review. Security warnings get fixed (header auth on the webhook) |
```
Webhook ──> Validate Input ──true──> Post to #signups ──success (main[0])──> Respond 200 OK
└──false──> Respond 400 Invalid Input
Post to #signups ──error (main[1])────> Respond 500 Slack Failed
```
Validation result (excerpt)
```
PASS Webhook responseMode is responseNode (Respond nodes control the reply)
PASS Every branch (success and each error) ends at a Respond to Webhook node: no hanging branch
PASS 'Post to #signups': onError=continueErrorOutput AND main[1] wired
PASS 'Post to #signups': retryOnFail with maxTries <= 5 and waitBetweenTries <= 5000
PASS Every {{ }} field starts with = (no 'Expression requires = prefix' error)
PASS Webhook fields read from .body, never $json.name / $json.email / $json.plan
…
43 passed, 0 failed
```
Expression dry run against sample webhook items:
```
valid IF -> true (Slack) Slack text: New signup: Ana Lima (ana@example.com) on pro
missing_plan IF -> false (400)
bad_email IF -> false (400)
no_body IF -> false (400)
500 body: {"error":"upstream_error","message":"The signup was received but could not be posted to Slack. Please retry later."}
```
Not verified without the server: the node typeVersions (Webhook 2.2, IF 2.3, Slack 2.3, Respond 1.5) and the Slack v2 parameter names; confirm by opening the nodes after import.
[The full answer also holds the six-node list, the importable workflow JSON and the expressions table with the reason behind each one.]Use it to have your coding agent build, configure and validate n8n workflows without the usual expression and node-config mistakes.

Use it to turn an image brief into a GPT Image prompt, with exact on-image text and the right size and quality settings.
2. Tool design
| Tool | Does | Inputs (constraints) | Returns | Read-only / destructive | Errors the model can fix |
|---|---|---|---|---|---|
| `find_customers` | Customers whose name or email contains the text, case-insensitive | `query` string 1–100 (trimmed), `limit` int 1–50 = 20, `cursor` optional | id, name, email; `next_cursor` | read-only, idempotent | no match: try a shorter part of the name or the email domain |
| `list_customer_orders` | One customer's orders, newest first | `customer_id` int ≥ 1, `status` enum optional, `limit`, `cursor` | customer + orders; `next_cursor` | read-only, idempotent | unknown customer: call `find_customers` |
| `get_order` | One order with the customer's name and email | `order_id` int ≥ 1 | order + customer (structured) | read-only, idempotent | not found: check the number or list the customer's orders |
| `refund_order` | Sets a paid order to refunded | `order_id` int ≥ 1, `confirm` int optional, must equal `order_id` | updated order, `previous_status: "paid"` | destructive, idempotent | no `confirm`: preview, ask the user; order pending or already refunded; not found |
Checklist notes: one rule for empty results (an `isError` result with a next step), applied to every tool. All SQL is parameterized. Read tools use a read-only SQLite handle; only `refund_order` opens a writable one, and its `UPDATE ... WHERE id = ? AND status = 'paid'` is a single statement. The guard on the destructive tool is server-side (the preview/confirm step), not just the `destructiveHint` annotation.
3. Scaffold
From `templates/typescript-server.md`. Installed: `@modelcontextprotocol/server` 2.4.0, `@modelcontextprotocol/client` 2.4.0, `zod` 4.6.7; Node 24.6.0.
```
build-an-mcp-server/
data/seed.sql, data/shop.db 3 customers, 5 orders
src/index.ts stdio entry point
src/server.ts createServer(): the four tools
src/shop.ts SQLite client module (the system being wrapped)
test/smoke.ts spawns the server over stdio, calls every tool
```
5. Test (Inspector CLI, eval loop layer 2)
```
$ npx @modelcontextprotocol/inspector --cli npx tsx src/index.ts --method tools/call --tool-name get_order --tool-arg order_id=1001
{
"content": [{ "type": "text", "text": "Order #1001 for Ada Lovelace <ada@example.com>: $49.99, paid, created 2026-10-02T09:15:00Z" }],
"structuredContent": { "order": { "id": 1001, "customer_id": 1, "total_cents": 4999, "status": "paid", "created_at": "2026-10-02T09:15:00Z", "customer_name": "Ada Lovelace", "customer_email": "ada@example.com" } }
}
```
Built, tested, not tested
- Built: four tools over `data/shop.db`, server-side preview/confirm guard on `refund_order`, smoke test, configs for Claude Code, Codex and Cursor, README.
- Tested: starter smoke (pass), full smoke test 14 checks (pass), strict typecheck (pass), Inspector CLI call (pass), seed database unchanged after tests.
- Not tested: the Inspector web UI by hand and the model check (running the five real requests through a live Claude Code session and recording which tool it picks).
[The full answer also holds `src/shop.ts`, `src/server.ts`, `test/smoke.ts` and the three client config snippets.]Use it to design, build, test and ship an MCP server your agents use well: 3 to 7 well-designed tools, a tested starter and ready client configs.

Idea to approved design to test-first plan to working code, with an approval gate between each stage.

Audit a live page that isn't converting: a 7-point scorecard, quick wins, test ideas and before/after copy.

24 named design moves for your coding agent: bolder, quieter, typeset, distill, polish, plus a heuristic critique and a technical audit.

Your agent writes launch films, explainers and social clips as HTML, CSS and GSAP scenes, checks them, and renders identical MP4s.

Your agent interviews you about a plan until nothing is assumed, then writes the spec and tracer-bullet tickets.

Makes your agent plan a design for your subject, check it against the generic AI look, then build. No cream-and-terracotta defaults.

One-line brief in, full design system out: page pattern, style, colour tokens, font pairing and anti-patterns from a local database.

Strips AI tells from a draft without inventing a new voice: quoted flags, a clean rewrite, a second-pass check.
Short answer: ChatGPT can't recommend Ledgerly, because nothing it can retrieve says Ledgerly exists. Even after launch, a single landing page is not enough. A "best X for Y" shortlist comes from web-wide consensus (reviews, roundups, forums, press), not from your own site.
Visibility ladder (retrieved → cited → mentioned → recommended)
| Rung | Ledgerly today | What governs it |
|---|---|---|
| 1. Retrieved | No: not live, not in Bing's index (ChatGPT search draws from a Bing-based index) | Being indexed and crawlable |
| 2. Cited | No | Extractable, factual, fresh pages |
| 3. Mentioned | No | Entity recognition; the web talking about you |
| 4. Recommended | No | Aggregate third-party consensus, largely independent of your own content |
Source pool (one web search for the exact query, 2026-11-07; not a ChatGPT answer): only third-party roundups and affiliate lists (NerdWallet, business.org, Zapier, Fueler, Techjockey, Aspire). The same five apps recur: Wave, Zoho Books, FreshBooks, QuickBooks, Xero. I did not run ChatGPT, so I'm not reporting what ChatGPT says; run the query list yourself.
Extractability check on site/index.html: clear definition in the first paragraph, partial (the H1 is a slogan); self-contained answer blocks, fail; statistics with sources, fail; comparison table for "vs" queries, fail; FAQ, partial (good answers hidden in collapsed <details>, none answers "Is Ledgerly good for freelancers?"); schema markup, fail; author or founder, fail; freshness date, fail; query-shaped headings, fail.
Top fixes, by impact against effort
1. Launch, then get indexed in Bing and Google. robots.txt with a wildcard allow plus explicit allows for OAI-SearchBot, PerplexityBot, Claude-SearchBot and Bingbot; decide training crawlers (GPTBot, ClaudeBot) separately.
2. Seed third-party consensus: G2 and Capterra listings with the first 20–30 real reviews; pitch the roundups that already rank for the query with a specific angle ("$12/month, no per-transaction fees, automatic invoice chasing"). Test: if a model ignored your own domain, would the web still put you on the list? Today, no.
3. Rewrite the hero into an extractable definition (below).
4. Add /vs/freshbooks, then QuickBooks and Wave, in the "fair source" pattern. Do not publish a self-ranked "best bookkeeping apps" listicle: in the skill's data 69% of such citations recommended competitors.
5. Publish /pricing.md and /llms.txt; fix the Studio button ("Talk to us" on a plan with a public price reads as a sales wall to an agent).
6. JSON-LD: Organization, SoftwareApplication with Offer per plan, FAQPage.
7. Buyer-intent FAQs rendered open in the HTML. 8. Named founder, "Last updated", one dated sourced number. 9. Measure monthly: 8 queries, 3–5 runs per engine, log rung and framing.
Hero answer block (57 words, every fact from the existing page):
> Ledgerly is a bookkeeping app for freelancers and two-person studios. It connects to your bank through Plaid or TrueLayer (US, UK, EU), auto-categorises each transaction by category and client, chases unpaid invoices on day 3, 7 and 14, and exports tax-ready P&L, VAT and quarterly estimates. Free plan available; Pro is $12/month with no per-transaction fees. […]Get cited in AI Overviews, ChatGPT and Perplexity: visibility audit, crawler check, ranked fixes, answer-block rewrites.

Turns the commits since your last tag into user-facing release notes, grouped and in your voice.