A website offer where the owner's only job is to approve the result — eight releases in 136 days.
amysoft-ai.online sells owned websites to local businesses that have earned a reputation on platforms they don't own. We built the marketing site that sells the offering from an empty repository to v0.5.0 in 136 days: Astro 7 static output, MDX content collections validated by Zod, eleven supporting pages, an inquiry form on a shared relay, and a release pipeline that refuses to publish an image with a HIGH CVE. 980 commits, 159 merged PRs, median 12.9-minute time-to-merge.
A personal chef, a cleaner or a contractor can have dozens of reviews and a feed full of photos and still have no address of their own. The usual website project opens with homework: create an account, buy a domain, write the copy, send the photos. Busy owners don't finish it. The work was to build a site that explains a different deal — we build the finished site from the public footprint the business already has, the owner reads it and approves it, and the domain and content belong to the business — and to make that site trustworthy enough to sell it.
A production marketing site on amysoft-ai.online. Astro 7 static output behind Traefik, one nginx image with Brotli and a dual-track CSP. A thirteen-section home page ported from a frozen design handoff. Eleven supporting pages in a typed collection, each with a sitemap entry, an llms.txt entry and JSON-LD, including the From Scratch by Ramona customer story. A seven-field inquiry form posting to the studio's shared form relay. Two published prices. First release tag on day 7, the redesign shipped across four planning cycles, v0.5.0 on day 136.
What we built, and how fast
amysoft-ai.online is the storefront for owned websites for local businesses: we capture what a business has already shown in public, build the complete site from it, and ask the owner one question — is this right? The positioning, the five steps and the two delivery models are written up as the Owned Websites product concept. The site itself is an Astro 7 static build on the studio's starter base: a thirteen-section home page, eleven supporting pages under /visibility/, /who-its-for/ and /ownership/, a /faq/ page, and an inquiry form that posts to the shared relay.
The build is the receipt. From first commit b1f3419 on 2026-06-07 to the v0.5.0 tag on 2026-10-21 was 136 days. 980 commits reachable from v0.5.0, 159 merged PRs, 159 of 160 human-authored PRs merged, median 12.9-minute time-to-merge, eight release tags. The pace was not even: 723 of the 980 commits landed in the last 43 days, after a seven-week detour into a lead pipeline that was built, then deliberately deleted.
Who it's for, and what was at stake
The audience is local owner-operators — food businesses, trades, services — whose reputation lives on a marketplace profile, an Instagram grid or a business listing. They are not short of interest; they are short of time. The first real customer, From Scratch by Ramona, was asked to create an account, buy a domain, gather content and send photos, and none of it got done. The offering exists because of that: the owner's part is to review a finished site, not to produce one. The marketing site has to say that plainly, price it plainly, and prove it with a real story.
Three constraints shaped the build. The site had to stay static — no server routes, no database — so it could ship as one nginx image behind Traefik. The redesign came as a frozen design handoff (ADR-0006), so every section had to match a reference rather than be reinvented. And every claim on the page had to pass messaging guardrails, later made reusable by the generated customer sites, so the marketing copy and the product could not drift apart. The concept page sets out the full offer: Owned Websites.
Two tools, neither finishing the job
A site builder or template, filled in by the owner
The cheap path, and the one the first customer was actually offered. It assumes the owner will write copy, pick photos and wire a domain. The log of this offering's own first approach says otherwise: the account was never created and the domain never bought. A template also flattens what makes a local business findable — every service and every area served, stated plainly — into a hero image and three cards.
An agency rebuild, or staying on the platform
An agency produces a finished site, but it starts with a discovery workshop the owner has no time for and often ends with the domain and the hosting account in the agency's name. Staying on the marketplace or the feed costs nothing up front, but the page, the layout and the rules stay the platform's. Neither gives the owner a finished property they own after a single review.
Planning cycles, a state ledger, and a release gate that blocks on HIGH CVEs
Work ran as numbered planning cycles, each a JSON work breakdown in planning/ with a state ledger that records authorizations, completed tasks and the gate run behind each story. 376 of 980 commits name a WBS story id (1A.1, 2F.3, 5C.1), and 176 are plan(...) records of the plan itself. CI ran every PR through a production audit, lint, typecheck, Vitest and Playwright against the built image; every release had to pass Trivy and build a CycloneDX SBOM before it reached GHCR.
Wrote the code red-green-refactor, one story at a time. The receipt: 709 of 807 non-merge commits carry a Claude co-author trailer, and the merged stories carry their tests with them — guardrail scans over the whole content corpus, a home-page anchor guard, a handoff-citation tripwire and an E2E test that proves the production image serves the promo video's captions as text/vtt.
Owned branches, PRs and releases. The receipt: 159 of 160 human-authored PRs merged, median 12.9 minutes from open to merge, 128 of the 159 merged within the hour, and eight tags from v0.1.0 to v0.5.0 cut through develop to master release PRs.
Each story was checked against its governing spec before an engineer was dispatched, and corrected — with an ADR when warranted — when the two disagreed. That is where most of the 31 decision records in specs/changes/ come from: ADR-0008 (the electric-lime accent measures 1.13:1 on paper, so it is a background colour only), ADR-0018 (pricing drops both CTA buttons), ADR-0030 (advertised URLs end with a slash).
Content collections, route conventions and the image pipeline stayed consistent across the cycles: a support collection with a fail-loud sitemap scan, a sitePages collection for About and Contact, and seven JSON-LD builders routed from frontmatter.
A storefront that sells approval, not homework
Astro 7 static output on amysoft-ai.online. A thirteen-section home page from a frozen handoff, eleven supporting pages, two published prices, and a real customer story. Here is what the live v0.5.0 surface looks like.
The home page opens on ownership, not features. The hero states the deal in one line — your business deserves more than a profile — beside a mock owned site tagged with search, answer and AI-discovery signals. It is the first of thirteen sections ported from the frozen design handoff in Cycle 1, with the lime accent used only as a background, per ADR-0008. Visit amysoft-ai.online.
Two delivery models, priced in public. Managed at $749 to build then $49 a year, or self-hosted at $499 one time with no annual fee. Both end with a site the business owns. The section dropped both CTA buttons in ADR-0018; the one call to action lives at the closing inquiry form.
The proof is a customer, named with permission. From Scratch by Ramona had customers, reviews and photos on Thumbtack and Instagram but no website. The supporting page tells how she came to own one without having to build it. It shipped in story 2F.3 as one of the eleven supporting pages, with article JSON-LD and a breadcrumb through the Ownership hub.
Seven phases, one deliberate detour, eight release tags
Phase boundaries are the release tags and the planning cycles in planning/. The quiet stretch in August is real: it is specs and decision records, not code.
Bootstrap and the first site
Infra workstreams first: plain HTTP behind the Traefik edge (WS-0), the image name (WS-1), the Astro 6 and Zod 4 toolchain, a dual-track CSP, Brotli, and a GHCR release pipeline with Trivy and an SBOM (WS-4). Then lettered stories A to E: a warm token palette, self-hosted fonts, the first home-page sections and the lead form. v0.1.0 was tagged on day 7. Its runtime base image failed the HIGH-CVE gate and needed a second release PR (#46).
The lead-pipeline detour
Eight lead-magnet pipeline specs landed on Jun 18. Cycle 1 built a POST /api/lead intake with a Haiku fit gate; Cycle 2 built a WIP ledger. Two merged PRs were reverted with GitHub's revert button and re-landed the same day (#48, #64), and one was abandoned (#66). On Jul 28 the site moved to Astro 7, Tailwind 4 and TypeScript 6. On Jul 31, PR #75 removed both cycles and returned the site to pure static: the intake route had never served a production request.
The quiet stretch
The slowest window in the history, and the one that set up the fastest. The pipeline was re-specified on paper — repository-evidence stages, an inbound door, suppression keyed to a business identity — and ADR-0001 to ADR-0006 were written; ADR-0006 froze the design handoff's surface so the redesign would port a reference rather than redesign in code. The internal outline for amysoft-ai.online landed on Sep 7.
Cycle 1 — the home redesign
PR #99 planned three cycles (17, 13 and 9 stories) and opened Cycle 1 with its gate red on purpose: two entry blockers, one of them the accent lime measuring 1.13:1 on paper. Both were closed by ADR-0007 and ADR-0008 before story one. Stories 1A to 1F rebuilt the hero, the problem, proof, pricing and FAQ sections, then guarded the anchors, the palette and the handoff citations. v0.2.0 was re-cut for a base-image CVE; v0.2.1 followed the same day to match the handoff's type and colours.
Cycle 3 — the inquiry form
Run before Cycle 2. The field contract shipped first (3A.1) so the cross-repo relay work could start at once, then the form component, its submit controller, the retirement of the old lead form, the bot check and its CSP origin, and an E2E test against a stubbed endpoint. ADR-0018 removed both pricing CTA buttons. v0.3.0 shipped the form as a new relay tenant; a libexpat HIGH CVE needed one more fix (#151).
Cycle 2 — eleven supporting pages
The densest window: a support collection, three segment hubs, eleven written pages including the From Scratch by Ramona story, a messaging-guardrail checker that scans the whole corpus, one FAQ source, and About and Contact moved to their own collection. Oct 6 was the busiest day of the build at 103 commits. v0.4.0 needed a CVE fix (v0.4.1); a one-story Cycle 4 made every advertised URL end with a slash (v0.4.2) the next day.
Cycle 5 — the promo video
ADR-0031 and the vendored video assets, a PromoVideo component, composition as the thirteenth home section after the hero, and an E2E test proving the production image serves the video and its captions as text/vtt. v0.5.0 was tagged on Oct 21, the first minor release cut without a CVE follow-up.
Plan-tracked velocity, gated before every release
Every figure below is drawn from git and gh history of amysoft-ai.online, read-only, counted on the v0.5.0 tag (980 commits, 2026-06-07 to 2026-10-21). PR figures cover PRs merged on or before the v0.5.0 commit. The bar chart below shows all 50 active days.
Commits per active day — 30 of 53 calendar days
Commit-type distribution · 346 commits
Quality signals
plan(...) records of the plan itself specs/changes/ · spec-and-story disagreements resolved in writing, not in code Where the workflow needed a human
A case study that only lists wins isn't evidence. The same git history that proves the pace also marks exactly where judgment had to stay with the human.
Seven weeks went into a pipeline that was then deleted
Between Jun 18 and Jul 31, 112 commits built a lead-intake API with an LLM fit gate and a WIP ledger, then PR #75 removed both and returned the site to pure static. The removal was the right call — src/pages/api/lead.ts never served a production request, because the production image only serves the static build — but a route that could not run in production should have been caught before two cycles were built on it. The repository's ledger skill now scans src/pages/ for server routes for exactly this reason.
Four of five minor releases needed a CVE follow-up
The release scan found a HIGH CVE in the runtime image at v0.1.0 (#45, #46), v0.2.0 (#130, #131), v0.3.0 (#151) and v0.4.0 (#187, shipped as v0.4.1). The gate did its job each time, but each time the vulnerable base image was discovered at the release cut and fixed by a follow-up PR. Pull-request CI audits npm dependencies, not the image; scanning the image before release day would have moved that work earlier.
Dependabot opened 24 PRs and none were merged
Every Dependabot PR opened up to v0.5.0 was closed or left open; dependency fixes landed instead as hand-authored fix(deps) PRs that cleared the production audit gate (#153, #161, #165, #197). That keeps each bump inside the gates, but it also means automated updates are not doing the work they were enabled for.
Visual drift reached a release tag twice
v0.2.1 shipped the same day as v0.2.0 to match the frozen handoff's font stack, body ink and wordmarks (#132), even though Cycle 1 had closed with a handoff-drift story (1F.4). Cycle 4's slash fix (v0.4.2) came one day after v0.4.0. A single human account merged every PR, so CI is the backstop — and the guards in place at each cycle close caught neither slip.
What this build teaches the next one
Ask the owner to approve, never to produce
The offering's founding fact is in its own history: the first customer was given the usual list of tasks and completed none of them. Once the work was done for her, From Scratch by Ramona went live with her involvement close to nothing. Every page of the site is written around that difference, and the product concept makes it the core of the offer.
Delete a seam that cannot run, rather than keep it in case
PR #75 deleted the intake route and the ledger instead of reverting them, and recorded the recovery commit (ece9940) so the code could be ported later. The site went back to static output, the build layout simplified, and nothing in production changed — because nothing in production had ever used it.
Freeze the design before porting it
ADR-0006 froze the handoff's design surface in early September. What followed was the fastest stretch of the build: 723 of 980 commits and 89 merged PRs in the 43 days from Sep 8 to Oct 21, with drift caught by tests that cite the handoff. Arguing about the design inside each PR would have cost far more than one decision record.
A plan in the repository is a plan you can audit
176 commits are plan(...) records: stories authorized, tasks closed, gate runs recorded, risks resolved. That is 22% of the non-merge history, and it is why every phase above can be dated from the log rather than from memory. The cost is real; the payback is a build history that reads as a project record.
Put the gates where the agent cannot skip them
A Husky pre-commit gate, CI against the built image, and a release job that blocks on CRITICAL/HIGH CVEs and a missing SBOM. With 709 of 807 non-merge commits co-authored by an agent and a median PR open for 12.9 minutes, the gates — not good intentions — are what stood between that pace and a broken build or a vulnerable image.
Have a reputation online but no website of your own?
We build the finished site from what your business has already shown in public. You read it, tell us what is wrong, and approve it. The domain, the site and the content are yours. Tell us about your business on a free 30-minute call.