Skip to content

feat: read your own site and draft your profile - #24

Merged
ralyodio merged 1 commit into
mainfrom
feat/onboarding-profile
Aug 13, 2026
Merged

ralyodio merged 1 commit into
mainfrom
feat/onboarding-profile

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

feat: read your own site and draft your profile

The setup step: paste your URL, a model reads the page, and you get back
a draft of your business — what you sell, who plausibly buys it, how you
write, and where those buyers are active. You correct it, then save.

The mirror image of the crawler that reads a prospect's site. Same fetch
and the same text extraction; the difference is whose page it is and what
comes out. There the page yields leads, here it yields the workspace's
own offering, ICP and voice.

Three tables that already existed and nothing ever filled — offerings,
campaign_filters and voice_profiles. Until now the only writer was
the test seed, and the campaign bootstrap created an offering literally
named "Your offering" whose description read "Describe what you sell
here" — which is the text every draft was then grounded in.

Verified email is required before the model runs, and the test asserts
the gate sits in front of the spend rather than in front of the reply: an
unverified signup that still burned a call would be an invitation to do
it a thousand times.

Nothing is written by the draft call. What comes back is a model's
reading of a marketing page — a starting point, not a fact about someone's
business — so it is rendered as editable fields and PUT is what commits
it. Saving twice corrects the profile rather than creating a rival one,
because this is a step people re-run after changing their site.

"Configured" keys off the voice profile, since only completing setup
creates one. The first version compared the offering's name to the
literal string "Your offering", which is the kind of check that stops
working the day somebody edits the bootstrap copy.

The contact scraper stays. It is a different job — mining other people's
sites for leads — and worth keeping.

11 new tests, 480 total.

Known limit, stated rather than hidden: this needs the Anthropic key,
which is capped until 2026-09-01. Until then the route answers 502 with

The setup step: paste your URL, a model reads the page, and you get back
a draft of your business — what you sell, who plausibly buys it, how you
write, and where those buyers are active. You correct it, then save.

The mirror image of the crawler that reads a prospect's site. Same fetch
and the same text extraction; the difference is whose page it is and what
comes out. There the page yields leads, here it yields the workspace's
own offering, ICP and voice.

Three tables that already existed and nothing ever filled — `offerings`,
`campaign_filters` and `voice_profiles`. Until now the only writer was
the test seed, and the campaign bootstrap created an offering literally
named "Your offering" whose description read "Describe what you sell
here" — which is the text every draft was then grounded in.

Verified email is required before the model runs, and the test asserts
the gate sits in front of the spend rather than in front of the reply: an
unverified signup that still burned a call would be an invitation to do
it a thousand times.

Nothing is written by the draft call. What comes back is a model's
reading of a marketing page — a starting point, not a fact about someone's
business — so it is rendered as editable fields and `PUT` is what commits
it. Saving twice corrects the profile rather than creating a rival one,
because this is a step people re-run after changing their site.

"Configured" keys off the voice profile, since only completing setup
creates one. The first version compared the offering's name to the
literal string "Your offering", which is the kind of check that stops
working the day somebody edits the bootstrap copy.

The contact scraper stays. It is a different job — mining other people's
sites for leads — and worth keeping.

11 new tests, 480 total.

Known limit, stated rather than hidden: this needs the Anthropic key,
which is capped until 2026-09-01. Until then the route answers 502 with
the model's own reason, and the page says to fill it in by hand.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit a85fb37 into main Aug 13, 2026
4 checks passed
@ralyodio
ralyodio deleted the feat/onboarding-profile branch August 13, 2026 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant