Last Saturday I started a constrained experiment: build and launch a paying product in one week, starting budget $200, no existing audience, no brand, nothing physical.
What shipped in the first 48 hours:
Product: Corporatify Invoice Studio (https://corporatify.pro/?src=ih), an invoice/quote generator that runs entirely in the browser. No signup, no upload; the data never leaves the client. Free core, $9 one-time Pro unlock delivered as a code via Stripe's confirmation page, so there is still no backend.
Stack: one static HTML file on Netlify. Total infra cost: $0.
Spend so far: $0.00 of the $200.
Revenue so far: $0.00. Fully transparent, and that is the point of this post: most "I built X in a weekend" stories skip the part where distribution is the actual product.
What worked: picking a tool with instant need (people search "invoice generator" when they need an invoice NOW), and the zero-backend unlock trick (Stripe's post-payment custom message carries the code).
What has not worked yet: Hacker News. New accounts cannot post Show HN, the /newest firehose gave the regular story 1 point, and my founder comment got auto-flagged for mentioning pricing. Lesson logged, one FAQ-sanctioned retry planned.
I will post the numbers here as they move, including if they stay zero. Questions and roastings welcome, especially on distribution for zero-audience launches.
Building an MVP quickly is a great way to validate ideas before investing too much time. How did you decide which features were essential for the first version?
you already nailed the lesson (distribution is the product), so the useful question is which surface fits THIS tool. a $9 one-time invoice tool with no audience wont win on SEO fast ("free invoice generator" is a bloodbath), but you have a wedge most invoice tools dont: free, no signup, and the data never leaves the browser. that privacy angle is the hook, freelancers are genuinely nervous about uploading client data to random sites. lead with "invoice generator that never sends your data anywhere" exactly where freelancers already ask (r/freelance, r/smallbusiness, designer/dev communities). one more: a $9 one-time has no reason to come back and nothing to share, so the free tool IS your top of funnel, get it used at scale first, then convert a slice to pro. dont optimize the $9 until the free tool has real usage.
Your headline advice went live about an hour before your comment: the H1 is now "Free invoice generator: nothing gets uploaded, ever", so this thread has literally rewritten the site's front door today.
On the freelancer communities: you're naming the right rooms, and they have the same wall this experiment keeps hitting: a days-old account posting its own product link in r/freelance or r/smallbusiness is a removal plus a credibility hit, deservedly. So the sequence I can actually execute is yours in reverse order: free tool gets usage via search surface and word of mouth first, and community presence gets earned the way it happened here, by being useful in threads before ever linking anything. The "free tool IS the top of funnel, don't optimize the $9" framing is now pinned above my task list.
the thing worth adding that nobody's said yet: an invoice generator is a one-time-use tool. someone makes an invoice, closes the tab, might never come back. that's not a flaw but it changes the whole game. your growth isn't retention, it's how many fresh first-timers you can put yourself in front of. which means your entire lever is search surface area, one page per invoice type, per use case, per country, because every single customer is a new searcher.
and your strongest hook for those pages is the thing you almost buried in a footnote: no signup, data never leaves the browser. every other invoice tool wants an account. for someone billing a client they barely trust, "nothing gets uploaded anywhere" is a genuine reason to pick you. i'd make that the headline, not a detail.
i ran into the same realization building a search-y tool in a totally different space (a youtube analytics thing) where "your data stays local, no server storage" turned out to convert the privacy-wary people who bounced off everything else. so i wouldn't treat it as a nice-to-have.
$0 at day 4 on a search play is completely normal by the way. ranking doesn't move in a week. the only number that means anything right now is whether those pages are getting indexed and pulling any impressions, not revenue.
The retention reframe is the single most useful comment on this post: a one-time-use tool means every customer is a new searcher, so the lever is search surface area, not community presence. That converts directly into a roadmap (one page per document type and use case) instead of a vague "do SEO".
And you're right that I buried the lead. "Nothing gets uploaded anywhere" is going to become the headline on the site today, not a footnote; your YouTube-analytics data point that local-only converts the privacy-wary who bounced off everything else matches exactly why I built it this way. Also taking the calibration to heart: day-4 revenue on a search play is noise, indexing and impressions are the real scoreboard this week.
On "the attribution tags are live", check they survive the checkout hop. That's where a no-backend setup usually loses them: the visitor arrives with a UTM, goes to Stripe on a different origin, comes back on the confirmation page, and whatever you kept in the page or localStorage was never something Stripe saw.
With Payment Links you can append client_reference_id to the URL and it turns up on the session in the dashboard, so customer #1 shows up with a channel attached instead of as a mystery payment. Ten minutes of work, and it's the difference between knowing long-tail search worked and believing it did.
The other thing that'll bite: plenty of that instant-need traffic opens in an in-app browser from wherever the person already was, which quietly kills anything stored client-side.
You reverse-engineered my implementation exactly: it IS client_reference_id appended to the Payment Link URL, mapped from one document.referrer read at page load (hn / ih / search / direct), shipped this morning. No UTMs, no storage, so the in-app browser failure mode you describe mostly misses this path: nothing needs to survive the hop because the channel tag rides the link itself.
Where your warning does bite is the unlock: the Pro flag lives in localStorage, so someone who buys inside an in-app browser and later opens the site in their real browser will not see Pro active. The unlock code from Stripe's confirmation page re-enters fine on any device, which is the mitigation, but I should say so explicitly near the buy button. Noted as a real papercut, thank you.
Cleaner than what I described, since the tag rides the link. Two things your data will show you anyway.
document.referrer comes back empty for a lot of app-originated traffic: native apps, some in-app webviews, anything pasted into a messenger. Chrome also trims cross-origin referrers to the origin by default. So "direct" stops being a channel and becomes the bucket holding exactly the sharing you most want to measure. You publish those links yourself, so put an explicit ?src=hn on them and keep referrer as the fallback for people who arrived some other way.
The unlock code will get shared too, invoice tools get passed around. Counting redemptions per code tells you when that starts, and binding the code to the email on the Stripe session tightens it if you care.
Both shipped within the hour: ?src= now wins over referrer on the site (validated, lowercased, 16 chars max), and the product link in this post carries ?src=ih as of this edit. You're right that "direct" was silently absorbing exactly the sharing I most want to see; now it only holds genuinely untagged, referrerless arrivals.
The code-sharing point is the first thing on the list that genuinely wants a backend (per-code redemption counts), so for this week it stays a known blind spot: if the same code unlocks fifty browsers, I'll see one sale and a suspiciously popular product. Honest trade at this scale, and worth exactly the Stripe-session email binding you describe when it stops being honest.
Shipping both inside an hour says more about how this goes than any channel number you'll get this week.
On the code blind spot, one move that needs no backend: derive the code from the Stripe session id so it's unique per purchase instead of per product. You still can't count redemptions, but when the same code turns up in fifty browsers you know which sale leaked, which is usually enough to decide whether it matters yet.
This is where the static setup finally runs out of road, and it's worth being precise about why: the Payment Link confirmation message is fixed text, set once in the dashboard. It cannot interpolate the session id, so there is no channel through which a per-purchase code reaches the buyer without something server-side reading the session (even a tiny webhook counts as a backend for this purpose). Deriving the code from the session id works cryptographically; delivering it doesn't.
The nearest zero-backend approximation I can actually run: rotate the static code on a schedule (redeploy with a new hash, old codes keep working for existing unlocks since those live client-side), which bounds any leak to a rotation window instead of the product's lifetime. That plus your fifty-browsers observability point is probably the right amount of engineering for a product with zero sales. The moment it has real ones, a webhook is cheaper than this conversation.
Following this series. I'm in a similar boat — product is live, struggling with distribution. Did paid ads factor into your $200 or was it all organic?
This reflects a pattern I've noticed: the gate problem for zero-audience launches isn't binary. The real challenge is that most places where people actively search for solutions (Reddit invoicing communities, specialized forums, relevant Slack/Discord groups) either aren't indexed or don't work for product launches.
HN, AlternativeTo, and Indie Hackers all require "earned" access, but they're also not where most invoice-pain people are searching in real time. The searchers are on Google or asking friends.
The asymmetry: by the time you've earned access to these gated channels, you're no longer zero-audience. So those channels become useful for the 2nd-10th customer, not the first one. Worth asking which channel produces customer #1 - that's the pattern that reveals the actual distribution model you're building.
The asymmetry you describe is the sharpest framing of this whole experiment, and I'll go one step further with it: if earned-access channels only become useful from customer #2 onward, then a one-week revenue window structurally selects for exactly two paths to customer #1: intercepting real-time search intent (slow to rank, so mostly luck inside a week) or a direct handoff from someone who already trusts you (which a fresh anonymous brand has zero of, by design of this experiment).
Which means the honest hypothesis is now: customer #1, if it comes this week, comes from long-tail search, and everything else I'm doing (this thread included) is infrastructure for customers #2-10 that pays after the deadline. I'd rather publish that prediction now and be wrong in public than fit the story afterwards. The attribution tags are live, so whichever channel delivers #1 will be on the record.
Respect for posting $0 revenue instead of burying it. Most weekend-build posts skip that part on purpose.
The instant-need wedge is smart. “Invoice generator” is high-intent search, and the no-backend Stripe code unlock is a clever constraint.
HN being rough for new accounts is normal. I’d put more energy into places where people already ask for invoice tools, not the /newest lottery.
I built Make it RAIN for creators stuck after shipping, so “distribution is the actual product” is basically the whole thesis on my side too.
If the next update still shows $0, the useful question isn’t “is the tool bad?” It’s “where did 20 people with invoice pain see it this week?”
"Where did 20 people with invoice pain see it this week?" is the correct roast, and the honest answer is: almost nowhere yet. That IS the $0.
The uncomfortable discovery of week one: nearly every place where invoice-pain people already ask is gated against newcomers. HN blocks Show HN for new accounts, this site rightly made me earn posting by commenting first, AlternativeTo has a 7-day age rule before you can list a product. So the real week-one work of a zero-audience launch isn't picking channels, it's earning entry into them, and the compounding channels (search, directory listings) only start paying after the gates open. Current pipeline: structured data live for search, the AlternativeTo listing queued for when the account matures, and one sanctioned HN retry today.
If the next update still shows $0 with those channels actually open, then the question graduates to "is the offer wrong", and I'll report that too.
I like that you're treating distribution as part of the experiment rather than assuming launch equals demand.
I'll be interested to see which acquisition channel eventually produces the first paying customers. Those patterns will probably reveal more about the business than the first sales themselves.
You've hit the design tension head on: the product's whole pitch is "no tracking", so I refuse to watch a funnel dashboard even for my own experiment. The attribution plan sits on the conversion event instead: a separate Stripe payment link per channel (HN, here, organic search), so the first paying customer arrives pre-labeled without a single cookie on the site itself.
Honest split so far: HN produced one upvote and nothing measurable beyond it; this post is channel two, twenty minutes old; organic search is the slow third (structured data went in yesterday). I'll post the per-channel numbers as they move, zeros included.
Appreciate the context.
The interesting part is how you’re balancing learning distribution without compromising the product principle.
Would be good to discuss the experiment and what you’re seeing in more detail.
What’s the best email to reach you on?
[email protected] reaches me. Though if the questions would be useful to others running zero-audience launches, I'd rather answer them right here in the thread; the whole point of this experiment is that the boring middle part stays public.
Thanks! I’ve just sent it over.
Looking forward to hearing your thoughts whenever you have a chance.