ADR 001: Technology Stack Selection
Status: Accepted Date: 2026-01-23 Deciders: Engineering Team Context: Initial technology stack selection for CAIRL platform
Context and Problem Statement
CAIRL requires a modern, secure, and scalable technology stack for building a privacy-first identity verification platform. The stack must support:
- Fast development iteration
- Strong type safety
- Security best practices
- Scalability for growth
- Developer experience
- Cost-effectiveness
Decision Drivers
- Security: Identity verification demands highest security standards
- Privacy: Must support encryption, data minimization, consent management
- Type Safety: Reduce runtime errors, improve developer confidence
- Developer Experience: Fast development with excellent tooling
- Performance: Fast page loads, responsive UI
- Scalability: Handle growth from MVP to millions of users
- Cost: Optimize for early-stage budget
- Ecosystem: Strong community, good libraries available
Considered Options
Frontend Framework
- Next.js 14 (App Router)
- Remix
- SvelteKit
- Nuxt.js (Vue)
Language
- TypeScript (strict mode)
- JavaScript
- Reason/ReScript
Database
- PostgreSQL (via Supabase)
- MySQL
- MongoDB
ORM
- Drizzle ORM
- Prisma
- TypeORM
- Raw SQL
Styling
- Tailwind CSS
- CSS Modules
- Styled Components
- Emotion
Component Library
- shadcn/ui
- Radix UI (raw)
- Headless UI
- Chakra UI
- Material UI
Authentication
- NextAuth.js (planned)
- Clerk
- Auth0
- Supabase Auth
File Storage
- AWS S3
- Supabase Storage
- Cloudinary
- Vercel Blob
Hosting
- Vercel
- AWS Amplify
- Netlify
- Self-hosted (AWS ECS)
Decision Outcome
Chosen Stack:
Frontend: Next.js 14 (App Router) + TypeScript
Why:
- ✅ Best-in-class DX: File-based routing, server components, streaming
- ✅ SEO-friendly: Excellent for marketing pages and documentation
- ✅ Performance: Automatic code splitting, image optimization
- ✅ Flexibility: Can use server-side, client-side, or hybrid rendering
- ✅ Ecosystem: Massive community, extensive libraries
- ✅ Vercel integration: Seamless deployment and preview environments
- ✅ API Routes: Built-in API layer for backend logic
Trade-offs:
- ❌ App Router still maturing (some edge cases)
- ❌ Framework lock-in (but migration path exists)
Language: TypeScript (Strict Mode)
Why:
- ✅ Type Safety: Catch errors at compile time, not runtime
- ✅ Better IDE Support: Autocomplete, refactoring, documentation
- ✅ Self-documenting: Types serve as inline documentation
- ✅ Refactoring Confidence: Safe large-scale changes
- ✅ Team Alignment: Enforces contracts between code sections
Trade-offs:
- ❌ Slight learning curve for pure JS developers
- ❌ More upfront type definitions
Database: PostgreSQL (Supabase)
Why:
- ✅ Proven: Battle-tested for 30+ years
- ✅ ACID Compliance: Critical for identity data integrity
- ✅ JSON Support: Flexible metadata storage with jsonb
- ✅ Full-text Search: Built-in search capabilities
- ✅ Encryption: Native encryption support
- ✅ Supabase: Managed hosting, backups, realtime subscriptions
- ✅ Cost: Free tier generous, scales affordably
Trade-offs:
- ❌ Not as horizontally scalable as NoSQL (not a concern at current scale)
ORM: Drizzle ORM
Why:
- ✅ TypeScript-first: Best TypeScript support of any ORM
- ✅ SQL-like: Familiar syntax, transparent SQL generation
- ✅ Performance: No runtime overhead, generates efficient queries
- ✅ Type Safety: Full end-to-end type safety
- ✅ Migration Support: Built-in migration tooling
- ✅ Small Bundle: Minimal impact on bundle size
- ✅ Zero Dependencies: No peer dependencies
Why not Prisma:
- Drizzle has better TypeScript inference
- Smaller bundle size
- More SQL-like syntax (easier to optimize)
- No separate schema language
Trade-offs:
- ❌ Smaller community than Prisma
- ❌ Fewer GUI tools
Styling: Tailwind CSS
Why:
- ✅ Utility-first: Rapid development, no naming fatigue
- ✅ Design System: Easy to enforce consistent spacing, colors
- ✅ Performance: PurgeCSS removes unused styles
- ✅ Responsive: Mobile-first design out of the box
- ✅ Customizable: Easy to extend with CAIRL brand colors
- ✅ Developer Experience: IntelliSense support excellent
Trade-offs:
- ❌ HTML can look "noisy" with many classes
- ❌ Learning curve for non-utility-CSS developers
Components: shadcn/ui
Why:
- ✅ Copy-paste: Components live in your codebase, full control
- ✅ Accessible: Built on Radix UI primitives (WCAG compliant)
- ✅ Customizable: Easy to modify since code is yours
- ✅ Tailwind-native: Perfect integration with Tailwind
- ✅ No Lock-in: Not a dependency, just starter code
- ✅ Beautiful: Professional design out of the box
Why not pre-built libraries:
- Full control over components
- No bundle bloat from unused components
- Easy customization for CAIRL brand
Trade-offs:
- ❌ More manual updates (but gives control)
- ❌ Need to maintain component code
Authentication: NextAuth.js (Future)
Why:
- ✅ Next.js Integration: Built specifically for Next.js
- ✅ Flexible: Supports credentials, OAuth, magic links
- ✅ Session Management: Secure JWT or database sessions
- ✅ Provider Support: Easy OAuth integration (Google, GitHub, etc.)
- ✅ TypeScript Support: Fully typed
- ✅ Free: Open source, self-hosted
Trade-offs:
- ❌ More setup than managed services (Clerk, Auth0)
- ❌ Need to implement MFA ourselves
Storage: AWS S3
Why:
- ✅ Industry Standard: Proven reliability, 99.999999999% durability
- ✅ Security: Server-side encryption, access policies
- ✅ Cost: Pay-per-use, affordable at scale
- ✅ Integration: Easy integration with Lambda for processing
- ✅ Compliance: SOC 2, GDPR compliant
- ✅ Lifecycle Policies: Automatic deletion for privacy compliance
Trade-offs:
- ❌ AWS complexity (but S3 is straightforward)
- ❌ Need AWS account management
Hosting: Vercel
Why:
- ✅ Next.js Creators: Best Next.js hosting experience
- ✅ Preview Deployments: Every PR gets a preview URL
- ✅ Edge Network: Global CDN for fast page loads
- ✅ Zero Config: Deploy with git push
- ✅ Analytics: Built-in performance monitoring
- ✅ Free Tier: Generous for MVP phase
Trade-offs:
- ❌ Pricing can scale up quickly
- ❌ Vendor lock-in for some features
Implementation Plan
Phase 1: Foundation (Current)
- ✅ Next.js 14 project setup
- ✅ TypeScript strict mode
- ✅ Tailwind CSS configuration
- ✅ shadcn/ui components
- ✅ Drizzle ORM with PostgreSQL
- ⏳ Vercel deployment
Phase 2: Core Features (Next 2 weeks)
- NextAuth.js authentication
- Email verification
- Phone verification
- User dashboard
- Consent management
Phase 3: Identity Verification (Weeks 3-6)
- Document upload to S3
- ID verification flow
- Selfie verification
- Admin review interface
Phase 4: Production Ready (Weeks 7-8)
- Security audit
- Performance optimization
- Compliance documentation
- User acceptance testing
Consequences
Positive
- Fast Development: Modern stack enables rapid iteration
- Type Safety: TypeScript + Drizzle catch errors early
- Security: Enterprise-grade security from day one
- Scalability: All components scale independently
- Developer Experience: Excellent tooling and DX
- Cost-Effective: Free tiers cover MVP, scales affordably
Negative
- Learning Curve: Team needs to learn App Router, Drizzle
- Framework Risk: App Router is relatively new
- Vendor Dependencies: Rely on Vercel, Supabase, AWS
Neutral
- Standardization: Decisions made, reduces bikeshedding
- Documentation: Need to document conventions
- Onboarding: New developers need to learn stack
Alternatives Considered
Alternative Stack: Remix + Prisma + Planetscale
Pros:
- Remix has excellent nested routing
- Prisma is more mature than Drizzle
- Planetscale offers serverless MySQL
Cons:
- Smaller ecosystem than Next.js
- Prisma less performant than Drizzle
- MySQL less feature-rich than PostgreSQL
Why Not: Next.js has stronger ecosystem and Vercel integration
Alternative Stack: SvelteKit + Supabase Auth
Pros:
- SvelteKit has excellent DX
- Supabase Auth handles authentication
- Smaller bundle sizes
Cons:
- Smaller ecosystem
- Less TypeScript support
- Fewer developers familiar with Svelte
Why Not: Next.js ecosystem and hiring pool larger
References
- Next.js Documentation
- Drizzle ORM Documentation
- Tailwind CSS Documentation
- shadcn/ui Documentation
- Supabase Documentation
Notes
- Revisit this decision in 6 months
- Track bundle size and performance metrics
- Monitor community adoption of App Router
- Consider Cloudflare Workers for edge compute if needed
Last Reviewed: 2026-01-23