惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
T
Threatpost
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - Franky
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell
M
MIT News - Artificial intelligence
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
S
Security Affairs
P
Proofpoint News Feed
L
LINUX DO - 最新话题
宝玉的分享
宝玉的分享
S
Security @ Cisco Blogs
H
Hacker News: Front Page
Security Archives - TechRepublic
Security Archives - TechRepublic
Vercel News
Vercel News
Engineering at Meta
Engineering at Meta
Know Your Adversary
Know Your Adversary
Y
Y Combinator Blog
美团技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
月光博客
月光博客
量子位
博客园_首页
The Last Watchdog
The Last Watchdog
D
DataBreaches.Net
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed
The Register - Security
The Register - Security
Schneier on Security
Schneier on Security
H
Help Net Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
F
Full Disclosure
C
Cyber Attacks, Cyber Crime and Cyber Security
MyScale Blog
MyScale Blog
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
L
Lohrmann on Cybersecurity
S
Secure Thoughts
Stack Overflow Blog
Stack Overflow Blog
Cloudbric
Cloudbric
Microsoft Security Blog
Microsoft Security Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
I asked ChatGPT for free status page tools. It didn't mention mine. Here's the Next.js + Supabase build behind that zero.
Hao · 2026-05-05 · via DEV Community

Twenty-four hours after I swapped Supabase Auth's default SMTP for Resend, my first real user signed up. I'll call him K. I emailed him three questions. He replied in 49 minutes: "make a better ui of admin so we can use." That sentence is now my Q2 roadmap. Three weeks into launch I have 3 users, 2 Google clicks, and zero mentions when you ask ChatGPT or Gemini for "free status page alternatives." This is what I shipped, and where I'm still wrong.

Why I built another status page (when there are already 15)

I launched EurekaWrite last year. Every time I deployed, users DM'd me the same question: "is it down?" I'd check, reply, repeat. After the tenth round I wanted a public URL I could send instead of typing the same reply. So I looked at what existed.

Statuspage.io is $29/month for a page that says "All Systems Operational." That's $348 a year for one indie project that earns nothing yet. Skip.

Upptime is free and open source. I tried it. Three things to learn before I get a public URL: a YAML monitor schema, a GitHub Actions workflow file, and the repo-as-config mental model where every status update is a commit. For a side project I want to ship in an evening, that is two evenings of yak-shaving I do not want.

So I built StatusPageBuddy. The pitch on the landing page is one line: "Skip the YAML, the GitHub Actions, and the $29/month bill." Type a name. Get a link. Share it. 60 seconds, free forever.

One scope decision worth naming: SPB is the public-facing page, not the prober. It is not a monitoring tool. That is deliberate. The trade-off buys 60-second onboarding: no built-in HTTP checks, no alerting rules engine, no integrations tab. Those are the three things a monitoring product would ship on day one and the three things SPB deliberately does not.

StatusPageBuddy landing hero — 60 seconds, free forever

The Supabase default that cost me a month of signups

The stack that gets to 60 seconds is small on purpose.

The stack:

  • Next.js 16.2.1 + React 19 on Vercel
  • Supabase for Auth, Postgres, and RLS
  • Resend for transactional email

The part that cost me a month was a default I never thought to question.

Supabase Auth ships with a built-in SMTP sender for confirmation emails. It is rate-limited to 3-4 messages per hour on the free tier, and the From address is on a shared Supabase domain. That combination did two things. It throttled my signup flow during the only window people were trying it, and it routed the rest to spam. I watched signups start the flow and never come back, and I assumed the product was the problem.

I caught it by accident. I created a fresh test account from a Gmail address I never use, watched the email never arrive, checked spam, and there it was. I sent another. Same path. Then I read the Supabase docs page on production SMTP and found the line I had skimmed past during setup: the built-in sender is for development, not production.

The fix took 20 minutes:

  1. Create a Resend account
  2. Verify a sending domain (one DNS record for SPF, one for DKIM)
  3. Paste the Resend SMTP credentials into Supabase Auth → SMTP Settings
  4. Flip the toggle from default to custom
  5. Send a test signup, watch it land in inbox not spam

Twenty-four hours later, K. signed up. I had been live for almost a month.

If you are on Supabase and you have not swapped the default SMTP, swap it first. It is not a scaling concern. It is a "your funnel is closed and you do not know it" concern.

Supabase Auth SMTP settings — custom SMTP enabled via Resend

Now the architecture piece. The SMTP fix reopened the funnel; RLS is what lets me sleep at night with multi-tenant data in one Postgres database.

SPB is multi-tenant: a user can belong to multiple orgs via an org_members join table, and every status_pages row is scoped to an org_id. The entire authorization layer for that table is one policy:

-- status_pages: a user sees only the pages of orgs they belong to
create policy "org_isolation" on status_pages
  for all using (
    org_id in (
      select org_id from org_members where user_id = auth.uid()
    )
  );

Enter fullscreen mode Exit fullscreen mode

Every read, write, update, delete from any client goes through that filter. The route still exists (Next.js RSC fetch, API handler, whatever), but the route can't leak rows: the query just returns zero. The counterfactual is the if (user.org_id !== page.org_id) throw 403 guard you'd otherwise sprinkle through every API handler and forget in exactly one of them. That forgotten one is the breach. RLS deletes the category.

Three weeks of cold outreach, by the numbers

Architecture closes the breach. It does not bring users. For that I had a spreadsheet and three weeks.

Week 1: 17 cold touches, 0 signups. Comments on indie-dev threads, replies in Supabase Discord, two PRs to awesome-* lists, one Twitter post from a 40-follower account. The Twitter post drew 2 impressions. That is the expected ceiling for a cold account with no graph, and it confirmed what I already suspected: Twitter is not a channel for me yet, it is a vanity surface I should stop touching until I have a reason to be there.

Week 2: 8 cold touches, 3 signups. Fewer touches, tighter targeting — I dropped the broad "any indie thread" comments and only posted in places where someone had already named the problem ("what status page should I use," "alternatives to Statuspage.io"). The signups landed as K. on 4/25, R. on 4/28, M. on 5/1.

The read on attribution: it is asset accumulation, not single-touch. The Supabase Discord #showcase post went up 4/22. K. signed up 4/25. Three days, not three minutes. The awesome-status-pages PR (#194) merged 4/19, before W1 even started counting, and it almost certainly fed R. and M. later through SEO. Neither of them came from anything I did the day they signed up. They came from work that had been sitting on someone else's page for a week or two.

The pattern: ecosystem PRs (awesome-status-pages #194, plus a second PR to awesome-selfhosted queued for review) and GitHub Issues where someone had already typed the buying question. Twitter stays off the list until I have a reason to be there.

Outreach tracker — Week 1 (17 touches, 0 signups) vs Week 2 (8 touches, 3 signups)

The first-user moment — why feedback in under 50 minutes changed the roadmap

I gave K. 24 hours to poke around, then sent three questions over email. No marketing, no "we'd love your thoughts," signed "Hao."

He replied in 49 minutes:

"make a better ui of admin so we can use"

That is the verbatim reply. One sentence, no punctuation, no hedge.

I had been planning a 12-question survey. I scrapped it. One sentence from a real user beats a survey because it tells you which bottleneck you are actually staring at. I had been optimizing acquisition — outreach lists, PR titles, Discord threads. K. told me the wall was activation, and inside activation it was the admin UI specifically. He had signed up. He had gotten in. He could not get out the other side with a working page.

If you want more posts like this — same numbers, smaller doses, sent Sundays — subscribe at statuspagebuddy.com/subscribe. One email a week.

The follow-up I sent the next day, 4/28, did one thing: it forced a choice. "Which screen is the worst right now: components, incidents, or settings? Send a screenshot of the one that frustrated you most." Three options, one ask, one attachment. That is the shape that turned a free-form sentence into shippable scope. The trap with "tell me more" is that the user has to do the structuring work for you, and they will not. Give them the menu.

The reusable shape of the email, in case it helps:

  1. Three questions, max.
  2. One of them forces a choice between named options you already know exist.
  3. One asks for an artifact (screenshot, link, snippet) so the reply has weight.
  4. Sign with your first name, not the company.

The funnel gap — when your spec is the bug

K. told me activation was broken. R. showed me the data side of the same wall.

R. signed up 4/28. He created an org. He never built a page. The status_pages table for his org_id stayed empty.

I had a cron job that was supposed to catch exactly this case. It runs nightly, finds users who signed up more than 48 hours ago and have not "activated," and queues a reminder email. It never fired for R.

The reason is embarrassing in the way good bugs always are. The cron's predicate for "activated" was has_org. R. had an org. The query, correctly, returned zero rows. The code did exactly what it was told. The instruction was wrong.

This is not a bug. The compiler did not lie. The database did not corrupt. The spec was wrong, and the spec was wrong because at the time I wrote it I had no users, and "create an org" felt like the meaningful step. Of course it did. It was the last step in the onboarding flow I had built. From the inside it looks like the finish line. From the user's side, the finish line is a published page someone else can load in a browser.

Fix: redefine activation as has_at_least_one_published_page. Re-fire the reminder cron with the new predicate. The two clauses, side by side:

-- old: activation = "user has at least one org"
where not exists (select 1 from org_members where user_id = u.id)

-- new: activation = "user has at least one published page"
where not exists (
  select 1 from status_pages sp
  join org_members om on om.org_id = sp.org_id
  where om.user_id = u.id
)

Enter fullscreen mode Exit fullscreen mode

R. now sits in the queue for tonight's run.

The takeaway I want to carry into the next product I build:

Your activation predicate is a product decision disguised as a SQL clause.

The schema makes one predicate cheap to query. The user behavior you actually care about is almost always a different one. Anywhere those two diverge, your dashboards look fine and your funnel stays empty. Mine was off by one join.

What ChatGPT and Gemini say about my product (nothing)

Schema fixes are inside-the-box work. The next beat is whether anyone outside the box can find SPB at all.

On 5/2 I ran the check I had been avoiding. ChatGPT first: "free statuspage alternatives for indie developers." Then the same prompt into Gemini.

Neither mentioned StatusPageBuddy. Baseline = 0.

Both named the obvious incumbents — Statuspage, Instatus, Better Stack, Upptime, a couple of self-hosted Docker projects. I tried a second prompt ("cheap status page for a side project, not Statuspage.io"). Same result.

This is the data point most build-in-public posts skip, because a zero is embarrassing in a way a low number is not. A low number reads like progress. A zero reads like absence. But LLMs are now a real discovery surface. When an indie dev asks for a tool today, a meaningful share of them ask a model first and Google second. A zero baseline is where the work begins.

What I'm doing about it, in three lanes:

  1. Ecosystem PRs to awesome-* lists for permanent backlinks that crawlers and training pipelines both eventually find. Next on the queue: awesome-selfhosted and awesome-sre.
  2. One weekly long-form post (this is the first) on dev.to and IndieHackers, canonical on the SPB blog.
  3. One Beehiiv issue per week, short and numbers-forward. First issue title: "Week 3: 3 users, 2 Google clicks, 0 AI mentions."

One PR, one post, one issue per week. I picked twelve weeks because that's one full GSC reporting window plus a buffer — long enough that "no movement" means the strategy is wrong, short enough that I'll still care. The lane I expect to fail first is the awesome-list PRs: most of those repos are unmaintained, and a merged PR is not a guaranteed crawl.

ChatGPT and Gemini answers to

SEO baseline — the search numbers nobody publishes

The older surface is search. Vercel Analytics, week of 4/25–5/2: 28 unique visitors, down 45% week-over-week. 120 page views. 68% bounce rate.

External referrers across the whole week, all sources combined: Google 2, Bing 1, GitHub 1. Four real external clicks in seven days. Everything else was direct or me.

Search Console, three-month rolling total: 2 clicks, 13 impressions, 15.4% CTR, average position 2.6.

Read that last line again. Average position 2.6. When SPB shows up at all, it ranks third on the page. The CTR is fine. The ranking is fine. The problem is that SPB shows up on thirteen queries in three months, total. Nobody is typing the queries I'd rank for, because the queries I'd rank for are queries nobody types.

The takeaway is uncomfortable: SEO ranking is not the bottleneck for a product like this in week three. Indexed surface area is. There are not enough pages on the open web that mention SPB for Google to surface, and not enough pages that mention SPB inside any LLM's training cut for it to recall the name. That is the same problem the AI baseline points at, from the other side. Both fixes look like the same fix.

This is roughly what week three looks like for any indie product without an existing audience. The interesting question is not whether the numbers are small. The interesting question is what the curve does between week three and week twelve.

Search Console 3-month summary — 2 clicks, 13 impressions, 15.4% CTR, position 2.6

What I'm shipping next

Three things that move the curve, in order.

First, the admin UX overhaul K. asked for. Broken into three sub-tasks I can ship one per week: components screen, incidents screen, settings screen. The components screen is first because that is the one he sent the screenshot of.

Second, the activation predicate fix from the funnel-gap section. Ship the new predicate, re-fire the reminder cron with R. in the queue, then leave it running so any future "org-only" user gets caught the same night.

Third, a one-click "create demo page" on first org-create. The funnel gap was a missing reminder, but the deeper gap was that creating a page felt like a separate decision after creating an org. If the org-create handler also writes a draft page row, the activation predicate flips on the same click. That kills the same-shaped gap at the source instead of catching it on a cron 48 hours later.

What would make the next post worth writing, as a threshold, not a scorecard: a non-zero AI mention, a second activated user, and the first 5 newsletter subs. If none of those move, I'll publish the same skeleton with the same zeros and write about why none of them moved. That is also a post.


The newsletter is the main thing I'm asking for. Subscribe at statuspagebuddy.com/subscribe. This Sunday: the W3 outreach data, whether the admin UX rewrite moved activation, and whether anything I shipped this week showed up in ChatGPT. One email a week. Hit reply.

If you actually need a status page, statuspagebuddy.com is free forever for indie projects. Type a name, share a link. If something breaks, email me — same Hao.