SpecStream fetches structured web data rows into your Convex database on demand: describe what you need in plain text, cap the spend, and subscribe to results a
npm install @specstream/convexThe SpecStream Convex component exposes a findList action that accepts a plain-text request, a row count, and a price cap. It resolves the request against live web pages and writes each matching row into your Convex tables as it finds them. Your UI subscribes to results using usePaginatedQuery against your own query that calls specstream.listRows.
Call specstream.findList from a Convex action with a description like 'roofers in Columbus rated 4.5 or better, with a phone number'. Rows land in your database as SpecStream finds them, each carrying the source URL it was read from. You can show the price to the user first with specstream.quote and specstream.approve before any work runs.
Wrap specstream.findList in a tool exposed to your Convex agent. The agent provides the plain-text request and row count, while your code sets the maxPriceUsd ceiling so the agent cannot overspend. Results are paginated Convex rows the agent or your app can query immediately.
Call specstream.findList from a Convex scheduled function, one list per category or city. Pass an onComplete internal mutation to receive a callback with the final row count and status once the list reaches a terminal state. The component tracks each list until it is done and retries transient failures automatically.
SpecStream charges only for rows that match your request. A search that finds nothing costs nothing. You set a maxPriceUsd ceiling in your code, and the list will not start if the estimated maximum exceeds that ceiling. A free account starts with $10 of credit and does not require a card.
No. Convex components cannot access ctx.auth, so authentication, authorization, and rate limiting are the responsibility of your application code. The README explicitly recommends keeping an owner table that maps lists to users, and checking that table before allowing any list to be read, canceled, or deleted.
Each row includes a sourceUrl pointing to the page it was read from, an observedAt timestamp, an ordinal position, and a cells array where each cell carries its own sourceUrl, label, display value, and observedAt. If a source does not publish a value, the display field is empty and an absence reason is provided. Values are never guessed or inferred.
Pass an onComplete internal mutation reference to findList or approve. SpecStream calls that mutation once when the list reaches a final state such as completed, partial, failed, canceled, or expired, and passes back the listId, row count, status, and any context object you provided. Optionally, mount the webhook HTTP route so SpecStream can push completion events to your deployment immediately rather than waiting for the polling interval.
The package ships a test module at @specstream/convex/test compatible with the convex-test library. Import it and call specstream.register(t) to wire the component into your test environment, then stub fetch for api.specstream.ai to return fixture responses. The example app in the repository includes a full test suite covering quote, approve, and row reading.