Back to all articles
Building in PublicTechnical

Why I Spent a Week Studying API Design Before Writing Code for vibestacks

Building a SaaS boilerplate means other developers will build on top of your API. I had to get this right. Heres what I learned.

Why I Spent a Week Studying API Design Before Writing Code for vibestacks

Why API design matters for a boilerplate

vibestacks isnt just an app. Its a starting point for other peoples apps. If my API structure sucks, every project built on it inherits that mess.

So before I wrote any endpoints I went back to basics. Spent a week studying API design properly. Heres what I learned and how its shaping vibestacks.

The three main approaches

REST - Resource based, stateless, standard HTTP methods. Most common. Everyone knows it. vibestacks uses this for external APIs.

GraphQL - Query based, single endpoint, client asks for exactly what it needs. Great for complex frontends. Overkill for most SaaS.

gRPC - Protocol buffers, service definitions, fast. Good for microservices talking to each other. Not great for browser clients.

For vibestacks I went with REST for the public API and tRPC internally. Why? Developers expect REST. Its predictable. And tRPC gives me type safety between frontend and backend without the GraphQL complexity.

Design principles I'm following

Consistency Same naming patterns everywhere. If its /users/:id its not /getUser somewhere else. Sounds obvious but I've seen codebases where every endpoint follows different conventions.

Simplicity Focus on core use cases first. I'm not building endpoints for edge cases nobody will use. Start minimal, extend later.

Security from day one

  • Authentication on every protected route
  • Authorization checks (can this user access this resource?)
  • Input validation with Zod
  • Rate limiting with Upstash

Not adding these later. Baking them in now.

Performance considerations

  • Pagination on list endpoints
  • Caching strategies where it makes sense
  • Minimize payload size
  • Reduce round trips

Understanding protocols

This part was new to me honestly. The protocol you choose affects everything.

HTTP/HTTPS - Standard web traffic. REST lives here.

WebSockets - Real time bidirectional. Using this for live features like notifications.

The TLS stuff - HTTPS is just HTTP + TLS encryption. TLS 1.3 is current standard. Anything below 1.2 is considered insecure now. Vercel handles this but good to understand why.

How I'm approaching vibestacks's API

Top down approach:

  1. Define use cases (what do SaaS apps actually need?)
  2. Identify resources (users, teams, subscriptions, etc)
  3. Map operations to endpoints
  4. Define request/response shapes
  5. Implement with validation

Core resources I'm building:

  • Users and authentication
  • Teams/organizations
  • Subscriptions and billing
  • API keys for end users
  • Webhooks

Each one follows the same patterns. If you understand one, you understand all of them.

The configurability problem

Heres what makes vibestacks different from me just building an API for one app.

Different projects need different things:

  • Some apps need REST APIs for external integrations
  • Some want tRPC for that end-to-end type safety
  • Some need GraphQL because their frontend is complex
  • Some need WebSockets, some dont
  • Some need public APIs with rate limiting, some are internal only

Most boilerplates pick one approach and hardcode it. Then you spend days ripping it out when it doesnt fit your use case.

I wanted vibestacks to be configurable. Want REST? Enable it. Need tRPC? Its there. Want both? Also fine. Need to add GraphQL later? The structure supports it.

The challenge:

How do you design an architecture that supports multiple API paradigms without becoming a mess?

If I just throw everything in, the codebase becomes confusing. If I make it too modular, simple projects have too much overhead.

How I'm solving it:

I cant share all the details (gotta keep some things for paying customers lol) but the general approach:

  • Core business logic is separate from the API layer
  • Each API type (REST, tRPC, etc) is a thin adapter on top of shared services
  • Feature flags control whats enabled
  • You delete what you dont need, the rest still works

So if you want REST only, you remove the tRPC folder and nothing breaks. If you want both, they share the same underlying logic. No duplication.

Same pattern for other choices:

  • Want Stripe? Or Lemonsqueezy? Swap the payment adapter
  • Want magic links? Or passwords? Or both? Auth config handles it
  • Need SSO for enterprise? Enable the module
  • Want WebSockets for real-time? Or skip it for a simpler app? Your choice

The API design principles I talked about earlier (consistency, simplicity) make this possible. When every part follows the same patterns, swapping pieces becomes predictable.

Still figuring out the right balance honestly. Too many options is overwhelming. Too few defeats the purpose. Will share more as I nail it down.

What this means for vibestacks users

When you start a project with vibestacks:

  • API structure is already decided (and documented)
  • Auth and validation already wired up
  • Rate limiting configured
  • Type safety end to end with tRPC
  • REST endpoints ready for external integrations

You extend it, you dont redesign it.

Still learning

I'm not an API design expert. Just someone who realized I needed to understand this properly before building something others will use.

Will share more as I implement. If you have opinions on API patterns for SaaS hit me up.


Following along: https://www.vibestacks.io//blog