Building an Audio Marketplace with Next.js, Supabase and Stripe
I recently built Loops, a marketplace where music producers can purchase and download piano audio loops. In this article, I share the technical decisions and best practices I implemented to create a modern, type-safe and scalable application.
Tech Stack
| Layer | Technology | Rationale |
|---|---|---|
| Frontend | Next.js 16 (App Router) | SSR, RSC, modern routing |
| API | tRPC v11 + React Query | End-to-end type safety |
| Database | Supabase (PostgreSQL) | Built-in auth, RLS, Storage |
| Payments | Stripe Checkout | Industry standard, webhooks |
| UI | shadcn/ui + Tailwind v4 | Accessible, customizable components |
Project Architecture
| |
Why This Structure?
- Clear separation between client and server code
- Colocation: each feature has its own components, hooks and routes
- Scalability: easy to add new features
End-to-End Type Safety with tRPC
One of the most impactful decisions was using tRPC instead of a traditional REST API.
| |
| |
Key Benefits:
- Zero manual type generation
- Type errors caught at compile time
- Safe refactoring
Authentication with Supabase SSR
Authentication is handled by Supabase Auth with Magic Links. The tricky part was properly managing sessions on the client side with @supabase/ssr.
Security with Row Level Security (RLS)
Supabase allows defining row-level security policies directly in SQL:
| |
Why This Matters:
- Defense in depth security: even if the API has a bug, the database rejects unauthorized access
- Centralized and auditable security logic
- No risk of missing authorization checks in code
Secure Payments with Stripe
I use Stripe Checkout in hosted mode for payments:
- User clicks “Buy”
- API creates a Checkout session with metadata
- Redirect to Stripe (secure UI)
- Webhook receives confirmation → purchase created in DB
| |
Best Practices Implemented:
- Webhook validation with
stripe.webhooks.constructEvent() - Idempotency: check if purchase already exists
- Metadata for tracing user/loop without additional queries
CI/CD with GitHub Actions
The project includes a continuous deployment workflow:
| |
Workflow:
- Every push triggers ESLint checks
- If
mainbranch + lint passes → automatic deployment to Vercel - PRs are verified but not deployed
Key Takeaways
- Type safety: tRPC + TypeScript = zero runtime surprises
- Layered security: RLS + API validation + auth middleware
- Methodical debugging: logs, timeouts, systematic reproduction
- Simplicity: Stripe Checkout over custom Stripe Elements
- CI/CD from day one: automate to prevent human errors
The full source code is available on GitHub .
Questions about the implementation? Reach out on LinkedIn .