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 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:
- Define use cases (what do SaaS apps actually need?)
- Identify resources (users, teams, subscriptions, etc)
- Map operations to endpoints
- Define request/response shapes
- 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
Read more

Tailwind CSS v4: What Changed and Why It's Better
No more tailwind.config.ts. Tailwind v4 moves configuration to CSS, drops JavaScript, and ships 2x faster. Here's everything that changed.

Why We Use cn() and cva() for Component Styling
String concatenation for Tailwind classes is a mess. Here's how cn() and cva() make conditional styling clean, type-safe, and maintainable.

Stop Trusting process.env: Type-Safe Env Variables in Next.js
process.env fails silently and leaks secrets. Here's how t3-env catches missing env vars at build time, not production.