vibecoder
·3 min read

What 'local first' actually means for a side project

Local first doesn't mean offline-only or anti-cloud. It means your app works on your machine before you spend a dollar on infrastructure. Here's why that constraint is productive.

local-firstprocessphilosophy

I keep saying "local first" and people keep hearing "anti-cloud" or "for hobbyists only." That's not what I mean.

Local first, in this context, means: your app works on your machine before you spend a dollar on infrastructure.

That's it. Nothing more ideological than that.

Why the constraint works

When you're building something new — especially a side project or a proof-of-concept — you have no idea yet what the hard part is. You don't know which features actually matter, what the data model should look like, or whether the core interaction is even useful.

Cloud infrastructure introduces costs and complexity at exactly the moment when you can least afford to deal with them:

  • You're paying for servers before you know if the thing works
  • You're debugging deployment issues instead of debugging your app
  • You're configuring IAM roles and VPCs when you should be validating your idea

Local first removes all of that. You run python main.py and it starts. If it breaks, you fix it and run it again. The feedback loop is fast, the cost is zero, and you stay focused on the thing you're actually trying to build.

What "shipped locally" looks like

A local app is done when someone else could sit down at a computer on the same network, open a browser, and use it without you hovering over them.

That means:

  • Runs consistently (not just when you hold it right)
  • Does the one thing it's supposed to do
  • Survives a machine restart (if you want it to)
  • Has real data in it (not just test fixtures)

It does not mean:

  • Has a domain name
  • Has CI/CD
  • Has monitoring
  • Has a beautiful UI (good enough is good enough)

The LAN share trick

One thing that helps: binding to 0.0.0.0 instead of localhost.

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8080)

Now anyone on your WiFi network can hit http://YOUR-IP:8080 from their phone or laptop. You can hand someone a phone and say "try using this" without any deployment at all.

This is how I do user testing on local projects. It's crude and it works.

When to move off local

Move to the cloud when one of these is true:

  1. You've validated that people actually use the thing
  2. You need it running when your machine is off
  3. You're ready to handle real user data with real security implications

Until then, local first keeps you building instead of maintaining.

A note on databases

SQLite gets dismissed as "not production-ready" by people who've never read the SQLite documentation. SQLite handles concurrent reads fine and serializes writes, which is a completely valid tradeoff for a local app with one user or a handful of users on a LAN.

You can always migrate to Postgres later. The SQL you write for SQLite will work with minor changes. Start local, migrate when you have a reason to.


The Starter Kit includes a SQLite setup that's been used to build all three path archetypes. See what's included →