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

  1. Next.js 14 (App Router)
  2. Remix
  3. SvelteKit
  4. Nuxt.js (Vue)

Language

  1. TypeScript (strict mode)
  2. JavaScript
  3. Reason/ReScript

Database

  1. PostgreSQL (via Supabase)
  2. MySQL
  3. MongoDB

ORM

  1. Drizzle ORM
  2. Prisma
  3. TypeORM
  4. Raw SQL

Styling

  1. Tailwind CSS
  2. CSS Modules
  3. Styled Components
  4. Emotion

Component Library

  1. shadcn/ui
  2. Radix UI (raw)
  3. Headless UI
  4. Chakra UI
  5. Material UI

Authentication

  1. NextAuth.js (planned)
  2. Clerk
  3. Auth0
  4. Supabase Auth

File Storage

  1. AWS S3
  2. Supabase Storage
  3. Cloudinary
  4. Vercel Blob

Hosting

  1. Vercel
  2. AWS Amplify
  3. Netlify
  4. 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

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