recommend — flow discovery for new apps

No Playwright tests yet? Point Specreel at your running app and it will crawl it, suggest demo-worthy flows, and scaffold a runnable Playwright script — so you go from "an app" to "a gallery" without writing the first flow by hand.

specreel recommend http://localhost:3000 --max 10
  crawling http://localhost:3000 (max 10 pages, server HTML) ...
  found 6 pages → 5 suggested flows:

    1. [form] Fill the Sign up form  (http://localhost:3000/signup · 2 field(s))
         type "demo@example.com" into "Email"; type a password into "Password"; stop there: the form is NOT submitted and nothing is sent
    2. [form] Fill the Trip calculator form  (http://localhost:3000/calculator · 2 field(s))
         type the date 60 days ago into "Entry date"; type the date 40 days ago into "Exit date"; stop there: …
    3. [search] Search on Docs  (http://localhost:3000/docs · 1 field(s))
         type "Webhooks" into "Search docs"; press Enter and show the search results
    4. [nav] Open Blog  (http://localhost:3000/blog)
         click the first item listed under /blog/ (at crawl time: "Launch week recap") and show its page; scroll down that page
    5. [nav] Open Pricing  (http://localhost:3000/pricing)
         scroll down the page
  scaffolded -> specreel_flows.py
  edit the TODOs, then:  python specreel_flows.py && specreel test-results -o site --bundle

What it does

  1. Crawls the app, same-origin, breadth-first (stdlib urllib + html.parser).
  2. Maps each page: title, headings, forms (+ fields and their labels), inputs outside any form, search boxes, links (and which ones are page chrome).
  3. Ranks candidate flows: forms > search > nav.
  4. Scaffolds a Playwright script with tracing on, real selectors, and the values each flow types — each flow writes test-results/<slug>/trace.zip.

What each flow shows

Every suggestion should show the product doing something, and stay read-only: - Values come from the site. A search types something the site itself lists (the first item of its biggest list of products / categories / articles), so the demo lands on results, not "No matching results". A field types the example its placeholder or label gives ("e.g. eggs, spinach, rice" → eggs, spinach, rice), or a value of the kind its label asks for. Never test or Sample text. Dates are relative to the day the flow runs (a calculator demo doesn't age), and a field that already holds a value (a default) keeps it. - A page's tool is a flow. Inputs outside any <form> — a calculator, an ingredients box, a chat prompt — are filled in like a form (never on a settings/profile page, where such inputs tend to autosave). - A page visit opens one real item. When the page lists same-site items, the flow clicks the first one (a[href^="/blog/"]:visible — whichever is first on the day, so a new post doesn't break tomorrow's run), checks it landed, and scrolls it. Never page chrome, a new tab, or a link that acts (cart, sign-out, delete…). - Nothing is submitted. Forms are filled and left — the submit click is a TODO only you can decide. A site-wide header search or footer form becomes one flow, not a reason to skip every page's own visit. - A page that is a bot check (Cloudflare's "Just a moment...") is never a flow; if that is all the crawl sees, recommend says so instead of demoing it.

--json reports each flow's does (these steps) and its fields' values.

The full loop

specreel recommend http://localhost:3000   # 1. suggest + scaffold
# (edit the TODOs in specreel_flows.py — add assertions / clicks you care about)
python specreel_flows.py                             # 2. run -> test-results/*/trace.zip
specreel test-results -o site --bundle     # 3. render the gallery

Options

  • --max N — pages to crawl (default 12).
  • --lang py|js — scaffold language (auto-detected: package.json → js, else py).
  • -o FILE — output path.
  • --ai [--api-key KEY] — curate & rename the suggestions with AI (BYO key). It reorders and retitles the discovered flows and may pick better values for their fields — it never invents new ones. Titles describe what the recording shows ("Tour the Schengen calculator", not "Calculate your Schengen days"); a title that still promises more than its flow does is not taken.

Server HTML vs. rendered DOM

By default recommend reads the server HTML (fast, zero-dep). For client-rendered SPAs (React/Vue/etc., where the initial HTML is near-empty), add --browser to render each page with Playwright first and read the live DOM:

specreel recommend http://localhost:5173 --browser

Needs Playwright (pip install playwright && playwright install chromium) — the same thing you need to run the scaffold. If a static crawl finds nothing, the CLI tells you to retry with --browser. Use --wait <ms> to give a slow SPA more time.

Logged-in crawls

Public pages crawl out of the box. For pages behind a login, pass your session as a cookie (or a Playwright storage state, --storage-state auth.json) — it works in both static and --browser mode and reaches the app's own host only, never a site the app redirects to (an OAuth provider gets nothing; a storage state's Google / GitHub cookies are dropped). Any other header is sent with every request:

specreel recommend http://localhost:3000 --cookie "session=abc; csrf=xyz"
specreel recommend http://localhost:3000 --header "Authorization: Bearer <token>"

Grab the cookie from your browser's devtools (Application → Cookies) after logging in.

The scaffold is a starting point, not a finished suite — it leaves TODOs for the assertions and submit clicks only you can decide — but it turns a blank page into editable, runnable flows in one command.