Small business website spec skill

Planning reference for rebuilding a small business website: page structure, copy voice, estimator widget, SEO requirements, form handling, DNS migration, and the no-code vs static-framework decision (Base44 vs Astro/Vercel vs WordPress).

by hewi333·MIT license·★ 122 Stars on the repo·GitHub ↗

Use now

Inside this skill

SKILL.md · the author's own words
# Small Business Website Spec

> ⚠️ **This is a planning/specification reference, not a deployable skill for
> no-code platforms.** Base44 and similar builders have no CLI the agent can
> call — building there means dragging pages in a web editor, done by a human.
> A static framework (Astro/Hugo/Eleventy) on Vercel/Netlify/Cloudflare Pages
> *is* agent-workable: the agent can clone the repo, edit, run checks, and push.
> Either way, this skill is the spec: page structure, copy voice, estimator
> widget, SEO checklist, form handling, and the DNS cutover runbook.

## When to Use
- Planning a website rebuild for a small service business
- Choosing between no-code (Base44, Wix Studio, Squarespace) and a static framework (Astro on Vercel)
- Page structure, copy voice, estimator widget, SEO requirements
- DNS migration notes (registrar → new host)
- Wiring contact-form submissions into the agent (email → IMAP polling → CRM → Telegram)

Word-for-word excerpt, not a result. Read the full SKILL.md ↓

Files of Small business website spec

hewi333/main1 file shown
SKILL.md
Show the full text225 lines

Small Business Website Spec

⚠️ This is a planning/specification reference, not a deployable skill for no-code platforms. Base44 and similar builders have no CLI the agent can call — building there means dragging pages in a web editor, done by a human. A static framework (Astro/Hugo/Eleventy) on Vercel/Netlify/Cloudflare Pages is agent-workable: the agent can clone the repo, edit, run checks, and push. Either way, this skill is the spec: page structure, copy voice, estimator widget, SEO checklist, form handling, and the DNS cutover runbook.

When to Use

  • Planning a website rebuild for a small service business
  • Choosing between no-code (Base44, Wix Studio, Squarespace) and a static framework (Astro on Vercel)
  • Page structure, copy voice, estimator widget, SEO requirements
  • DNS migration notes (registrar → new host)
  • Wiring contact-form submissions into the agent (email → IMAP polling → CRM → Telegram)
  • NOT for automated no-code deployment — no agent-accessible CLI exists there

Platform Decision: No-Code vs Static Framework

Both paths are valid. Pick by workload, not by hype:

Factor No-code (Base44 etc.) Static framework (Astro/Vercel etc.)
Who builds it Human, in a web editor (drag-and-drop) Human or AI coding agent, in a repo
Time to first draft Hours Days
Monthly cost ~$50/mo for domain connection + GitHub sync on Builder-tier plans $0 on Vercel/Netlify free tiers (or an existing plan)
SEO Prerendering exists but is often a black box you can't control Static HTML — fully crawlable, you own everything
Export/exit Frontend only; backend (auth, DB, entities) stays on the platform SDK — you can't self-host by exporting It's your repo. Portable by definition.
Site types that fit Interactive apps, member areas, anything needing a real backend Marketing sites: pages + one estimator widget + one contact form
Mutability A living app on their platform — platform updates can change rendering without you touching anything An immutable build artifact on CDN edge — it can't break while untouched
Agent's role Paying for the subscription (via stripe-link-cli) and writing the spec — not the build Full repo work: edit, test, verify, push, deploy

How to choose: if the site needs user accounts, database writes, or complex app behavior, no-code (or a real framework with a backend) earns its subscription. If it's a marketing site — pages, photos, an estimator widget, a contact form — a static build is cheaper, faster to load, better for SEO, and fully agent-workable.

We started on Base44 (for a hackathon "the agent bought the subscription" beat, which is what stripe-link-cli is for), then pivoted to Astro-on-Vercel for the production site because a static marketing site had zero backend needs. The pivot itself was cheap because the spec (this document) was written before either build — page inventory, copy voice, estimator logic, and SEO checklist all carried over unchanged.

Prerequisites

  • Domain at a registrar (GoDaddy or similar) — keep DNS there, repoint records
  • Static path: git repo, framework (Astro recommended), hosting account (Vercel/Netlify)
  • No-code path: builder account, manual signup + build in the web interface
  • Form delivery: an email API (Resend/Postmark/SES) or SMTP — forms should email the owner's inbox
  • Payment for no-code subscriptions via the stripe-link-cli skill (agent handles the spend, human handles the build)

Website Architecture

Pages needed (marketing site for a service business)
  1. Home — hero image, value proposition, primary CTA ("Get Free Estimate"), estimator above the fold
  2. Service pages — one per service line (built from a template route; each names the reader's exact situation in the first two sentences)
  3. Service area / location pages — one per market city (template route, real local copy, not doorway spam)
  4. Realtors & property managers — the B2B repeat-revenue page, if referrals drive the business
  5. About / Why Us — owner story, process steps, trust signals, real photos
  6. Gallery — real job photos, captioned
  7. FAQ — include a "what makes you different from everyone else?" answer
  8. Contact — form with estimator pre-fill flow
  9. Reviews — embedded review widget (or hold back until the widget is wired)
  10. Thank you — noindex, conversion event fires here
  11. Terms — warranty/terms as a proper page (not a PDF scan)
  12. 404, plus robots.txt, llms.txt (for AI/agentic search), sitemap-index.xml
Estimator tool integration

The estimator is the conversion hook AND the differentiator. Pricing logic lives in ONE place (see estimator-engine skill; a rate-card.json both the website widget and the agent read is the cleanest split).

  • Input: square footage, region tier, property type (residential/commercial/apartment), add-ons
  • Output: a ±15% range, never a single number, never internal line-item math
  • Flow: result → one tap → contact form pre-filled with all inputs + quoted range
  • Mobile-first: thumb-reachable controls, ≤60 seconds, ≤8 taps
  • The website widget, the agent's chat estimator, and the rate-card file must all read from the same rate card. If a price changes, change the rate card first; both consumers pick it up. Canonical source: estimator-engine.
Contact form handler
  • Serverless function (or the host's form feature) receives the POST
  • Email API (Resend etc.) delivers to the owner's inbox — reply-to set to the submitter so the owner can hit Reply
  • Honeypot spam field (hidden "company" input — if filled, reject silently)
  • Validate: required core fields, plus "at least one of phone or email"
  • Carrying estimator data into the form? Keep it as structured fields in the submission email — the agent's inbox monitor parses them (see below)
  • Optional webhook to the agent — but see "Lead intake" before exposing one
Lead intake (agent integration)

Two ways to get form submissions to the agent:

A. IMAP polling (recommended default). The form emails the owner's inbox with a stable subject prefix (New website lead: ...) and a structured plain-text body. A no_agent=True cron script polls the inbox every 3 min, parses the fields, logs to CRM, and texts the owner's Telegram. Latency ~3 min — irrelevant for a few leads a week. No public endpoint, nothing to attack. Full pattern: grasshopper-voicemail-monitor skill and its notification-email reference.

B. Webhook (faster, more surface). The form handler POSTs straight to an agent endpoint. You get instant delivery but you must expose, secure, rate- limit, and monitor a public URL on the agent box. Only worth it at volume.

Choose A unless leads/minute is a real metric for you. The webhook code can stay in the form handler, dormant, if you want the option open.

Content guide

Copy voice
  • Premium-because-[your real differentiator] — never "affordable," "budget-friendly," "cheap" (they attract price-shoppers, not your buyers)
  • Lead with the outcome (it works, it's guaranteed, it's permanent) — not the chemistry
  • Name the reader's exact situation in the first 2 sentences of every service page
  • Specificity = trust: real cities, real timeframes, real guarantee terms
  • ~7th-grade reading level, short sentences
Banned-word check

Add a verify-script check for cheap-sounding words: affordable, budget-friendly, cheap, competitive pricing, "we work with many budgets," best-in-class, world-class, "look no further." Ban list lives in the repo and runs in CI — banned words slip back in with every copy edit otherwise.

Guarantee

If you advertise a guarantee, state its exceptions wherever the guarantee appears — exceptions buried on a distant page erode trust and invite disputes.

Common Pitfalls

  • Contact-form cutover risk: the OLD site's form probably works and goes to the owner's inbox. Do NOT repoint DNS until the new form is verified delivering to that same inbox on a staging domain. Breaking a working lead path is worse than keeping the old site live another week.
  • DNS propagation: 24-48h. Save old DNS values for instant rollback.
  • Email routing: changing A/CNAME records is fine, but MX records stay pointed at the email host (e.g. Workspace: imap.secureserver.net / smtpout.secureserver.net). Repointing MX silently breaks the business's email.
  • Mobile-first: most service-business leads come from phones. Test at 320px, 375px, 414px widths.
  • 301 redirects: map old (especially WordPress) URLs → new pages before cutover, or years of accumulated SEO equity 404s overnight.
  • Banned words: enforce via the verify script, not vigilance.
  • Terms & conditions: a scanned-image PDF has no extractable text — transcribe it into a real page.
  • Stock photos: verify licensing before a live launch; "we scraped them from our old site" is not a license.
  • Browserless agent box: no-code checkout and Lighthouse audits need a browser. The agent can't drive a web UI without Chromium (npx playwright install --with-deps chromium); run audits via web tools.
  • Region classification sync: if you update region tiers in estimator-engine, update the estimator widget options AND the rate-card file. All three must match. Canonical source: estimator-engine.
  • No-code export is a one-way door: the frontend exports; the backend doesn't. If you start on no-code, treat it as a prototype — don't wire business logic (auth, DB, entities) into it that you'll have to rebuild.
  • Agent pushes to main: for a 1-2 person shop, direct-push with a quality gate (tests + verify script) is faster than PR review. Whatever you choose, make it a written convention — agents follow conventions, they don't infer them.
  • GitHub PATs expire: if the clone URL embeds a PAT, pushes fail mysteriously ~30 days later. Check the token's expiry when setting up, and note the git remote set-url fix before it bites.

DNS Configuration (registrar → Vercel example)

Type: CNAME
Name: www
Value: cname.vercel-dns.com

Type: A
Name: @
Value: 76.76.21.21 (Vercel default)

(No-code hosts give you their own CNAME/A targets — same idea.)

Do NOT touch MX records — email stays with the email host.

Cutover order:

  1. New contact form verified delivering to the owner's inbox (staging domain)
  2. Owner sign-off on content + design
  3. THEN repoint DNS
  4. Old DNS values saved for instant rollback

Verification Checklist

Quality gate (automated — run before every push)
  • Every page renders static HTML with copy in the raw HTML (no client-only content)
  • Unique title (≤60 chars) + meta description (≤155 chars) per indexable page
  • Exactly one H1 + substantial body copy per page
  • Zero banned words (enforced by script)
  • Estimator output matches the agent's chat estimator (same rate card, test N quotes)
  • Guarantee caveats reachable from every page mentioning "guarantee"
  • Structured data (LocalBusiness, Service, FAQPage) + tap-to-call on every page
  • robots.txt, llms.txt, sitemap-index.xml present; /thank-you is noindex
  • Unit tests pass (pricing engine + form validation)
Pre-cutover (manual)
  • Owner sign-off on the site
  • Form submissions verified delivering to the owner's inbox on the real domain
  • Schema.org validates (Google Rich Results Test)
  • Lighthouse mobile: Performance ≥90, SEO ≥95, Accessibility ≥90
  • Real photos on the site (machines/equipment/jobs, not stock)
Post-cutover
  • DNS propagated (dig yourdomain.com) + HTTPS working
  • 301 redirects from old URLs live
  • Email MX records preserved (don't break email)
  • Search Console + Bing Webmaster verified; sitemap submitted
  • Analytics events firing (estimator_start, estimator_complete, form_submit, call_click)
  • Mobile responsive verified on real devices
  • Lead-intake monitor (if used) picking up form submissions → CRM → Telegram
1---
2name: small-business-website-spec
3description: "Planning reference for rebuilding a small business website: page structure, copy voice, estimator widget, SEO requirements, form handling, DNS migration, and the no-code vs static-framework decision (Base44 vs Astro/Vercel vs WordPress). NOT a deploy tool for no-code platforms — no-code builders have no agent-accessible CLI. Includes the honest reasons we pivoted from no-code to a static framework."
4version: "2.0.0"
5author: Hermes Agent
6license: MIT
7metadata:
8 hermes:
9 tags: [website, planning, base44, astro, vercel, no-code, seo, small-business]
10 related_skills: [estimator-engine, grasshopper-voicemail-monitor, agent-cheatsheet-builder]
11---
12 
13# Small Business Website Spec
14 
15> ⚠️ **This is a planning/specification reference, not a deployable skill for
16> no-code platforms.** Base44 and similar builders have no CLI the agent can
17> call — building there means dragging pages in a web editor, done by a human.
18> A static framework (Astro/Hugo/Eleventy) on Vercel/Netlify/Cloudflare Pages
19> *is* agent-workable: the agent can clone the repo, edit, run checks, and push.
20> Either way, this skill is the spec: page structure, copy voice, estimator
21> widget, SEO checklist, form handling, and the DNS cutover runbook.
22 
23## When to Use
24- Planning a website rebuild for a small service business
25- Choosing between no-code (Base44, Wix Studio, Squarespace) and a static framework (Astro on Vercel)
26- Page structure, copy voice, estimator widget, SEO requirements
27- DNS migration notes (registrar → new host)
28- Wiring contact-form submissions into the agent (email → IMAP polling → CRM → Telegram)
29- NOT for automated no-code deployment — no agent-accessible CLI exists there
30 
31## Platform Decision: No-Code vs Static Framework
32 
33Both paths are valid. Pick by workload, not by hype:
34 
35| Factor | No-code (Base44 etc.) | Static framework (Astro/Vercel etc.) |
36|---|---|---|
37| Who builds it | Human, in a web editor (drag-and-drop) | Human or AI coding agent, in a repo |
38| Time to first draft | Hours | Days |
39| Monthly cost | ~$50/mo for domain connection + GitHub sync on Builder-tier plans | $0 on Vercel/Netlify free tiers (or an existing plan) |
40| SEO | Prerendering exists but is often a black box you can't control | Static HTML — fully crawlable, you own everything |
41| Export/exit | Frontend only; backend (auth, DB, entities) stays on the platform SDK — you can't self-host by exporting | It's your repo. Portable by definition. |
42| Site types that fit | Interactive apps, member areas, anything needing a real backend | Marketing sites: pages + one estimator widget + one contact form |
43| Mutability | A living app on their platform — platform updates can change rendering without you touching anything | An immutable build artifact on CDN edge — it can't break while untouched |
44| Agent's role | Paying for the subscription (via stripe-link-cli) and writing the spec — not the build | Full repo work: edit, test, verify, push, deploy |
45 
46**How to choose:** if the site needs user accounts, database writes, or complex
47app behavior, no-code (or a real framework with a backend) earns its subscription.
48If it's a marketing site — pages, photos, an estimator widget, a contact form —
49a static build is cheaper, faster to load, better for SEO, and fully agent-workable.
50 
51We started on Base44 (for a hackathon "the agent bought the subscription" beat,
52which is what `stripe-link-cli` is for), then pivoted to Astro-on-Vercel for the
53production site because a static marketing site had zero backend needs. The
54pivot itself was cheap **because the spec (this document) was written before
55either build** — page inventory, copy voice, estimator logic, and SEO checklist
56all carried over unchanged.
57 
58## Prerequisites
59- Domain at a registrar (GoDaddy or similar) — keep DNS there, repoint records
60- Static path: git repo, framework (Astro recommended), hosting account (Vercel/Netlify)
61- No-code path: builder account, manual signup + build in the web interface
62- Form delivery: an email API (Resend/Postmark/SES) or SMTP — forms should email the owner's inbox
63- Payment for no-code subscriptions via the `stripe-link-cli` skill (agent handles the spend, human handles the build)
64 
65## Website Architecture
66 
67### Pages needed (marketing site for a service business)
681. **Home** — hero image, value proposition, primary CTA ("Get Free Estimate"), estimator above the fold
692. **Service pages** — one per service line (built from a template route; each names the reader's exact situation in the first two sentences)
703. **Service area / location pages** — one per market city (template route, real local copy, not doorway spam)
714. **Realtors & property managers** — the B2B repeat-revenue page, if referrals drive the business
725. **About / Why Us** — owner story, process steps, trust signals, real photos
736. **Gallery** — real job photos, captioned
747. **FAQ** — include a "what makes you different from everyone else?" answer
758. **Contact** — form with estimator pre-fill flow
769. **Reviews** — embedded review widget (or hold back until the widget is wired)
7710. **Thank you** — `noindex`, conversion event fires here
7811. **Terms** — warranty/terms as a proper page (not a PDF scan)
7912. **404**, plus `robots.txt`, `llms.txt` (for AI/agentic search), `sitemap-index.xml`
80 
81### Estimator tool integration
82The estimator is the conversion hook AND the differentiator. Pricing logic
83lives in ONE place (see `estimator-engine` skill; a `rate-card.json` both the
84website widget and the agent read is the cleanest split).
85- Input: square footage, region tier, property type (residential/commercial/apartment), add-ons
86- Output: a **±15% range, never a single number**, never internal line-item math
87- Flow: result → one tap → contact form pre-filled with all inputs + quoted range
88- Mobile-first: thumb-reachable controls, ≤60 seconds, ≤8 taps
89- **The website widget, the agent's chat estimator, and the rate-card file
90 must all read from the same rate card.** If a price changes, change the rate
91 card first; both consumers pick it up. Canonical source: `estimator-engine`.
92 
93### Contact form handler
94- Serverless function (or the host's form feature) receives the POST
95- Email API (Resend etc.) delivers to the **owner's inbox** — reply-to set to
96 the submitter so the owner can hit Reply
97- Honeypot spam field (hidden "company" input — if filled, reject silently)
98- Validate: required core fields, plus "at least one of phone or email"
99- Carrying estimator data into the form? Keep it as structured fields in the
100 submission email — the agent's inbox monitor parses them (see below)
101- Optional webhook to the agent — but see "Lead intake" before exposing one
102 
103### Lead intake (agent integration)
104Two ways to get form submissions to the agent:
105 
106**A. IMAP polling (recommended default).** The form emails the owner's inbox
107with a stable subject prefix (`New website lead: ...`) and a structured
108plain-text body. A `no_agent=True` cron script polls the inbox every 3 min,
109parses the fields, logs to CRM, and texts the owner's Telegram. Latency ~3 min
110— irrelevant for a few leads a week. No public endpoint, nothing to attack.
111Full pattern: `grasshopper-voicemail-monitor` skill and its notification-email
112reference.
113 
114**B. Webhook (faster, more surface).** The form handler POSTs straight to an
115agent endpoint. You get instant delivery but you must expose, secure, rate-
116limit, and monitor a public URL on the agent box. Only worth it at volume.
117 
118Choose A unless leads/minute is a real metric for you. The webhook code can
119stay in the form handler, dormant, if you want the option open.
120 
121## Content guide
122 
123### Copy voice
124- **Premium-because-[your real differentiator]** — never "affordable,"
125 "budget-friendly," "cheap" (they attract price-shoppers, not your buyers)
126- Lead with the outcome (it works, it's guaranteed, it's permanent) — not the chemistry
127- Name the reader's exact situation in the first 2 sentences of every service page
128- Specificity = trust: real cities, real timeframes, real guarantee terms
129- ~7th-grade reading level, short sentences
130 
131### Banned-word check
132Add a verify-script check for cheap-sounding words: *affordable,
133budget-friendly, cheap, competitive pricing, "we work with many budgets,"
134best-in-class, world-class, "look no further."* Ban list lives in the repo and
135runs in CI — banned words slip back in with every copy edit otherwise.
136 
137### Guarantee
138If you advertise a guarantee, state its exceptions wherever the guarantee
139appears — exceptions buried on a distant page erode trust and invite disputes.
140 
141## Common Pitfalls
142 
143- **Contact-form cutover risk:** the OLD site's form probably works and goes
144 to the owner's inbox. Do NOT repoint DNS until the new form is **verified
145 delivering to that same inbox** on a staging domain. Breaking a working
146 lead path is worse than keeping the old site live another week.
147- **DNS propagation:** 24-48h. Save old DNS values for instant rollback.
148- **Email routing:** changing A/CNAME records is fine, but **MX records stay
149 pointed at the email host** (e.g. Workspace: `imap.secureserver.net` /
150 `smtpout.secureserver.net`). Repointing MX silently breaks the business's email.
151- **Mobile-first:** most service-business leads come from phones. Test at
152 320px, 375px, 414px widths.
153- **301 redirects:** map old (especially WordPress) URLs → new pages before
154 cutover, or years of accumulated SEO equity 404s overnight.
155- **Banned words:** enforce via the verify script, not vigilance.
156- **Terms & conditions:** a scanned-image PDF has no extractable text —
157 transcribe it into a real page.
158- **Stock photos:** verify licensing before a live launch; "we scraped them
159 from our old site" is not a license.
160- **Browserless agent box:** no-code checkout and Lighthouse audits need a
161 browser. The agent can't drive a web UI without Chromium
162 (`npx playwright install --with-deps chromium`); run audits via web tools.
163- **Region classification sync:** if you update region tiers in
164 `estimator-engine`, update the estimator widget options AND the rate-card
165 file. All three must match. Canonical source: `estimator-engine`.
166- **No-code export is a one-way door:** the frontend exports; the backend
167 doesn't. If you start on no-code, treat it as a prototype — don't wire
168 business logic (auth, DB, entities) into it that you'll have to rebuild.
169- **Agent pushes to `main`:** for a 1-2 person shop, direct-push with a
170 quality gate (tests + verify script) is faster than PR review. Whatever
171 you choose, make it a written convention — agents follow conventions,
172 they don't infer them.
173- **GitHub PATs expire:** if the clone URL embeds a PAT, pushes fail
174 mysteriously ~30 days later. Check the token's expiry when setting up,
175 and note the `git remote set-url` fix before it bites.
176 
177## DNS Configuration (registrar → Vercel example)
178 
179```
180Type: CNAME
181Name: www
182Value: cname.vercel-dns.com
183 
184Type: A
185Name: @
186Value: 76.76.21.21 (Vercel default)
187```
188(No-code hosts give you their own CNAME/A targets — same idea.)
189 
190**Do NOT touch MX records** — email stays with the email host.
191 
192Cutover order:
1931. New contact form verified delivering to the owner's inbox (staging domain)
1942. Owner sign-off on content + design
1953. THEN repoint DNS
1964. Old DNS values saved for instant rollback
197 
198## Verification Checklist
199 
200### Quality gate (automated — run before every push)
201- [ ] Every page renders static HTML with copy in the raw HTML (no client-only content)
202- [ ] Unique title (≤60 chars) + meta description (≤155 chars) per indexable page
203- [ ] Exactly one H1 + substantial body copy per page
204- [ ] Zero banned words (enforced by script)
205- [ ] Estimator output matches the agent's chat estimator (same rate card, test N quotes)
206- [ ] Guarantee caveats reachable from every page mentioning "guarantee"
207- [ ] Structured data (LocalBusiness, Service, FAQPage) + tap-to-call on every page
208- [ ] robots.txt, llms.txt, sitemap-index.xml present; /thank-you is noindex
209- [ ] Unit tests pass (pricing engine + form validation)
210 
211### Pre-cutover (manual)
212- [ ] Owner sign-off on the site
213- [ ] Form submissions verified delivering to the owner's inbox on the real domain
214- [ ] Schema.org validates (Google Rich Results Test)
215- [ ] Lighthouse mobile: Performance ≥90, SEO ≥95, Accessibility ≥90
216- [ ] Real photos on the site (machines/equipment/jobs, not stock)
217 
218### Post-cutover
219- [ ] DNS propagated (`dig yourdomain.com`) + HTTPS working
220- [ ] 301 redirects from old URLs live
221- [ ] Email MX records preserved (don't break email)
222- [ ] Search Console + Bing Webmaster verified; sitemap submitted
223- [ ] Analytics events firing (estimator_start, estimator_complete, form_submit, call_click)
224- [ ] Mobile responsive verified on real devices
225- [ ] Lead-intake monitor (if used) picking up form submissions → CRM → Telegram

Discussion

Alternatives