chore: move planning/handoff docs to Buzz channels (ideas, business, per-site)
This commit is contained in:
parent
2545a1ecb3
commit
9bacc83344
5 changed files with 0 additions and 431 deletions
147
HANDOFF.md
147
HANDOFF.md
|
|
@ -1,147 +0,0 @@
|
||||||
# HANDOFF BRIEF — djg-oracle-sl Buzz + sites deployment
|
|
||||||
|
|
||||||
**Audience:** senior engineers taking over this stack. Written by the ZCode
|
|
||||||
agent that built it, including its own mistakes. Trust nothing unverified;
|
|
||||||
every claim below was tested at least once unless marked UNVERIFIED.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. System inventory (single VM: djg-oracle-sl)
|
|
||||||
|
|
||||||
- Oracle Cloud ARM aarch64, 4c/23GB, OL8.10, public IP **144.24.30.131**.
|
|
||||||
SELinux **enforcing**. cgroup **v1** (blocks k3s ≥1.35 — do NOT upgrade k3s
|
|
||||||
past 1.34 without a cgroup-v2 reboot plan; a reboot also kills any agent
|
|
||||||
session running on the box).
|
|
||||||
- **k3s v1.34.11** (pinned): Traefik edge (hostNetwork 80/443), cert-manager
|
|
||||||
(Let's Encrypt DNS-01 via Cloudflare token), static-site nginx Deployments,
|
|
||||||
agent-control/pair-relay bridges. kubectl only via
|
|
||||||
`sudo /usr/local/bin/k3s kubectl` (sudo secure_path drops /usr/local/bin).
|
|
||||||
- **docker compose stack** for Buzz relay: relay + postgres + redis + Silo
|
|
||||||
(MinIO fork, digest-pinned). Compose dir: /home/opc/buzz/deploy/compose
|
|
||||||
(.env = secrets, 600).
|
|
||||||
- **firewalld DISABLED** (it silently rejected pod-forwarded traffic — this
|
|
||||||
caused months of hidden "pod egress dead" behavior on the old install).
|
|
||||||
OCI security list (22/80/443) is the only perimeter.
|
|
||||||
- **coredns Corefile patched** to `forward . 1.1.1.1 8.8.8.8` because OCI's
|
|
||||||
169.254.169.254 resolver is link-local and unreachable from pods. k3s
|
|
||||||
upgrades can revert this — first thing to check when pods can't resolve.
|
|
||||||
- Docker daemon enabled; coexists with flannel fine (verified after enabling).
|
|
||||||
|
|
||||||
## 2. Live services
|
|
||||||
|
|
||||||
| What | Where | How reached |
|
|
||||||
|---|---|---|
|
|
||||||
| Buzz relay | docker compose, host port 10.0.0.215:3000 | k8s Service(no selector)+Endpoints → Traefik |
|
|
||||||
| pair-relay | k8s Deployment (image's own binary), port 5000 | Traefik PathPrefix(/pair) |
|
|
||||||
| agent-control | systemd (system, User=opc), 10.0.0.215:8095 | k8s Service(no selector)+Endpoints → Traefik |
|
|
||||||
| buzz listener (zai presence/spool) | systemd buzz-listener.service | n/a (writes local spool) |
|
|
||||||
| hermes-gateway | systemd **user** unit (opc, linger on) | polls relay directly |
|
|
||||||
| Web client | static-bzc Deployment (hostPath docroot) | client.ch4t.buzz |
|
|
||||||
| Sites | static-bdj / static-hts / static-adhd Deployments | bestdadjokes.lol / helpme.tips / myadhd.dev |
|
|
||||||
|
|
||||||
Domains: ch4t.buzz (relay, /pair, agent control), client.ch4t.buzz (web),
|
|
||||||
bestdadjokes.lol, helpme.tips, myadhd.dev. Wildcard A * exists for ch4t.buzz.
|
|
||||||
DNS via Cloudflare API; token at ~/.cloudflare-token (600).
|
|
||||||
|
|
||||||
## 3. Secrets & keys map (all 600, none committed)
|
|
||||||
|
|
||||||
- /home/opc/.cloudflare-token — CF API token (zones: bestdadjokes.lol,
|
|
||||||
myadhd.dev, helpme.tips, ch4t.buzz)
|
|
||||||
- /home/opc/buzz-agent-key.txt — zai identity (relay admin)
|
|
||||||
- /home/opc/buzz-hermes-key.txt, buzz-antigravity-key.txt,
|
|
||||||
buzz-openfang-key.txt — staged harness identities (relay members)
|
|
||||||
- /home/opc/buzz-owner-key.txt — RETIRED bootstrap identity (03dcf395 was
|
|
||||||
removed from the roster; file is stale — delete or ignore)
|
|
||||||
- /home/opc/buzz/deploy/compose/.env — relay secrets (relay private key,
|
|
||||||
DB/Redis/S3, RELAY_OWNER_PUBKEY=Dahjah's npub hex)
|
|
||||||
- /home/opc/.hermes/.env — hermes secrets + GATEWAY_ALLOW_ALL_USERS=true
|
|
||||||
- /home/opc/.buzz-pending.json — reactions awaiting cleanup (listener state)
|
|
||||||
|
|
||||||
## 4. Known issues, ranked (what to look at first)
|
|
||||||
|
|
||||||
### A. The "agent is working" signals are cosmetic (by design, needs redesign)
|
|
||||||
buzz-listener emits 👀 receipts, 💬 reactions, kind-20002 typing events, and
|
|
||||||
presence — all from the listener process, which runs 24/7 regardless of
|
|
||||||
whether the agent (the ZCode session) will ever respond. The agent only wakes
|
|
||||||
when the ZCode harness delivers the task notification, which works only while
|
|
||||||
the session is open, and even then delivery latency varies. The user correctly
|
|
||||||
identified this: green dot + typing ≠ agent working. Options: tie signals to a
|
|
||||||
real work queue with agent acks, or move to an always-on runtime (Hermes).
|
|
||||||
|
|
||||||
### B. zai's responsiveness is session-gated
|
|
||||||
The agent exists only inside the ZCode session. Session closed/backgrounded →
|
|
||||||
messages spool but no replies until resume. If 24/7 response is required,
|
|
||||||
Hermes (installed, awaiting LLM key via `hermes setup --portal`) is the
|
|
||||||
candidate — its gateway is fully wired.
|
|
||||||
|
|
||||||
### C. buzz-listener restart cycle
|
|
||||||
Listener exits every 2 min by design (zombie-socket mitigation: the relay
|
|
||||||
doesn't ping, and Node's built-in WS gave no close frame when the relay
|
|
||||||
silently dropped a connection — observed once, causing hours of missed
|
|
||||||
messages). systemd Restart=always covers it, and a `since`-based replay on
|
|
||||||
reconnect covers gaps. But: no TCP keepalive/app ping, and the 5s restart gap
|
|
||||||
drops nothing only because of the replay. A proper fix = real WS ping/pong
|
|
||||||
liveness. Also: reactions dedupe via /home/opc/.buzz-reacted (file, append-only).
|
|
||||||
|
|
||||||
### D. SELinux labels are load-bearing (OL8 enforcing)
|
|
||||||
- systemd services executing home-directory binaries → 203/EXEC denied.
|
|
||||||
Fixed by semanage fcontext: hermes venv + uv python → bin_t (persistent).
|
|
||||||
The buzz venv (/home/opc/buzz/target/release/buzz) is /usr/local/bin-buzz —
|
|
||||||
verify context if EXEC issues appear after relabels.
|
|
||||||
- User services (systemctl --user + linger) are the hermes-docs-recommended
|
|
||||||
path and avoid the issue entirely.
|
|
||||||
|
|
||||||
### E. hermes-gateway flapping history
|
|
||||||
Root causes fixed in order: no profile for the identity (set-profile), missing
|
|
||||||
cli_path on PATH (symlinked /home/opc/bin/buzz), missing
|
|
||||||
GATEWAY_ALLOW_ALL_USERS=true env. If it flaps again: ~/.hermes/logs/gateway.log
|
|
||||||
has the real logs (journald often shows nothing for the user unit).
|
|
||||||
|
|
||||||
### F. Upstream drift
|
|
||||||
- block/buzz moves fast (relay image :main, unpinned). Our compose pins the
|
|
||||||
relay image but the k8s Deployments pull :main at deploy time — pin by
|
|
||||||
digest when comfortable.
|
|
||||||
- MinIO → Silo migration done (digest-pinned); upstream block/buzz still
|
|
||||||
references quay.io MinIO — if they migrate, mirror their choice.
|
|
||||||
|
|
||||||
## 5. Debugging playbook (commands that actually work)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# relay health + NIP-11
|
|
||||||
curl -s -H 'Accept: application/nostr+json' https://ch4t.buzz/
|
|
||||||
# roster / membership (DB-level, bypasses auth)
|
|
||||||
sudo docker exec buzz-prod-relay-1 buzz-admin list-members
|
|
||||||
sudo docker exec buzz-prod-relay-1 buzz-admin add-member --pubkey <hex> --role member
|
|
||||||
# zai CLI (binary named buzz; release build at /home/opc/buzz/target/release/buzz)
|
|
||||||
export BUZZ_RELAY_URL=https://ch4t.buzz BUZZ_PRIVATE_KEY=$(grep '^SECRET:' /home/opc/buzz-agent-key.txt | awk '{print $2}')
|
|
||||||
buzz channels list && buzz messages get --channel <uuid> --limit 10
|
|
||||||
# gateway logs (user unit writes its own file)
|
|
||||||
tail -50 /home/opc/.hermes/logs/gateway.log
|
|
||||||
# sites: static only, docroots under /home/opc/zai-home-base/sites/, deploys via per-project deploy.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6. Where the previous agent (zai) made mistakes — verify, don't trust
|
|
||||||
|
|
||||||
1. Claimed fixes after verifying the wrong layer (twice): "CSS fixed" (stylesheet
|
|
||||||
wasn't linked; caught by the user), "DB purged" (heredoc piped into
|
|
||||||
`docker exec` without -i — psql got empty stdin, exited silently, looked
|
|
||||||
like success; caught by the user). Rule: validate at the layer the user sees.
|
|
||||||
2. Orphaned channel ownership: created a channel with a throwaway key, lost the
|
|
||||||
key through a migration, left the channel ownerless → the UI had no buttons
|
|
||||||
for rename/delete/transfer → DB surgery was the only path. Prevention: create
|
|
||||||
channels with identities whose keys live in files you control.
|
|
||||||
3. Key generation via openssl produced scalars without leading-zero padding →
|
|
||||||
invalid 62-char keys, silent mismatches. Use `buzz-admin generate-key`.
|
|
||||||
4. Multiple silent no-op edits: python str.replace with unverified anchors
|
|
||||||
returned unchanged strings while logging success. Assert every anchor.
|
|
||||||
5. The agent shell dies if its cwd is deleted (recreate the path to recover).
|
|
||||||
|
|
||||||
## 7. Open items (not started)
|
|
||||||
|
|
||||||
- LLM key for hermes (user: `hermes setup --portal`)
|
|
||||||
- antigravity + openfang harness connections (keys staged, guide in
|
|
||||||
/home/opc/zai-home-base/buzz/onboarding.md)
|
|
||||||
- dadjokes.guru + raspiinthesky.com fleet builds (design notes in repo)
|
|
||||||
- helpme.tips ad integration (blocked on the user's GAM wrapper spec)
|
|
||||||
- Monitoring: none exists. Presence dot is the only health signal. A dead-man's
|
|
||||||
switch on the listener would be the first thing to add.
|
|
||||||
59
README.md
59
README.md
|
|
@ -1,59 +0,0 @@
|
||||||
# zai-home-base — revenue projects on djg-oracle-sl
|
|
||||||
|
|
||||||
Workspace for revenue-generating projects. Cluster edge: **Traefik v2.11**
|
|
||||||
(hostNetwork 80/443) + **cert-manager** (Let's Encrypt DNS-01 via Cloudflare).
|
|
||||||
Sites are static nginx Deployments fed by hostPath docroots in `sites/`.
|
|
||||||
|
|
||||||
## Live sites
|
|
||||||
|
|
||||||
- **bestdadjokes.lol** — dad-joke content site (Track 1; ads play via user's AdX/MCM)
|
|
||||||
- **myadhd.dev** — placeholder; ADHD micro-tools product coming (Track 2, Paddle/Stripe later)
|
|
||||||
|
|
||||||
## Layout
|
|
||||||
|
|
||||||
- `bdj/` — bestdadjokes.lol project
|
|
||||||
- `content/jokes.json` — dataset, APPEND-ONLY (joke id = array index)
|
|
||||||
- `build.py` — stdlib-only static generator (Python 3.6! no walrus, no dict-merge `|`)
|
|
||||||
- `static/` — css/js/favicon (`jokes-data.js` is generated, don't hand-edit)
|
|
||||||
- `k8s/traefik.yaml` — edge DaemonSet (hostNetwork, RBAC incl. endpointslices+nodes)
|
|
||||||
- `k8s/letsencrypt-issuer.yaml` — ClusterIssuer, DNS-01 via CF token Secret
|
|
||||||
- `k8s/static-sites.yaml` — per-site Deployment+Service+Ingress+Certificate
|
|
||||||
- `deploy.sh` — build + in-place rsync to docroot (no dir swap — see gotchas)
|
|
||||||
- `adhd/site/index.html` — myadhd.dev placeholder (copied to `sites/myadhd.dev/`)
|
|
||||||
- `sites/` — live docroots (generated, gitignored)
|
|
||||||
|
|
||||||
## Deploy content
|
|
||||||
|
|
||||||
cd bdj && ./deploy.sh
|
|
||||||
|
|
||||||
New site = docroot + copy the Deployment/Service/Ingress/Certificate pattern in
|
|
||||||
`bdj/k8s/static-sites.yaml` + a DNS record (Cloudflare API, token in
|
|
||||||
`~/.cloudflare-token`, zones bestdadjokes.lol=0cd16b5205725d310366859b3352a189,
|
|
||||||
myadhd.dev=00fa64c074d7162b7616a4a3dc42ba77).
|
|
||||||
|
|
||||||
## Server facts & gotchas (hard-won)
|
|
||||||
|
|
||||||
- VM: djg-oracle-sl, Oracle Linux 8.10, **ARM** 4c/23GB, public IP 144.24.30.131
|
|
||||||
- **k3s pinned v1.34.11**: newest kubelet (1.36) refuses cgroup v1; OL8 boots cgroup v1
|
|
||||||
and a reboot to switch would kill the agent session. Revisit only with user OK.
|
|
||||||
- kubectl: `sudo /usr/local/bin/k3s kubectl` (sudo secure_path drops /usr/local/bin)
|
|
||||||
- **firewalld is DISABLED** (it silently rejected pod-forwarded traffic → all pod
|
|
||||||
egress dead, "No route to host"). OCI security list (22/80/443) is the perimeter.
|
|
||||||
- **coredns Corefile patched**: `forward . 1.1.1.1 8.8.8.8` because OCI's
|
|
||||||
169.254.169.254 resolver is link-local and unreachable from pods. A k3s upgrade
|
|
||||||
may revert this — re-patch if pods can't resolve DNS.
|
|
||||||
- **Traefik gotcha**: without `--entrypoints.websecure.http.tls=true`, TLS routers
|
|
||||||
register but never match → every HTTPS request 404s while plaintext works.
|
|
||||||
- **hostPath gotcha**: never atomic-swap docroot dirs (mv breaks the bind by inode);
|
|
||||||
rsync in place. If a pod serves 403/empty after content ops, rollout-restart it.
|
|
||||||
- Local test: `curl -sk --resolve bestdadjokes.lol:443:127.0.0.1 https://bestdadjokes.lol/`
|
|
||||||
- Shell rule: never `cd` into a directory a command might delete (agent shell cwd
|
|
||||||
breaks and needs manual recovery).
|
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
1. Google Search Console (user creates property; HTML-meta verification token → I add)
|
|
||||||
2. Social content pipeline (needs user accounts: X/Pinterest/Bluesky/Reddit)
|
|
||||||
3. Ads: site into user's MCM/AdX; ad slots marked `<!-- AD_SLOT_* -->` in build.py
|
|
||||||
4. Daily content growth + long-tail topic pages; then paid-traffic arb experiments
|
|
||||||
5. myadhd.dev build-out (client-side tools, Paddle/Stripe when user ready)
|
|
||||||
126
SITES-HANDOFF.md
126
SITES-HANDOFF.md
|
|
@ -1,126 +0,0 @@
|
||||||
# SITES HANDOFF — bestdadjokes.lol, helpme.tips, raspiinthesky.com
|
|
||||||
|
|
||||||
**Audience:** whoever continues the sites + monetization track. Infrastructure
|
|
||||||
handoff is in HANDOFF.md (same repo) — this doc covers the three sites only.
|
|
||||||
Written by the ZCode agent that built them. Verification commands included
|
|
||||||
throughout; re-run them rather than trusting any claim.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Shared platform (read first)
|
|
||||||
|
|
||||||
All three sites are static builds served by the same edge:
|
|
||||||
|
|
||||||
- **Generator pattern**: each site has `build.py` (Python 3.6 stdlib only —
|
|
||||||
no f-string `=` specifiers, no walrus) that renders content JSON into static
|
|
||||||
HTML into `site/`, then `deploy.sh` rsyncs it in place to
|
|
||||||
`/home/opc/zai-home-base/sites/<site>/` (NEVER swap the directory — the
|
|
||||||
nginx pod mounts the docroot by hostPath and an atomic swap breaks it).
|
|
||||||
- **Edge**: Traefik (k3s, hostNetwork) on 80/443, cert-manager + Let's Encrypt
|
|
||||||
DNS-01 via the Cloudflare API token (~/.cloudflare-token, 600 perms).
|
|
||||||
Cloudflare proxies all domains (orange cloud).
|
|
||||||
- **Ad integration**: slots are marked `<!-- AD_SLOT_* -->` in the build
|
|
||||||
templates. Nothing is wired — the user's GAM wrapper spec was never
|
|
||||||
delivered. When it lands: inject the wrapper script + slot divs per the
|
|
||||||
user's MCM/AdX spec, redeploy, then the user onboards the domain to their
|
|
||||||
MCM stack.
|
|
||||||
- **Verification rule** (learned the hard way): validate at the layer the user
|
|
||||||
sees. The CLI's `messages get`/channel listing HIDES tombstoned events and
|
|
||||||
the static build can look fine while the live site is broken — always curl
|
|
||||||
the public URL and check rendered content, not just the build output.
|
|
||||||
|
|
||||||
Per-site deploys:
|
|
||||||
```
|
|
||||||
cd /home/opc/zai-home-base/bestdadjokes && ./deploy.sh # wait: dir is bdj/
|
|
||||||
cd /home/opc/zai-home-base/bdj && ./deploy.sh # bestdadjokes.lol
|
|
||||||
cd /home/opc/zai-home-base/helpme-tips && ./deploy.sh # helpme.tips
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. bestdadjokes.lol — fully operational, zero revenue so far
|
|
||||||
|
|
||||||
**Live:** https://bestdadjokes.lol (plus welcome-everyone channel on Buzz for
|
|
||||||
its audience thread). Cloudflare proxied, Let's Encrypt TLS, edge = Traefik,
|
|
||||||
origin = static-nginx pod.
|
|
||||||
|
|
||||||
**Content (as of handoff):**
|
|
||||||
- 322 jokes in `bdj/content/jokes.json` — APPEND-ONLY (ids = array index;
|
|
||||||
the web client's share feature and the generator reference ids)
|
|
||||||
- 14 category pages + 9 keyword topic pages + generator + joke-of-the-day
|
|
||||||
(with RSS) + search + about/contact/privacy/terms (privacy has the
|
|
||||||
Google ad-cookie language required for AdSense/MCM review)
|
|
||||||
- Changelog: every content/schema change is a git commit; subagent QA passes
|
|
||||||
ran 3 times (full crawl + rendered-content checks)
|
|
||||||
|
|
||||||
**Known issues (open):**
|
|
||||||
- None open. Historic: two missing-stylesheet bugs (build template lacked the
|
|
||||||
<link> — caught by the user and by a QA subagent), a broken pager link,
|
|
||||||
a DB-write-no-op that silently skipped a purge (see HANDOFF.md §6).
|
|
||||||
|
|
||||||
**Monetization status: NOTHING LIVE.** Strategy (agreed with the user):
|
|
||||||
1. Organic SEO baseline (currently zero traffic — domain is fresh)
|
|
||||||
2. Social distribution — BLOCKED on user providing social accounts
|
|
||||||
3. MCM/AdX onboarding — BLOCKED on user's GAM service account + wrapper spec
|
|
||||||
4. Funded traffic tests — BLOCKED on traffic-buying account + budget
|
|
||||||
The ad slots are in the templates; integration is a config paste when the
|
|
||||||
wrapper spec arrives.
|
|
||||||
|
|
||||||
**Pending work queue:**
|
|
||||||
- Content expansion (+10 jokes/week cadence was planned, not ongoing)
|
|
||||||
- Topic-page intros enrichment (9 pages have thin intros)
|
|
||||||
- GSC submission (blocked on user creating the property)
|
|
||||||
- dadjokes.guru sister build (design only)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. helpme.tips — live, awaiting ad integration
|
|
||||||
|
|
||||||
**Live:** https://helpme.tips (Cloudflare proxied, TLS, same edge).
|
|
||||||
Cloudflare DNS records created via API; the zone is in the CF token scope.
|
|
||||||
|
|
||||||
**Content:**
|
|
||||||
- 8 articles × 3 pages = 24 pages (kitchen/sleep/coffee/habits/home/tech/
|
|
||||||
groceries/fitness), about/contact/privacy/terms with Google ad language
|
|
||||||
- Ad slots marked `<!-- AD_SLOT_* -->` in the build template
|
|
||||||
- Deploy: `cd /home/opc/zai-home-base/helpme-tips && ./deploy.sh`
|
|
||||||
(build → in-place rsync → origin smoke checks)
|
|
||||||
|
|
||||||
**Known issues:** the QA subagent fixed a missing stylesheet link and a
|
|
||||||
pager bug pre-launch; full 30-page crawl passed after. Nothing open.
|
|
||||||
|
|
||||||
**Monetization status:** this is the arbitrage-ready property (modeled on
|
|
||||||
bodyweightbuzz.com — see the arbitrage-play memory). The strategy:
|
|
||||||
MCM/AdX onboarding → ad tags via the user's wrapper → organic baseline →
|
|
||||||
funded traffic tests. BLOCKED on the same user unlocks as bestdadjokes.
|
|
||||||
|
|
||||||
**Pending:**
|
|
||||||
- Ad integration when the wrapper spec arrives
|
|
||||||
- Content batch #2 (+10 articles) — planned, not started
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. raspiinthesky.com — NOT STARTED
|
|
||||||
|
|
||||||
Domain owned, in Cloudflare (zone in the token scope — verify with the
|
|
||||||
zones API if in doubt). No content, no deploy, no design. Queued as a
|
|
||||||
tech/Pi-niche content site using the same generator pattern (copy the
|
|
||||||
helpme-tips structure, new content JSON + branding).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Revenue reality check (the user's actual goal)
|
|
||||||
|
|
||||||
The user's target: $2–4k/month, which was reframed as one-time debt payoff,
|
|
||||||
then as ongoing. Current revenue: **$0** across all three. The dependency
|
|
||||||
chain to first revenue:
|
|
||||||
|
|
||||||
1. User: GAM service account (they offered it — never delivered)
|
|
||||||
2. User: MCM onboarding of helpme.tips + bestdadjokes.lol
|
|
||||||
3. Agent: ad wrapper integration (slots exist; spec pending)
|
|
||||||
4. User: traffic-buying account + float for funded tests
|
|
||||||
5. Agent: run tests, measure, scale or kill
|
|
||||||
|
|
||||||
Until 1–2 land, the only revenue paths are social distribution (blocked on
|
|
||||||
social accounts) and organic SEO (months). Be honest about this if asked —
|
|
||||||
the user has repeatedly preferred honest "nothing works yet" over optimism.
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
# Micro-SaaS ideas — "stupid simple deadline tools" shortlist
|
|
||||||
|
|
||||||
Researched 2026-09-16. Pattern: **a calendar with teeth** — tool X has no native
|
|
||||||
expiry/deadline feature + an auditor/law requires it + incumbents are enterprise-
|
|
||||||
priced → tiny flat-rate SaaS. Buyers are compliance-driven (dates + fines), not
|
|
||||||
taste-driven — which suits us (no sales channel, but SEO + community distribution).
|
|
||||||
|
|
||||||
De-risk protocol per idea: landing page + one community post → measure email
|
|
||||||
signups for a week → build only if ~30-50 signups. Infra spins landing pages up
|
|
||||||
in an hour. Billing: Paddle/Stripe (user account, pending).
|
|
||||||
|
|
||||||
## Ranked shortlist
|
|
||||||
|
|
||||||
### 1. COI (certificate of insurance) / vendor compliance tracking — FLAGSHIP
|
|
||||||
- Who pays: small general contractors, property managers, agencies.
|
|
||||||
- Evidence: manual COI tracking costs ~$36,400/yr in labor
|
|
||||||
(https://www.bramble.solutions/learn/coi-tracking-software/); enterprise tools
|
|
||||||
$500+/mo "prohibitively expensive" for small contractors
|
|
||||||
(https://trackmyvendor.com/compare-coi-tracking-software); new self-serve
|
|
||||||
entrants price per-vendor $0.95-$20/mo (https://www.getbcs.com/pricing-and-plans)
|
|
||||||
→ validated demand, SMB gap still open but entrants arriving — wedge is
|
|
||||||
FLAT price ($25-30/mo unlimited vendors) + simplicity.
|
|
||||||
- v1: vendors + policy uploads + expiry reminders (email/SMS) + audit log.
|
|
||||||
Days of build. SEO keywords: "coi tracking for small contractors".
|
|
||||||
|
|
||||||
### 2. STR / rental permit & license deadline tracking
|
|
||||||
- Who pays: short-term-rental hosts, small landlords.
|
|
||||||
- Moat: per-city permit renewal rules (fragmented data nobody maintains well).
|
|
||||||
- Hosts already pay for tools. Fines for missed renewals are real.
|
|
||||||
- 1-2 weeks build (data collection is the work).
|
|
||||||
|
|
||||||
### 3. DMARC/SPF/DNS watchdog for SMB domains — WARM-UP (shippable this week)
|
|
||||||
- Who pays: any small business burned by email deliverability breaking.
|
|
||||||
- $5-10/mo. Very fast build; becomes lead-gen for the rest.
|
|
||||||
|
|
||||||
### 4. Equipment inspection logging (fire extinguishers, backflow, AED)
|
|
||||||
- Small facility managers, churches, schools. Paper logbooks today,
|
|
||||||
fire-marshal fines. 1 week build.
|
|
||||||
|
|
||||||
### 5. Employee cert / CE expiry tracking (small clinics, trades)
|
|
||||||
- Office managers; HR platforms are enterprise. 1 week build.
|
|
||||||
|
|
||||||
### 6. Access-review evidence generator (user's original postgres idea, generalized)
|
|
||||||
- Postgres + GitHub + AWS → quarterly access-review PDF for pre-SOC2 startups
|
|
||||||
(10-50 people; spreadsheets until ~50 per
|
|
||||||
https://www.accessowl.com/blog/detailed-guide-to-soc-2-access-reviews).
|
|
||||||
- Risk: security buyers demand brand trust; integrations = scope creep. Rank last.
|
|
||||||
|
|
||||||
## Why these beat our failed attempts
|
|
||||||
Compliance pain is a date with a fine attached (deadline-based), not a taste call
|
|
||||||
(taste-based sells failed twice: ad-tech tools, site audits to cost-averse
|
|
||||||
publishers).
|
|
||||||
|
|
||||||
## Validation status
|
|
||||||
| # | landing page | signups | build |
|
|
||||||
|---|---|---|---|
|
|
||||||
| 1 | not started | — | — |
|
|
||||||
| 2 | not started | — | — |
|
|
||||||
| 3 | not started | — | can ship immediately |
|
|
||||||
|
|
||||||
Needs to proceed: product domain(s) (~$10 each, registrar-side), Paddle/Stripe
|
|
||||||
(user).
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
# Service menu — draft for [YOUR COMPANY NAME]
|
|
||||||
|
|
||||||
> One-time technical services, delivered by our automation stack, QA'd by our
|
|
||||||
> engineers. Fixed prices, fast turnaround. Edit freely — this is a draft for
|
|
||||||
> your voice/branding.
|
|
||||||
|
|
||||||
## 1. Ad-ready publisher site — 48 hours — $750–1,500
|
|
||||||
A complete, fast, policy-clean publisher site: 8–20 original articles
|
|
||||||
(paginated for session depth), consent/privacy pages, hosting on our
|
|
||||||
infrastructure, Cloudflare DNS + TLS, and your ad tags wired in.
|
|
||||||
You own the domain and the inventory. Includes 30 days of hosting.
|
|
||||||
|
|
||||||
Upsell: content expansion (+$25/article/mo), additional niches, analytics setup.
|
|
||||||
|
|
||||||
## 2. Ad setup / revenue-leak audit — $500
|
|
||||||
We audit a publisher's ad setup end to end: tag placement, viewability,
|
|
||||||
lazy-loading, consent handling, layout stability (CLS), fill-rate basics.
|
|
||||||
Deliverable: a prioritized report of leaks with fixes — or we fix them
|
|
||||||
(see #4).
|
|
||||||
|
|
||||||
## 3. Core Web Vitals overhaul — $750
|
|
||||||
LCP/CLS/INP measured before and after (Lab + field numbers included).
|
|
||||||
Typical wins: image pipeline, font loading, render-blocking cleanup,
|
|
||||||
cache headers. Deliverable: before/after report + deployed fixes.
|
|
||||||
|
|
||||||
## 4. Fix-it engagement — from $500
|
|
||||||
Anything in our wheelhouse, quoted fixed-price after a 30-minute call:
|
|
||||||
site migrations, DNS/CDN cleanup, monitoring/alerting, uptime postmortems.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Notes for internal use:
|
|
||||||
- Delivery cost to us is near zero (automation + QA pass). Margin ~95%.
|
|
||||||
- Turnaround promise: #1 is the only 48h item; others are 2–3 business days.
|
|
||||||
- Order of pitches: warm publisher clients first (they know our ad ops work),
|
|
||||||
then any publisher community we're active in.
|
|
||||||
- Collection: invoice through the existing company (rails already exist).
|
|
||||||
Loading…
Reference in a new issue