50% off SaaS Starter Kit — only for the first 100 buildersGrab it →
← Back to blog
best-practicesMay 22, 2026·11 min read

Building in Public: What Actually Works, What Doesn't, and What's Just Cringe

We've been building peal.dev in public for a while now. Here's the honest breakdown of what moves the needle and what's just performance art.

Ștefan Binisor

Ștefan Binisor

Co-founder, peal.dev

Building in Public: What Actually Works, What Doesn't, and What's Just Cringe

Building in public has this reputation as a magic growth hack. Post your MRR, share your wins, document the journey — and somehow people will flock to your product. That's the pitch, anyway. The reality is messier, more interesting, and involves a lot more awkward silence than the Twitter success stories suggest.

We've been doing some version of building in public since we started peal.dev. Not because we read a blog post about it being a growth strategy, but because we like talking about the technical problems we're solving and we figured if we're going to be writing things down anyway, we might as well do it where people can see it. Here's what we've actually learned.

What "Building in Public" Actually Means (vs. What People Think It Means)

Most people think building in public means posting a monthly revenue update with a chart that (hopefully) goes up and to the right. Some people think it means being parasocially oversharing about every emotion you feel while building a SaaS. The useful definition is narrower: it means making your process legible to other people in a way that's genuinely useful to them, and incidentally useful to you.

The key word is "genuinely." If you're sharing something because you think it'll make you look good, or because some build-in-public guru told you to post daily — people can smell it. Developers especially. We have finely tuned BS detectors because we spend all day reading documentation that's trying to make every product sound perfect.

The test for whether something is worth sharing publicly: would you send this exact post to a developer friend who'd call you out if it was stupid? If yes, post it. If you're hedging because you're worried how it looks, either fix it until you believe it or don't post it.

What Actually Works

Sharing specific technical problems you solved — with the actual code — consistently gets more engagement than any "here's our MRR update" post. Not engagement in the vanity metrics sense. Engagement in the sense of people actually replying with useful things, finding your project, and occasionally becoming customers.

When we wrote about the subdomain routing approach we use for multi-tenant Next.js apps, we got three separate people DMing us saying they'd been wrestling with the same thing. Two of them ended up buying templates. That's not because we were clever about marketing — it's because we wrote down a real problem we had, the wrong solutions we tried first, and what eventually worked.

// This is the kind of thing worth sharing publicly:
// The WRONG approach we tried first (helpful to document!)
export function middleware(request: NextRequest) {
  // ❌ First attempt: parsing subdomain from host header directly
  // This breaks in development, on Vercel preview URLs, and
  // any time your hostname has more than 2 parts
  const host = request.headers.get('host') || ''
  const subdomain = host.split('.')[0] // DON'T DO THIS
  
  // ❌ Also breaks on localhost:3000, 192.168.1.1:3000, etc.
  return NextResponse.rewrite(new URL(`/${subdomain}${request.nextUrl.pathname}`, request.url))
}

// The approach that actually works:
export function middleware(request: NextRequest) {
  const host = request.headers.get('host') || ''
  const hostname = host.replace(':3000', '').replace(':443', '')
  
  // Handle localhost and IP addresses
  const isLocalhost = hostname === 'localhost' || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)
  
  if (isLocalhost) {
    // In dev, use a query param or path segment instead
    return NextResponse.next()
  }
  
  const parts = hostname.split('.')
  // Needs at least: subdomain.domain.tld (3 parts)
  const subdomain = parts.length >= 3 ? parts[0] : null
  
  if (!subdomain || subdomain === 'www') {
    return NextResponse.next()
  }
  
  return NextResponse.rewrite(
    new URL(`/tenant/${subdomain}${request.nextUrl.pathname}`, request.url)
  )
}

That's worth posting. The wrong attempt, the reason it was wrong, the fix. Not "we built multi-tenancy, here's our MRR." The technical specificity is what makes it worth reading.

Failure stories also work — but only when they're specific and you're not performing vulnerability. "We launched and got zero signups" is not interesting. "We launched and got zero signups, and after talking to 8 people we realized we'd built an elaborate solution to a problem nobody had, specifically because we were afraid to do the boring obvious thing" — that's interesting, because it contains information other people can use.

What Doesn't Work (And Why People Keep Doing It)

Vanity metric updates posted on a fixed schedule. "Week 47 update: 3 new users, $0 MRR, still grinding." Nobody cares, and more importantly, YOU don't actually care — you're doing it because some advice said to be consistent. Consistency is useful when you have something consistent to say. When you don't, consistency is just noise.

Fake vulnerability. This one's harder to describe but easy to spot. It's when someone posts about how hard entrepreneurship is, how they almost quit, how the journey is difficult — but in a way that's actually just a humble brag about how dedicated and resilient they are. The tell is that there's no specific mistake, no concrete thing that went wrong, no actual useful information. It's just vibes dressed up as openness.

Posting for the algorithm. This is where building in public goes completely off the rails. When you start thinking about what kind of content "performs well" rather than what's actually true or useful, you've exited building in public and entered content marketing. Nothing wrong with content marketing, but pretending it's authentic is where the cringe lives.

  • Posting revenue numbers when you're at $0 — there's no reason to do this except to perform hustle culture
  • "Here's what I learned this week" posts that are just restating obvious things everyone already knows
  • Engagement bait framed as building in public: "I almost quit today. Should I keep going? Reply below."
  • Product screenshots of things that don't work yet, posted like they already work
  • Parasocial oversharing that makes readers feel responsible for your emotional state

The Cringe Taxonomy

There are different flavors of cringe in the build-in-public space, and it's worth naming them because they come from different places.

Hustle-cringe is when someone is clearly performing hard work more than doing it. The person who posts at 2am about "still coding, no days off" — but the code they're posting is a hello world component. This is mostly harmless but it's a trap because you start optimizing for the appearance of building rather than the building itself.

Guru-cringe is when someone who has one minor success starts packaging it as universal advice. "Here's the exact framework I used to get to $500 MRR" — friend, $500 MRR is a nice start, not a framework worth copying. We try hard to avoid this by being specific about what worked for us and acknowledging we don't know if it generalizes.

Transparency-cringe is the most insidious one. It's when "being transparent" becomes the brand rather than the product. When every post is about the process of building and nothing is actually about what you're building or who it's for. At some point you need to ship something that people want. No amount of public journaling substitutes for that.

If someone follows your building-in-public content for 6 months and can't clearly explain what your product does and who it's for, you have a problem. The process content has become the product.

The Practical Framework We Actually Use

We don't have a content calendar. We don't have a posting schedule. When we solve something interesting, or when we make a mistake that cost us time and seems like it would cost other people time too, we write it down. That's it.

The filter we apply is: does this contain at least one thing a developer would find non-obvious? Not "surprising" in a clickbait way, but actually useful and not immediately obvious. If the answer is yes, it's probably worth sharing. If we're just recapping what we did this week without any genuine insight, we don't post it.

// A real example of the kind of thing worth documenting:
// We spent 45 minutes debugging why our Stripe webhook handler
// kept returning 400s in production but worked fine locally.
// The issue: we were using req.json() instead of raw body parsing,
// which broke Stripe's signature verification.

// ❌ This breaks webhook signature verification
export async function POST(req: Request) {
  const body = await req.json() // Stripe needs the RAW body bytes
  const signature = req.headers.get('stripe-signature')!
  
  // This will throw: No signatures found matching the expected signature
  const event = stripe.webhooks.constructEvent(
    JSON.stringify(body), // ← re-serializing changes whitespace, breaks HMAC
    signature,
    process.env.STRIPE_WEBHOOK_SECRET!
  )
}

// ✅ Correct approach in Next.js App Router
export async function POST(req: Request) {
  const rawBody = await req.text() // Keep it as text, don't parse
  const signature = req.headers.get('stripe-signature')!
  
  let event: Stripe.Event
  
  try {
    event = stripe.webhooks.constructEvent(
      rawBody,
      signature,
      process.env.STRIPE_WEBHOOK_SECRET!
    )
  } catch (err) {
    console.error('Webhook signature verification failed:', err)
    return new Response('Invalid signature', { status: 400 })
  }
  
  // Now handle the event
  switch (event.type) {
    case 'customer.subscription.updated':
      // ...
      break
  }
  
  return new Response('OK', { status: 200 })
}

That's a post worth writing. Not because it makes us look smart — we look kind of dumb for taking 45 minutes to debug it. But because the next person to hit this problem might find it and save themselves 45 minutes. That's the actual value proposition of building in public.

When Building in Public Helps Your Business (and When It Doesn't)

Building in public works as a business strategy in one specific way: it creates a body of specific, useful content that demonstrates you know what you're talking about, which makes people more likely to trust your product. That's a slow process. It's not a launch strategy. It's not going to get you to product-market fit. It's something you do as a side effect of doing the actual work, and over 12-18 months it builds an audience of people who have learned something from you and therefore trust you.

It doesn't work as a substitute for talking to customers. It doesn't work as a substitute for building something people actually want. The number of people who have an audience from building in public but no real product traction is... large. Posting about your process doesn't validate your idea. Paying customers validate your idea.

For us, the approach has been to focus on content that's actually useful to the developers we want as customers. When we write about something like how we handle authentication patterns in our Next.js templates, or why we made certain schema decisions, we're not doing it primarily for distribution — we're doing it because it's an honest account of the decisions we made and the reasoning behind them. The distribution is a byproduct.

That said, building a catalog of technical content has been genuinely useful for peal.dev. When someone lands on the site and sees that we've written in depth about the actual problems you face building production Next.js apps, it changes the relationship. They're not just buying a template — they're buying from people who clearly have opinions about how this stuff should work. That's a different kind of trust than a landing page with five star testimonials from people nobody has heard of.

The Honest Version of Why We Do It

Partially, we build in public because it's useful for the people who might buy our templates. Writing about real problems we solved is a better demo than any screenshot carousel.

Partially, we do it because writing things down forces clarity. You can be confused about why something works when it's just in your head. Writing a post that other developers will read forces you to actually understand it. We've caught bugs in our own code while writing posts explaining how the code works.

Partially, we do it because it's what we'd want from tools we use. When we're evaluating whether to use some library or template, we want to know that the people who built it actually understand the problems and have thought carefully about the tradeoffs. Posts like this are the evidence.

And honestly, partially we do it because we find it fun. We like the problems. We like talking about them. That's probably the most sustainable reason — if you're only doing it because you think it's a growth strategy, you'll stop when it doesn't immediately produce results. If you do it because you genuinely want to share what you're learning, you'll keep going.

The most honest filter: would you write this post if you knew only 10 people would read it? If yes, it's probably worth writing. If you're only writing it because you imagine a large audience, you're already in performance mode.

One practical note to end on: separate your building-in-public content from your marketing content. It's fine to have both. A post explaining a hard technical problem you solved is building in public. A post saying "our templates are great, here's why you should buy them" is marketing. Both have their place, but mixing them makes both worse. People will stop trusting your technical content if it always seems to have an agenda, and your marketing content will be unconvincing if it's dressed up as something more neutral than it is. Keep them separate. Be clear about which is which. Your readers will respect you more for it.

Newsletter

Liked this post? There's more where it came from.

Dev guides, honest build stories, and the occasional 2am debugging confession — straight to your inbox. No spam, unsubscribe anytime.

Browse templates
Written by humansWeekly dropsSubscriber perks

Join the Discord

Ask questions, share builds, get help from founders