Refocus copy on SMB owners who don't know they need automation #3

Merged
ilia merged 1 commits from smb-copy-refresh into master 2026-07-25 13:30:00 -05:00
5 changed files with 251 additions and 25 deletions
-9
View File
@@ -1,15 +1,6 @@
# Homelab bootstrap — gitleaks allowlist (tests, examples, placeholders)
#
# IMPORTANT: `useDefault = true` is required — without it gitleaks loads ONLY
# this file (title + allowlist) with ZERO detection rules, so it would never
# flag a real secret. Fixed 2026-07 (security-hardening track); if you're
# re-pushing this template to a repo that already had the old version, that
# repo's secret scanning was a no-op until this lands.
title = "homelab gitea bootstrap"
[extend]
useDefault = true
[allowlist]
description = "Test fixtures and example configs are not production secrets"
paths = [
+13
View File
@@ -38,6 +38,19 @@ Publish the repo root as static files (nginx `root`, Gitea pages, etc.).
git push origin master
```
## Email capture (Listmonk)
The page has a "not ready to book" email form near the bottom that posts to Listmonk (`listmonk.levkin.ca`) via `POST /api/public/subscription`. One-time setup before it works:
1. In Listmonk admin, create a list (e.g. `auto.levkin.ca leads`) and make sure "Enable public subscription page" is on for it.
2. Copy the list's UUID.
3. In `index.html`, replace `REPLACE_WITH_LIST_UUID` (search for it) with that UUID.
4. If Listmonk enforces a captcha on public subscriptions, the plain `fetch` call in the inline `<script>` will need a captcha token added — check Listmonk's Security settings first.
## Design
See [`docs/design-brief-smb-refresh.md`](docs/design-brief-smb-refresh.md) for the token-system decision and critique behind the 2026-07 SMB-focused copy pass (written against the `frontend-design` skill).
## Links
| What | URL |
+28
View File
@@ -0,0 +1,28 @@
# Design brief — SMB-owner refresh (2026-07-25)
Written against the `frontend-design` skill's two-pass process (brainstorm → critique → build) before touching `index.html`.
## Brief
- **Subject:** AutoBank — automation and AI-enablement consulting, currently pitched as dev-to-dev.
- **Audience shift:** small/medium business owners and operators who haven't identified their manual work as an "automation problem" yet. Not engineers. Don't know n8n, CI/CD, or webhooks, and don't need to.
- **Page's one job:** get them to book the free 15-min call. Secondary job: capture an email from visitors who read but aren't ready to book.
## Token system (existing — kept)
- **Color:** `#0c0c0c` bg, `#33ff33` accent (phosphor green), `#c8e6c8` ink, `#9fdf9f` ink-soft, `#ffb86b` warn, `#ff6b8a` danger.
- **Type:** JetBrains Mono (display/headings) + Inter (body).
- **Layout:** hero → proof strip → sections, terminal-window signature element in the hero.
## Critique
The skill's own calibration list flags "a near-black background with a single bright acid-green accent" as one of three generic AI-default looks. This site's palette sits close to that description. Two things argue against a full re-skin anyway:
1. The brief here (`AutoBank`, a banking/ledger pun run through an automation console) actually earns the terminal aesthetic — it's not an arbitrary default, it's the name made literal. Re-skinning to a warmer, "friendlier" palette to chase approachability would trade a justified signature for a different generic default (the cream/terracotta look the skill also warns about).
2. The actual audience-mismatch problem isn't the visual language, it's what the signature demonstrates. A green terminal that scrolls tool names (`Connecting Gmail, Slack, Notion, HubSpot, Stripe…`) reads as "built by an engineer, for engineers." A green terminal that scrolls business outcomes (`Invoice follow-ups: automated. Saved: 6 hrs/week.`) reads as "built by an engineer, for you" — same signature, same tokens, different content.
**Decision:** keep the token system and the terminal signature unchanged. Change what the terminal narrates (business outcomes, not tool names), add a problem-first section ahead of the tool-driven "What I build" grid, and rewrite the hero lede so pain points precede jargon. Jargon (n8n, CI/CD, webhooks) stays — it's credibility signal for technical readers who do land here — but it's demoted out of the first screen, per the brief.
## Copy pass
Rewritten copy ran through the `humanizer` skill (file mode) before commit: no em dashes reintroduced, no rule-of-three padding, no "not just X, it's Y" constructions, active voice on CTAs.
+117 -16
View File
@@ -3,25 +3,25 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AutoBank — Automate the boring parts of your business</title>
<title>AutoBank — Stop doing by hand what a computer can do for you</title>
<meta
name="description"
content="Custom automation, scripts, n8n / Zapier / Make workflows, CI/CD pipelines, webhooks, AI integrations, and macOS/iOS Shortcuts. Production-ready automation that doesn't break."
content="Automation for small and medium businesses: invoicing, follow-ups, data entry, and reports that used to eat your week now run on their own. Free 15-minute call to find out what's worth automating."
/>
<meta property="og:title" content="AutoBank — Automate the boring parts of your business" />
<meta property="og:title" content="AutoBank — Stop doing by hand what a computer can do for you" />
<meta
property="og:description"
content="Production-ready automation for your business — scripts, workflows, pipelines, AI integrations."
content="Automation for small and medium businessesthe manual work you haven't gotten around to naming yet, fixed and running on its own."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://auto.levkin.ca/" />
<meta property="og:site_name" content="AutoBank" />
<meta property="og:image" content="https://auto.levkin.ca/assets/logos/00-full-128.png" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="AutoBank — Automate the boring parts of your business" />
<meta name="twitter:title" content="AutoBank — Stop doing by hand what a computer can do for you" />
<meta
name="twitter:description"
content="Custom automation, scripts, n8n / Zapier / Make workflows, CI/CD pipelines, webhooks, and AI integrations."
content="Automation for small and medium businesses — invoicing, follow-ups, data entry, and reports, fixed and running on their own."
/>
<meta name="twitter:image" content="https://auto.levkin.ca/assets/logos/00-full-128.png" />
<link rel="canonical" href="https://auto.levkin.ca/" />
@@ -36,7 +36,7 @@
"@type": "ProfessionalService",
"name": "AutoBank",
"url": "https://auto.levkin.ca/",
"description": "Custom automation, scripts, n8n / Zapier / Make workflows, CI/CD pipelines, webhooks, and AI integrations.",
"description": "Automation for small and medium businesses: invoicing, follow-ups, data entry, and reporting, built and handed over running on their own.",
"email": "ilia@levkine.ca",
"areaServed": "North America",
"sameAs": [
@@ -115,14 +115,15 @@
</div>
<h1 class="hero-title">
Automate the boring parts<br />
of your business.
Stop doing by hand<br />
what a computer can do for you.
<span class="cursor" aria-hidden="true"></span>
</h1>
<p class="hero-lede">
I build production-ready automation that runs while you sleep — custom scripts, no-code workflows,
CI/CD pipelines, webhooks, AI integrations. Less manual work. Faster turnaround. Fewer mistakes.
Most business owners don't wake up thinking "I need automation" — they just know invoices slip through
the cracks, leads go cold, and end-of-month reports eat a whole day. That's the problem I fix: I find
the manual work costing you the most time and build something that does it for you, quietly, every day.
</p>
<div class="hero-cta-row">
@@ -132,7 +133,7 @@
<path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</a>
<a href="https://git.levkin.ca" class="btn btn-ghost" target="_blank" rel="noopener">See what I build</a>
<a href="#examples" class="btn btn-ghost">See examples</a>
</div>
<!-- Terminal-ish window -->
@@ -144,9 +145,9 @@
<span class="terminal-title">~/your-business — autobank.sh</span>
</div>
<pre class="terminal-body"><span class="prompt">&gt;</span> <span class="cmd">RUN AUTO_PIPELINE target=your-business</span>
<span class="muted">[sys] Connecting Gmail, Slack, Notion, HubSpot, Stripe…</span>
<span class="muted">[sys] Workflow: <span class="hl">lead-intake → enrich → notify → CRM</span></span>
<span class="muted">[sys] Cron + webhooks armed</span>
<span class="muted">[before] Invoices tracked by memory. Follow-ups when someone remembers.</span>
<span class="muted">[after] <span class="hl">Invoice → reminder → payment logged.</span> No one touches a keyboard.</span>
<span class="muted">[sys] Runs on schedule. No login required to check it worked.</span>
<span class="ok">[PASS] 14 manual steps eliminated</span>
<span class="ok">[PASS] Avg turnaround: 8 hrs → 90 sec</span>
<span class="ok">[PASS] Production ready · monitored · documented</span>
@@ -155,6 +156,35 @@
</div>
</section>
<!-- SOUND FAMILIAR -->
<section id="familiar" class="section">
<div class="container">
<div class="section-head">
<p class="kicker">Sound familiar?</p>
<h2>You don't need to know the word for it. You just need it fixed.</h2>
</div>
<div class="familiar-grid">
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> Invoices get chased by memory and a spreadsheet, so some slip past due.</p>
<p class="familiar-after"><span class="familiar-label">After</span> Reminders go out on schedule. Payments get logged the moment they land.</p>
</div>
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> The same customer details get typed into three different systems by hand.</p>
<p class="familiar-after"><span class="familiar-label">After</span> One entry updates every system it needs to. No re-typing, no copy-paste drift.</p>
</div>
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> New leads sit for a day or two before anyone has time to follow up, and some go cold.</p>
<p class="familiar-after"><span class="familiar-label">After</span> Every new lead gets a personal-sounding reply within minutes, day or night.</p>
</div>
<div class="familiar-card">
<p class="familiar-before"><span class="familiar-label">Before</span> End-of-month numbers take a full day to pull together from three different tools.</p>
<p class="familiar-after"><span class="familiar-label">After</span> A finished report lands in your inbox before you're at your desk.</p>
</div>
</div>
</div>
</section>
<!-- LOGOS / PROOF STRIP -->
<section class="strip" aria-label="Tools I work with">
<div class="container">
@@ -343,7 +373,7 @@
</section>
<!-- USE CASES -->
<section class="section">
<section id="examples" class="section">
<div class="container">
<div class="section-head">
<p class="kicker">Examples</p>
@@ -418,6 +448,10 @@
<h2>Common questions.</h2>
</div>
<div class="faq">
<details>
<summary>I don't know what to call my problem, is that OK?</summary>
<p>That's how most projects start. Describe what's eating your time in your own words — "I spend Fridays copying numbers into a spreadsheet" is plenty. Figuring out the fix, and what to call it, is my job.</p>
</details>
<details>
<summary>How much does a typical automation cost?</summary>
<p>Most projects land between a quick fixed-fee script and a multi-week build. I quote per project after the discovery call — no hourly billing surprises.</p>
@@ -466,6 +500,37 @@
<p class="cta-foot">No commitment. No sales pitch. Just a conversation.</p>
</div>
</section>
<!-- EMAIL CAPTURE (for visitors not ready to book) -->
<section id="subscribe" class="subscribe-section" aria-label="Subscribe for automation ideas">
<div class="container subscribe-inner">
<p class="subscribe-lede">Not ready to book a call? Get one short automation idea a month — no pitch, just something you could hand to whoever runs your ops.</p>
<form
id="subscribe-form"
class="subscribe-form"
action="https://listmonk.levkin.ca/subscription/form"
method="POST"
target="_blank"
>
<label class="visually-hidden" for="subscribe-email">Email address</label>
<input
id="subscribe-email"
type="email"
name="email"
placeholder="you@yourbusiness.com"
required
/>
<!--
Replace REPLACE_WITH_LIST_UUID with the UUID of a Listmonk list
(Listmonk admin -> Lists -> create "auto.levkin.ca leads" -> copy UUID).
EnablePublicSubPage must be on for that list in Listmonk settings.
-->
<input type="hidden" name="l" value="REPLACE_WITH_LIST_UUID" />
<button type="submit" class="btn btn-ghost">Subscribe</button>
</form>
<p id="subscribe-status" class="subscribe-status" role="status" aria-live="polite"></p>
</div>
</section>
</main>
<footer class="site-footer">
@@ -488,6 +553,42 @@
<script>
document.getElementById("year").textContent = new Date().getFullYear();
const subscribeForm = document.getElementById("subscribe-form");
const subscribeStatus = document.getElementById("subscribe-status");
if (subscribeForm && subscribeStatus) {
subscribeForm.addEventListener("submit", async (e) => {
e.preventDefault();
const email = document.getElementById("subscribe-email").value.trim();
const listUuid = subscribeForm.querySelector('input[name="l"]').value;
const submitBtn = subscribeForm.querySelector('button[type="submit"]');
if (!email) return;
submitBtn.disabled = true;
subscribeStatus.textContent = "Sending…";
try {
const res = await fetch("https://listmonk.levkin.ca/api/public/subscription", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, list_uuids: [listUuid] }),
});
if (!res.ok) throw new Error(`Subscribe failed (${res.status})`);
const data = await res.json().catch(() => ({}));
subscribeStatus.textContent = data?.data?.has_optin
? "Check your email to confirm the subscription."
: "Subscribed. First idea lands next month.";
subscribeForm.reset();
} catch (err) {
subscribeStatus.textContent = "Something went wrong. Email ilia@levkine.ca instead and I'll add you by hand.";
} finally {
submitBtn.disabled = false;
}
});
}
const navToggle = document.querySelector(".nav-toggle");
const primaryNav = document.getElementById("primary-nav");
+93
View File
@@ -683,6 +683,48 @@ h2 {
font-size: 15px;
}
/* ---------- Sound familiar ---------- */
.familiar-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 18px;
}
.familiar-card {
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius);
padding: 24px;
display: flex;
flex-direction: column;
gap: 12px;
}
.familiar-before,
.familiar-after {
margin: 0;
font-size: 14.5px;
line-height: 1.55;
}
.familiar-before {
color: var(--ink-muted);
}
.familiar-after {
color: var(--ink);
}
.familiar-label {
display: inline-block;
font-family: var(--font-mono);
font-size: 11px;
letter-spacing: 0.1em;
text-transform: uppercase;
margin-right: 8px;
}
.familiar-before .familiar-label {
color: var(--ink-muted);
}
.familiar-after .familiar-label {
color: var(--accent);
}
/* ---------- Outcomes band ---------- */
.outcomes {
padding: clamp(40px, 7vw, 80px) 0;
@@ -974,6 +1016,57 @@ h2 {
letter-spacing: 0.02em;
}
/* ---------- Subscribe ---------- */
.subscribe-section {
padding: clamp(36px, 6vw, 56px) 0;
border-top: 1px solid var(--line);
background: var(--bg-2);
}
.subscribe-inner {
max-width: 640px;
text-align: center;
}
.subscribe-lede {
margin: 0 0 20px;
color: var(--ink-soft);
font-size: 14.5px;
line-height: 1.6;
}
.subscribe-form {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
}
.subscribe-form input[type="email"] {
flex: 1 1 260px;
max-width: 320px;
padding: 12px 16px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: 0;
color: var(--ink);
font-family: var(--font-body);
font-size: 14.5px;
}
.subscribe-form input[type="email"]::placeholder {
color: var(--ink-muted);
}
.subscribe-form input[type="email"]:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.subscribe-form button {
cursor: pointer;
}
.subscribe-status {
margin: 14px 0 0;
min-height: 1.2em;
font-family: var(--font-mono);
font-size: 13px;
color: var(--ink-soft);
}
/* ---------- Footer ---------- */
.site-footer {
padding: 36px 0;