• ShipSaaSDocumentation
  • Introduction
  • Getting Started
    • Installation
    • Environment Setup
    • Database Setup
    • Development Guide
  • Database
    • Repository Pattern
    • Drizzle Queries
    • Migration Workflow
    • Drizzle Studio
    • Best Practices
  • File Management
    • File Upload Component
    • Server Actions
    • Storage Configuration
  • Authentication Methods
    • Credentials Authentication
    • Magic Link Authentication
    • Two-Factor Authentication (2FA)
    • Social Authentication
    • API Keys & Bearer Tokens
    • Organizations (Multi-tenant)
  • Authorization & Permissions
    • Roles & Hierarchy
    • Route Protection
    • API Protection
    • CASL Permissions
  • Email & Notifications
    • Resend Setup
    • React Email Templates
    • Notification System
    • Email Workflows
    • Customization & Extension
  • Stripe & Payments
    • Stripe Setup
    • Better Auth Integration
    • Checkout Methods
    • Subscription Management
    • Admin Dashboard
    • Webhook Events
  • Architecture & Development
    • Presentation Layer
    • Service Layer
    • Persistence Layer
    • Helpers Architecture
    • Project Structure
    • Development Workflow
  • Testing
    • General Testing
    • Unit Testing
    • UI Component Testing
    • Repository Testing
    • Service Testing
    • End-to-End Testing
  • Deployment
    • Vercel Deployment
    • GitHub Actions CI/CD
    • Database Backup & Restore
    • Database Migrations
    • Troubleshooting Deployment
  • AI Agents Integration
  • Blog Management
    • Blog Setup
    • MDX Blog
    • Database Blog
  • Async Tasks
    • Setup
    • Email Workflows
    • Payment Processing
    • Maintenance Jobs
  1. Documentation
  2. Architecture & Development
  3. Project Structure
Buydocschangelogsdemocommunity

Project Structure

PreviousHelpers ArchitectureNextDevelopment Workflow
On this page
Project OverviewNaming ConventionsImport OrganizationCode Organization PatternsBest Practices

The boilerplate follows a carefully designed project structure that promotes maintainability, scalability, and developer productivity. The structure enforces clear boundaries between different concerns and provides consistent patterns across the entire codebase.

Perfect for: Understanding the codebase organization, following established patterns, and maintaining consistency as your application grows.

Project Overview

ShipSaaS is a monolithic Next.js SaaS boilerplate with a well-organized layered architecture. It emphasizes clear separation of concerns with dedicated layers for routing, components, services, and database access.

Project Root Organization:

shipsaas-ai-boilerplate/
โ”œโ”€โ”€ src/                            # ๐Ÿ“ Application source code
โ”œโ”€โ”€ public/                         # ๐Ÿ“ Static assets (images, fonts)
โ”œโ”€โ”€ docs/                           # ๐Ÿ“š Documentation
โ”œโ”€โ”€ messages/                       # ๐ŸŒ i18n translation files
โ”œโ”€โ”€ scripts/                        # ๐Ÿ”ง Build/database scripts
โ”œโ”€โ”€ drizzle/                        # ๐Ÿ—„๏ธ Database migrations
โ”œโ”€โ”€ e2e/                           # ๐Ÿงช End-to-end tests
โ”œโ”€โ”€ .github/                       # ๐Ÿ“‹ GitHub workflows
โ”œโ”€โ”€ .claude/                       # ๐Ÿค– Claude Code configuration
โ”œโ”€โ”€ .cursor/                       # ๐Ÿ“‹ Cursor IDE rules
โ”œโ”€โ”€ package.json                   # Dependencies configuration
โ”œโ”€โ”€ next.config.ts                 # Next.js configuration
โ”œโ”€โ”€ tsconfig.json                  # TypeScript configuration
โ”œโ”€โ”€ drizzle.config.ts              # Drizzle ORM configuration
โ””โ”€โ”€ playwright.config.ts           # E2E testing configuration

Key Principles:

  • Single application - All code in one cohesive Next.js project
  • Layered architecture - Clear separation: routes โ†’ components โ†’ services โ†’ database
  • Feature-based organization - Components grouped by feature
  • Service layer pattern - Business logic isolated in services
  • Type safety - Full TypeScript coverage with Drizzle ORM

Next.js App Router Structure (src/app/):

src/app/
โ”œโ”€โ”€ [locale]/                      # ๐ŸŒ Internationalization (i18n) wrapper
โ”‚   โ”œโ”€โ”€ (public)/                  # Public routes
โ”‚   โ”‚   โ”œโ”€โ”€ page.tsx               # Home page
โ”‚   ๏ฟฝ๏ฟฝ๏ฟฝ   โ”œโ”€โ”€ blog/                  # Blog pages
โ”‚   โ”‚   โ”œโ”€โ”€ docs/                  # Documentation pages
โ”‚   โ”‚   โ”œโ”€โ”€ checkout/              # Stripe checkout
โ”‚   โ”‚   โ”œโ”€โ”€ privacy/               # Privacy policy
โ”‚   โ”‚   โ”œโ”€โ”€ terms/                 # Terms of service
โ”‚   โ”‚   โ””โ”€โ”€ [slug]/               # Dynamic public routes
โ”‚   โ”œโ”€โ”€ (app)/                     # Protected user routes (auth required)
โ”‚   โ”‚   โ”œโ”€โ”€ dashboard/             # User dashboard
โ”‚   โ”‚   โ”œโ”€โ”€ account/               # Account settings
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ organizations/     # Organization management
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ settings/          # User settings
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ subscription/      # Subscription management
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ api-keys/          # API key management
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ invitations/       # Team invitations
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ notifications/     # Notification settings
โ”‚   โ”‚   โ”œโ”€โ”€ team/                  # Team/organization view
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ [slug]/            # Team details
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ projects/      # Team projects
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ react-query/   # React Query example
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ [id]/          # Project detail
โ”‚   โ”‚   โ””โ”€โ”€ chat/                  # Chat interface (AI features)
โ”‚   โ”œโ”€โ”€ admin/                     # Admin-only routes
โ”‚   โ”‚   โ”œโ”€โ”€ organizations/         # Organization management
โ”‚   โ”‚   โ”œโ”€โ”€ users/                 # User management
โ”‚   โ”‚   โ”œโ”€โ”€ plans/                 # Pricing plans management
โ”‚   โ”‚   โ”œโ”€โ”€ subscriptions/         # Subscription management
โ”‚   โ”‚   โ”œโ”€โ”€ tasks/                 # Task management
โ”‚   โ”‚   โ””โ”€โ”€ blog/                  # Blog management
โ”‚   โ””โ”€โ”€ [...rest]/                 # Catch-all for 404
โ”œโ”€โ”€ api/                           # ๐Ÿ”Œ API routes
โ”‚   โ”œโ”€โ”€ auth/                      # Authentication endpoints
โ”‚   โ”œโ”€โ”€ webhooks/                  # Stripe/external webhooks
โ”‚   โ””โ”€โ”€ [feature]/                 # Feature-specific endpoints
โ”œโ”€โ”€ layout.tsx                     # Root layout
โ”œโ”€โ”€ globals.css                    # Global styles
โ””โ”€โ”€ middleware.ts                  # Middleware (auth, i18n)

Route Organization:

  • (public) - Landing pages, blog, documentation, checkout, public legal pages
  • (app) - Authenticated user dashboard and account management
  • admin/ - Administrative panels for managing the platform
  • api/ - API endpoints for backend operations
  • [locale] - Multi-language support wrapper

Complete src/ Directory Organization:

src/
โ”œโ”€โ”€ app/                           # ๐ŸŽฏ Next.js App Router (routes & API)
โ”œโ”€โ”€ components/                    # ๐ŸŽจ React Components
โ”‚   โ”œโ”€โ”€ ui/                        # Base UI components (Button, Card, etc.)
โ”‚   โ”œโ”€โ”€ features/                  # Feature-specific components
โ”‚   โ”‚   โ”œโ”€โ”€ admin/                # Admin feature components
โ”‚   โ”‚   โ”œโ”€โ”€ api-key/              # API key management UI
โ”‚   โ”‚   โ”œโ”€โ”€ auth/                 # Authentication components
โ”‚   โ”‚   โ”œโ”€โ”€ blog/                 # Blog-related components
โ”‚   โ”‚   โ”œโ”€โ”€ chat/                 # AI chat interface
โ”‚   โ”‚   โ”œโ”€โ”€ checkout-stripe/      # Stripe checkout flow
โ”‚   โ”‚   โ”œโ”€โ”€ dashboard/            # Dashboard components
โ”‚   โ”‚   โ”œโ”€โ”€ layouts/              # Layout wrappers
โ”‚   โ”‚   โ”œโ”€โ”€ notifications/        # Notification components
โ”‚   โ”‚   โ”œโ”€โ”€ organization/         # Organization management UI
โ”‚   โ”‚   โ”œโ”€โ”€ payment/              # Payment-related UI
โ”‚   โ”‚   โ”œโ”€โ”€ projects/             # Project management UI
โ”‚   โ”‚   โ”œโ”€โ”€ subscription/         # Subscription UI
โ”‚   โ”‚   โ”œโ”€โ”€ team/                 # Team management UI
โ”‚   โ”‚   โ””โ”€โ”€ user/                 # User profile components
โ”‚   โ”œโ”€โ”€ context/                   # React Context providers
โ”‚   โ”œโ”€โ”€ hooks/                     # Custom React hooks
โ”‚   โ””โ”€โ”€ mdx-components.tsx         # MDX rendering components
โ”œโ”€โ”€ services/                      # โš™๏ธ Business Logic Layer
โ”‚   โ”œโ”€โ”€ authentication/            # Auth service & logic
โ”‚   โ”œโ”€โ”€ authorization/             # Access control & permissions
โ”‚   โ”œโ”€โ”€ facades/                   # Service interfaces/facades
โ”‚   โ”‚   โ”œโ”€โ”€ interceptors/         # Service interceptors (logging, error handling)
โ”‚   โ”‚   โ””โ”€โ”€ [domain]-service-facade.ts
โ”‚   โ”œโ”€โ”€ validation/                # Input validation schemas (Zod)
โ”‚   โ”œโ”€โ”€ errors/                    # Custom error classes
โ”‚   โ”œโ”€โ”€ types/                     # Service types & domain models
โ”‚   โ”œโ”€โ”€ [domain]-service.ts        # Core service implementations
โ”‚   โ””โ”€โ”€ __tests__/                 # Service unit tests
โ”œโ”€โ”€ db/                            # ๐Ÿ—„๏ธ Database Layer
โ”‚   โ”œโ”€โ”€ models/                    # Drizzle schema definitions
โ”‚   โ”œโ”€โ”€ repositories/              # Data access objects (DAOs)
โ”‚   โ””โ”€โ”€ scripts/                   # Database utility scripts
โ”œโ”€โ”€ lib/                           # ๐Ÿ”ง Utilities & Helpers
โ”‚   โ”œโ”€โ”€ api/                       # API client utilities
โ”‚   โ”œโ”€โ”€ better-auth/               # Better Auth configuration
โ”‚   โ”œโ”€โ”€ helper/                    # Helper functions
โ”‚   โ”‚   โ”œโ”€โ”€ blog.server.ts        # Blog-related helpers
โ”‚   โ”‚   โ”œโ”€โ”€ blog.client.ts        # Client-side blog helpers
โ”‚   โ”‚   โ”œโ”€โ”€ docs.server.ts        # Documentation helpers
โ”‚   โ”‚   โ”œโ”€โ”€ date-helper.ts        # Date formatting/parsing
โ”‚   โ”‚   โ”œโ”€โ”€ menu-helper.ts        # Menu structure helpers
โ”‚   โ”‚   โ””โ”€โ”€ [feature]-helper.ts   # Feature-specific helpers
โ”‚   โ”œโ”€โ”€ stripe/                    # Stripe integration
โ”‚   โ”œโ”€โ”€ emails/                    # Email templates & sending
โ”‚   โ”œโ”€โ”€ files/                     # File handling utilities
โ”‚   โ”œโ”€โ”€ inngest/                   # Inngest job queue setup
โ”‚   โ”œโ”€โ”€ auth.ts                    # Auth configuration
โ”‚   โ”œโ”€โ”€ logger.ts                  # Logging utility
โ”‚   โ”œโ”€โ”€ constants.ts               # Application constants
โ”‚   โ”œโ”€โ”€ crypto.ts                  # Cryptography utilities
โ”‚   โ””โ”€โ”€ utils.ts                   # General utilities
โ”œโ”€โ”€ i18n/                          # ๐ŸŒ Internationalization
โ”‚   โ”œโ”€โ”€ request.ts                 # i18n request handling
โ”‚   โ”œโ”€โ”€ config.ts                  # i18n configuration
โ”‚   โ””โ”€โ”€ routing.ts                 # i18n routing setup
โ”œโ”€โ”€ styles/                        # ๐ŸŽจ Global styles
โ”œโ”€โ”€ __tests__/                     # ๐Ÿงช Global tests
โ”œโ”€โ”€ middleware.ts                  # Request middleware
โ”œโ”€โ”€ env.ts                         # Environment variables (runtime)
โ”œโ”€โ”€ env-schemas.ts                 # Environment schemas (validation)
โ””โ”€โ”€ types/                         # ๐Ÿ“ Global TypeScript types

Service Layer Organization:

src/services/
โ”œโ”€โ”€ authentication/                # Authentication service
โ”‚   โ”œโ”€๏ฟฝ๏ฟฝ strategies/               # Auth strategies (OAuth, etc.)
โ”‚   โ””โ”€โ”€ session-management.ts     # Session handling
โ”œโ”€โ”€ authorization/                 # Authorization & permissions
โ”‚   โ”œโ”€โ”€ rbac/                     # Role-based access control
โ”‚   โ”œโ”€โ”€ permissions/              # Permission checks
โ”‚   โ””โ”€โ”€ policies/                 # Authorization policies
โ”œโ”€โ”€ facades/                       # Service Facade Pattern
โ”‚   โ”œโ”€โ”€ interceptors/             # Logging, error handling
โ”‚   โ”œโ”€โ”€ user-service-facade.ts    # User service interface
โ”‚   โ”œโ”€โ”€ organization-service-facade.ts
โ”‚   โ”œโ”€โ”€ subscription-service-facade.ts
โ”‚   โ”œโ”€โ”€ email-service-facade.ts
โ”‚   โ”œโ”€โ”€ notification-service-facade.ts
โ”‚   โ”œโ”€โ”€ file-service-facade.ts
โ”‚   โ”œโ”€โ”€ post-service-facade.ts
โ”‚   โ””โ”€โ”€ [domain]-service-facade.ts
โ”œโ”€โ”€ validation/                    # Input validation (Zod)
โ”‚   โ”œโ”€โ”€ user-validation.ts
โ”‚   โ”œโ”€โ”€ subscription-validation.ts
โ”‚   โ””โ”€โ”€ [domain]-validation.ts
โ”œโ”€โ”€ errors/                        # Custom error classes
โ”‚   โ”œโ”€โ”€ AppError.ts               # Base error class
โ”‚   โ”œโ”€โ”€ ValidationError.ts        # Validation errors
โ”‚   โ””โ”€โ”€ AuthorizationError.ts     # Permission errors
โ”œโ”€โ”€ types/                         # Domain types & interfaces
โ”‚   โ”œโ”€โ”€ domain/                   # Domain-specific types
โ”‚   โ””โ”€โ”€ common.ts                 # Common types
โ”œโ”€โ”€ user-service.ts                # User management service
โ”œโ”€โ”€ organization-service.ts        # Organization service
โ”œโ”€โ”€ subscription-service.ts        # Subscription & billing
โ”œโ”€โ”€ email-service.ts               # Email sending service
โ”œโ”€โ”€ notification-service.ts        # Notification service
โ”œโ”€โ”€ file-service.ts                # File upload/management
โ”œโ”€โ”€ chat-service.ts                # AI chat service
โ”œโ”€โ”€ post-service.ts                # Post/content service
โ”œโ”€โ”€ project-service.ts             # Project management
โ”œโ”€โ”€ admin-dashboard-service.ts     # Admin dashboard
โ””โ”€โ”€ __tests__/                     # Service tests

Service Pattern:

  1. Input Validation - Using Zod schemas in validation/
  2. Authorization - Checking permissions in authorization/
  3. Business Logic - Core logic in [domain]-service.ts
  4. Data Access - Using repositories from db/repositories
  5. Response - Returning typed results
  6. Error Handling - Using custom error classes
  7. Facade - Public interface in facades/[domain]-service-facade.ts

Database Layer Organization:

src/db/
โ”œโ”€โ”€ models/                        # Drizzle schema definitions
โ”‚   โ”œโ”€โ”€ user.ts                   # User schema
โ”‚   โ”œโ”€โ”€ organization.ts           # Organization schema
โ”‚   โ”œโ”€โ”€ subscription.ts           # Subscription schema
โ”‚   โ”œโ”€โ”€ post.ts                   # Post/content schema
โ”‚   โ””โ”€โ”€ [entity].ts               # Entity schemas
โ”œโ”€โ”€ repositories/                  # Data Access Objects (DAOs)
โ”‚   โ”œโ”€โ”€ user-repository.ts        # User data access
โ”‚   โ”œโ”€โ”€ organization-repository.ts
โ”‚   โ”œโ”€โ”€ subscription-repository.ts
โ”‚   โ”œโ”€โ”€ post-repository.ts
โ”‚   โ””โ”€โ”€ [entity]-repository.ts
โ””โ”€โ”€ scripts/                       # Database scripts
    โ”œโ”€โ”€ seed.ts                   # Database seeding
    โ””โ”€โ”€ migrate.ts                # Migration utilities

Database Operations:

  • Models define table schemas using Drizzle ORM
  • Repositories provide type-safe data access methods
  • Services use repositories for business logic
  • Scripts handle migrations and seeding

Naming Conventions

Consistent naming patterns across the codebase improve readability and maintainability:

File Naming Patterns (ShipSaaS Standard):

โœ… GOOD FILE NAMES:

# Components (PascalCase - React convention)
UserProfile.tsx
SubscriptionCard.tsx
PaymentForm.tsx
UserAvatar.tsx
NotificationBell.tsx

# Pages & Layouts (Next.js conventions)
page.tsx
layout.tsx
loading.tsx
error.tsx
not-found.tsx

# Services (kebab-case with suffix)
user-service.ts
subscription-service.ts
email-service.ts
organization-service.ts

# Service Facades (kebab-case with suffix)
user-service-facade.ts
subscription-service-facade.ts
email-service-facade.ts

# Database Models (kebab-case)
user.ts                           # Schema definition
organization.ts
subscription.ts

# Repositories (kebab-case with suffix)
user-repository.ts
organization-repository.ts
subscription-repository.ts

# Utilities & Helpers (kebab-case)
user-helper.ts
date-helper.ts
api-client.ts
common-helper.ts

# Validation Schemas (kebab-case with suffix)
user-validation.ts
subscription-validation.ts

# Context & Hooks (camelCase for hooks, PascalCase for Context)
useUserData.ts
useSubscription.ts
UserContext.tsx
ThemeContext.tsx

Directory Naming:

โœ… GOOD DIRECTORY NAMES:

# Feature directories (kebab-case)
/user/
/organization/
/subscription/
/payment/
/api-key/

# Component feature directories (kebab-case)
/checkout-stripe/
/user-profile/
/admin-dashboard/
/project-management/

# Service subdirectories (kebab-case)
/authentication/
/authorization/
/validation/
/errors/

# Next.js special directories (exact names)
/(public)/
/(auth)/
/(app)/
/admin/
/api/

File Organization Rules:

  • PascalCase: React components (.tsx files)
  • kebab-case: Services, utilities, hooks, repositories, models
  • camelCase: React hooks (useMyHook.ts)
  • lowercase: Next.js special files (page.tsx, layout.tsx, etc.)
  • SCREAMING_SNAKE_CASE: Constants only

Variable and Function Naming:

typescript
// โœ… GOOD: camelCase for variables and functions
const userName = 'john'
const userSubscription = await getSubscription()
const isUserActive = true
const userEmail = user?.email

function getUserById(id: string): User | null {
  return users.find(user => user.id === id) || null
}

// โœ… GOOD: PascalCase for types and interfaces
interface UserSubscription {
  id: string
  userId: string
  status: SubscriptionStatus
}

type PaymentMethod = 'card' | 'bank' | 'crypto'

// โœ… GOOD: SCREAMING_SNAKE_CASE for constants
const MAX_RETRY_ATTEMPTS = 3
const DEFAULT_PAGE_SIZE = 20
const API_BASE_URL = 'https://api.example.com'
const DATABASE_POOL_SIZE = 10

// โœ… GOOD: Descriptive boolean names (with is/has/can prefix)
const isAuthenticated = checkAuth()
const hasPermission = checkPermission()
const canEditProfile = hasPermission && isOwner
const isLoading = await fetchData()

// โŒ BAD: Unclear or abbreviated names
const u = getUser() // What is 'u'?
const chkPerm = () => {} // Unclear abbreviation
const flag = true // What does this flag represent?

Service and Repository Function Naming:

typescript
// โœ… GOOD: Service function naming pattern (kebab-case files)
// user-service.ts
export const getUserByIdService = async (id: string): Promise<User> => { }
export const createUserService = async (data: CreateUserInput): Promise<User> => { }
export const updateUserService = async (id: string, data: UserUpdate): Promise<User> => { }
export const deleteUserService = async (id: string): Promise<void> => { }

// โœ… GOOD: Repository function naming pattern (kebab-case files)
// user-repository.ts
export const getUserByIdRepository = async (id: string): Promise<UserModel | null> => { }
export const createUserRepository = async (data: NewUserModel): Promise<UserModel> => { }
export const updateUserRepository = async (id: string, data: UserUpdate): Promise<UserModel> => { }
export const deleteUserRepository = async (id: string): Promise<void> => { }

// โœ… GOOD: Validation schema naming
// user-validation.ts
export const createUserValidationSchema = z.object({
  email: z.string().email(),
  name: z.string().min(2),
  password: z.string().min(8)
})

// โœ… GOOD: Helper function naming
// date-helper.ts
export function formatDate(date: Date): string { }
export function parseDate(dateString: string): Date { }
export function isDateInPast(date: Date): boolean { }

File-Specific Naming Patterns:

typescript
// Service files (kebab-case)
// user-service.ts - Main business logic
export const getUserByIdService = async (id: string) => { }

// Service Facade files (kebab-case with -facade suffix)
// user-service-facade.ts - Public interface
export { getUserByIdService, createUserService } from '../user-service'

// Validation files (kebab-case with -validation suffix)
// user-validation.ts - Zod schemas
export const createUserSchema = z.object({ /* ... */ })

// Authorization files (kebab-case with -authorization suffix)
// user-authorization.ts - Permission checks
export const canEditUser = (userId: string, targetUserId: string) => { }

// Helper files (kebab-case with -helper suffix)
// date-helper.ts - Utility functions
export const formatDate = (date: Date) => { }

React Component Naming (PascalCase - Files):

typescript
// โœ… GOOD: PascalCase component names and filenames
// UserProfile.tsx
export function UserProfile({ userId }: { userId: string }) {
  return <div>Profile for {userId}</div>
}

// SubscriptionDashboard.tsx
export default function SubscriptionDashboard() {
  return <div>Subscription Dashboard</div>
}

// โœ… GOOD: Descriptive component names
export function PaymentMethodSelector() { }
export function SubscriptionPlanCard() { }
export function UserAccountSettings() { }
export function NotificationBell() { }
export function TeamSwitcher() { }

// โœ… GOOD: Feature component organization
// components/features/user/UserProfile.tsx
export function UserProfile({ userId }: { userId: string }) {
  // Implementation
}

// โœ… GOOD: Hook naming (must start with 'use')
// hooks/useUserSubscription.ts
export function useUserSubscription(userId: string) {
  // Hook implementation
}

export function useLocalStorage<T>(key: string, defaultValue: T) {
  // Hook implementation
}

// โœ… GOOD: Context naming (PascalCase with Context suffix)
// context/UserContext.tsx
export const UserContext = createContext<User | null>(null)
export const UserProvider = ({ children }) => { }

Component File Organization (ShipSaaS Structure):

components/
โ”œโ”€โ”€ ui/                               # Base reusable UI components
โ”‚   โ”œโ”€โ”€ Button.tsx
โ”‚   โ”œโ”€โ”€ Input.tsx
โ”‚   โ”œโ”€โ”€ Card.tsx
โ”‚   โ”œโ”€โ”€ Dialog.tsx
โ”‚   โ””โ”€โ”€ ...more base components
โ”œโ”€โ”€ features/                         # Feature-specific components
โ”‚   โ”œโ”€โ”€ user/
โ”‚   โ”‚   โ”œโ”€โ”€ UserProfile.tsx          # Main component
โ”‚   โ”‚   โ”œโ”€โ”€ UserAvatar.tsx           # Sub-component
โ”‚   โ”‚   โ”œโ”€โ”€ UserSettings.tsx
โ”‚   โ”‚   โ””โ”€โ”€ hooks/
โ”‚   โ”‚       โ””โ”€โ”€ useUserData.ts       # Feature-specific hook
โ”‚   โ”œโ”€โ”€ organization/
โ”‚   โ”‚   โ”œโ”€โ”€ OrganizationSelector.tsx
โ”‚   โ”‚   โ”œโ”€โ”€ OrganizationForm.tsx
โ”‚   โ”‚   โ””โ”€โ”€ hooks/
โ”‚   โ”œโ”€โ”€ subscription/
โ”‚   โ”‚   โ”œโ”€โ”€ SubscriptionCard.tsx
โ”‚   โ”‚   โ”œโ”€โ”€ PlanSelector.tsx
โ”‚   โ”‚   โ””โ”€โ”€ PricingTable.tsx
โ”‚   โ”œโ”€โ”€ admin/
โ”‚   โ”‚   โ”œโ”€โ”€ UserManagement.tsx
โ”‚   โ”‚   โ”œโ”€โ”€ AnalyticsDashboard.tsx
โ”‚   โ”‚   โ””โ”€โ”€ settings/
โ”‚   โ”œโ”€โ”€ auth/
โ”‚   โ”‚   โ”œโ”€โ”€ LoginForm.tsx
โ”‚   โ”‚   โ”œโ”€โ”€ SignupForm.tsx
โ”‚   โ”‚   โ””โ”€โ”€ PasswordResetForm.tsx
โ”‚   โ”œโ”€โ”€ checkout-stripe/
โ”‚   โ”‚   โ”œโ”€โ”€ CheckoutForm.tsx
โ”‚   โ”‚   โ”œโ”€โ”€ PaymentElement.tsx
โ”‚   โ”‚   โ””โ”€โ”€ OrderSummary.tsx
โ”‚   โ””โ”€โ”€ layouts/
โ”‚       โ”œโ”€โ”€ MainLayout.tsx
โ”‚       โ”œโ”€โ”€ AuthLayout.tsx
โ”‚       โ””โ”€โ”€ AdminLayout.tsx
โ”œโ”€โ”€ context/                         # React Context providers
โ”‚   โ”œโ”€โ”€ UserContext.tsx
โ”‚   โ”œโ”€โ”€ ThemeContext.tsx
โ”‚   โ””โ”€โ”€ OrganizationContext.tsx
โ””โ”€โ”€ hooks/                           # Global custom hooks
    โ”œโ”€โ”€ useUser.ts
    โ”œโ”€โ”€ useOrganization.ts
    โ””โ”€โ”€ useTheme.ts

Component Naming Conventions Summary:

  • File names: PascalCase (e.g., UserProfile.tsx, SubscriptionCard.tsx)
  • Function names: PascalCase (e.g., function UserProfile() )
  • Hook file names: camelCase with 'use' prefix (e.g., useUserData.ts)
  • Hook function names: camelCase (e.g., function useUserData() )
  • Context file names: PascalCase (e.g., UserContext.tsx)
  • Context variable names: PascalCase (e.g., UserContext)
  • Directories: kebab-case (e.g., /user-profile/, /checkout-stripe/)

Import Organization

Consistent import patterns improve code readability and dependency tracking:

Import Order and Grouping (ShipSaaS Standard):

typescript
// โœ… GOOD: Organized import groups
// 1. Node.js built-ins
import fs from 'fs'
import path from 'path'

// 2. External libraries
import React from 'react'
import { z } from 'zod'
import { eq } from 'drizzle-orm'

// 3. Internal services and business logic
import { getUserByIdService } from '@/services/facades/user-service-facade'
import { getUserByIdRepository } from '@/db/repositories/user-repository'

// 4. UI components and utilities
import { Button, Card } from '@/components/ui'
import { UserProfile } from '@/components/features/user'
import { formatDate } from '@/lib/helper/date-helper'

// 5. Types and constants
import type { User } from '@/services/types/domain'
import { MAX_RETRY_ATTEMPTS } from '@/lib/constants'

// 6. Relative imports (local to current file)
import { localHelper } from './local-helper'
import './styles.css'

export function MyComponent() {
  // Component implementation
}

Path Aliases Configuration:

typescript
// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],                        // Root src alias
      "@/components/*": ["./src/components/*"],  // Components
      "@/services/*": ["./src/services/*"],      // Services
      "@/db/*": ["./src/db/*"],                  // Database
      "@/lib/*": ["./src/lib/*"],                // Utilities
      "@/app/*": ["./src/app/*"],                // App routes
      "@/i18n/*": ["./src/i18n/*"]               // i18n
    }
  }
}

Service Layer Imports (Facade Pattern):

typescript
// โœ… GOOD: Import from service facades
// user-service-facade.ts - Public interface
import {
  getUserByIdService,
  updateUserService,
  createUserService
} from '@/services/facades/user-service-facade'

// โœ… GOOD: Type imports from services
import type { User, CreateUserInput } from '@/services/types/domain'

// โŒ BAD: Direct imports from service implementation
import { getUserByIdService } from '@/services/user-service'

// โŒ BAD: Importing repository directly in components
import { getUserByIdRepository } from '@/db/repositories/user-repository'

Component Imports (Feature-Based Organization):

typescript
// โœ… GOOD: UI component imports
import { Button, Card, Input, Dialog } from '@/components/ui'

// โœ… GOOD: Feature component imports
import { UserProfile } from '@/components/features/user'
import { SubscriptionCard } from '@/components/features/subscription'
import { CheckoutForm } from '@/components/features/checkout-stripe'

// โœ… GOOD: Custom hooks from features
import { useUserData } from '@/components/features/user/hooks'

// โœ… GOOD: Relative imports for local components
import { UserAvatar } from './UserAvatar'
import { UserActions } from './UserActions'

// โŒ BAD: Importing deeply nested components
import { UserAvatar } from '@/components/features/user/UserAvatar'
// Use relative imports instead: './UserAvatar'

Database and Repository Imports (Server-Side Only):

typescript
// โœ… GOOD: Import from repositories (in services only)
// user-service.ts
import {
  getUserByIdRepository,
  createUserRepository
} from '@/db/repositories/user-repository'

import type { UserModel, NewUserModel } from '@/db/models/user'

// โœ… GOOD: Type imports from models
import type { Organization } from '@/db/models/organization'

// โŒ BAD: Repository imports in components
// Components should use service facades, not repositories

// โŒ BAD: Direct database imports anywhere
import db from '@/db'

Validation and Helper Imports:

typescript
// โœ… GOOD: Validation schema imports
import { createUserValidationSchema } from '@/services/validation/user-validation'

// โœ… GOOD: Helper function imports
import { formatDate } from '@/lib/helper/date-helper'
import { calculateTotal } from '@/lib/helper/common-helper'

// โœ… GOOD: Authorization helper imports (server-side)
import { canEditUser } from '@/services/authorization/user-authorization'

Circular Dependency Prevention:

typescript
// โœ… GOOD: Layered imports prevent cycles
// Components โ†’ Services (via facades)
// Services โ†’ Database (via repositories)
// Database โ†’ Types (never upward)

// types/domain.ts
export interface User {
  id: string
  name: string
}

// db/models/user.ts - Defines schema
import type { User } from '@/services/types/domain'

// services/user-service.ts - Business logic
import { getUserByIdRepository } from '@/db/repositories/user-repository'
import type { User } from '@/services/types/domain'

// services/facades/user-service-facade.ts - Public API
export { getUserByIdService } from '../user-service'

// components/features/user/UserProfile.tsx - UI
import { getUserByIdService } from '@/services/facades/user-service-facade'

// โŒ BAD: Circular imports
// user-service.ts imports from user-repository.ts
// user-repository.ts imports from user-service.ts โ† Never!

Export Consistency (ShipSaaS Patterns):

typescript
// โœ… GOOD: Named exports for utility functions
// lib/helper/date-helper.ts
export function formatDate(date: Date): string { }
export function parseDate(dateString: string): Date { }
export function isDateInPast(date: Date): boolean { }

// โœ… GOOD: Default export for main React component
// components/features/user/UserProfile.tsx
export default function UserProfile() { }

// โœ… GOOD: Named exports for sub-components
export function UserCard() { }
export function UserList() { }

// โœ… GOOD: Service function exports
// services/user-service.ts
export const getUserByIdService = async (id: string): Promise<User | null> => { }
export const createUserService = async (data: CreateUserInput): Promise<User> => { }
export const updateUserService = async (id: string, data: UserUpdate): Promise<User> => { }

// โœ… GOOD: Facade re-exports for public API
// services/facades/user-service-facade.ts
export {
  getUserByIdService,
  createUserService,
  updateUserService,
  deleteUserService
} from '../user-service'

// โœ… GOOD: Type exports
export type { User, CreateUserInput, UserUpdate } from '../types/domain'

// โœ… GOOD: Barrel exports for feature components
// components/features/user/index.ts
export { default as UserProfile } from './UserProfile'
export { UserCard } from './UserCard'
export { UserList } from './UserList'
export { useUserData } from './hooks'

// โœ… GOOD: Validation schema exports
// services/validation/user-validation.ts
export const createUserValidationSchema = z.object({ /* ... */ })
export const updateUserValidationSchema = z.object({ /* ... */ })

Facade Pattern (Service Public API):

typescript
// services/facades/user-service-facade.ts
// This is the ONLY way external code accesses user service functions

export {
  getUserByIdService,
  createUserService,
  updateUserService,
  deleteUserService,
  listUsersService
} from '../user-service'

export type { User, CreateUserInput, UserUpdate } from '../types/domain'

// โŒ BAD: Direct imports from service
// Instead of: import { getUserByIdService } from '@/services/user-service'
// Use: import { getUserByIdService } from '@/services/facades/user-service-facade'

Component & Feature Exports:

typescript
// components/ui/Button.tsx - Single component
export function Button({ children, ...props }: ButtonProps) { }
// Use: import { Button } from '@/components/ui'

// components/features/user/index.ts - Feature barrel export
export { default as UserProfile } from './UserProfile'
export { UserCard } from './UserCard'
export { UserList } from './UserList'
export * from './types'
export * from './hooks'
// Use: import { UserProfile, UserCard } from '@/components/features/user'

// components/features/user/UserProfile.tsx - Main feature component
export default function UserProfile({ userId }: UserProfileProps) { }

Code Organization Patterns

Consistent patterns for organizing code within files and directories:

Service File Organization (ShipSaaS Pattern):

typescript
// src/services/user-service.ts

// 1. Imports (organized by groups)
import { eq } from 'drizzle-orm'
import type { User, CreateUserInput, UserUpdate } from './types/domain'
import { createUserValidationSchema } from './validation/user-validation'
import { canEditUser, canDeleteUser } from './authorization/user-authorization'
import { getUserByIdRepository, createUserRepository } from '@/db/repositories/user-repository'

// 2. Main service functions (public)
export const getUserByIdService = async (id: string): Promise<User | null> => {
  const user = await getUserByIdRepository(id)
  return user ?? null
}

export const createUserService = async (data: CreateUserInput): Promise<User> => {
  const validated = createUserValidationSchema.parse(data)
  return await createUserRepository(validated)
}

export const updateUserService = async (
  id: string,
  data: UserUpdate,
  userId: string
): Promise<User> => {
  // Authorization check
  if (!canEditUser(userId, id)) {
    throw new AuthorizationError('Cannot edit this user')
  }

  // Validation and update
  return await updateUserRepository(id, data)
}

export const deleteUserService = async (id: string, userId: string): Promise<void> => {
  if (!canDeleteUser(userId, id)) {
    throw new AuthorizationError('Cannot delete this user')
  }
  await deleteUserRepository(id)
}

Service Facade Organization:

typescript
// src/services/facades/user-service-facade.ts
// Public API - only exports from this file should be imported externally

export {
  getUserByIdService,
  createUserService,
  updateUserService,
  deleteUserService,
  listUsersService
} from '../user-service'

export type { User, CreateUserInput, UserUpdate } from '../types/domain'

Component File Organization (ShipSaaS Pattern):

typescript
// src/components/features/user/UserProfile.tsx

'use client'

// 1. Imports (organized)
import { useState } from 'react'
import { Button, Card } from '@/components/ui'
import { useUserData } from './hooks'
import type { User } from '@/services/types/domain'

// 2. Types and interfaces (local to component)
interface UserProfileProps {
  userId: string
  onEdit?: () => void
}

// 3. Component implementation
export default function UserProfile({ userId, onEdit }: UserProfileProps) {
  const [isLoading, setIsLoading] = useState(false)
  const { user, error } = useUserData(userId)

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error loading user</div>
  if (!user) return <div>User not found</div>

  return (
    <Card>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
      {onEdit && <Button onClick={onEdit}>Edit Profile</Button>}
    </Card>
  )
}

Repository File Organization:

typescript
// src/db/repositories/user-repository.ts

import { eq } from 'drizzle-orm'
import db from '../client'
import { usersTable } from '../models/user'
import type { User, NewUser } from '../models/user'

// Query functions
export const getUserByIdRepository = async (id: string): Promise<User | null> => {
  const result = await db.query.usersTable.findFirst({
    where: eq(usersTable.id, id)
  })
  return result ?? null
}

export const createUserRepository = async (data: NewUser): Promise<User> => {
  const [user] = await db.insert(usersTable).values(data).returning()
  return user
}

export const updateUserRepository = async (
  id: string,
  data: Partial<User>
): Promise<User> => {
  const [user] = await db
    .update(usersTable)
    .set(data)
    .where(eq(usersTable.id, id))
    .returning()
  return user
}

export const deleteUserRepository = async (id: string): Promise<void> => {
  await db.delete(usersTable).where(eq(usersTable.id, id))
}

Feature Component Organization (ShipSaaS):

components/features/
โ”œโ”€โ”€ user/                              # User feature domain
โ”‚   โ”œโ”€โ”€ index.ts                       # Barrel export
โ”‚   โ”œโ”€โ”€ UserProfile.tsx                # Main component
โ”‚   โ”œโ”€โ”€ UserCard.tsx                   # Sub-component
โ”‚   โ”œโ”€โ”€ UserList.tsx                   # Sub-component
โ”‚   โ”œโ”€โ”€ UserAvatar.tsx                 # Sub-component
โ”‚   โ”œโ”€โ”€ hooks/
โ”‚   โ”‚   โ”œโ”€โ”€ index.ts                  # Barrel export
โ”‚   โ”‚   โ”œโ”€โ”€ useUserData.ts            # Feature-specific hook
โ”‚   โ”‚   โ””โ”€โ”€ useUserActions.ts         # Feature-specific hook
โ”‚   โ”œโ”€โ”€ types/
โ”‚   โ”‚   โ””โ”€โ”€ user-component-types.ts   # Component-specific types
โ”‚   โ””โ”€โ”€ __tests__/
โ”‚       โ”œโ”€โ”€ UserProfile.test.tsx
โ”‚       โ””โ”€โ”€ useUserData.test.ts
โ”œโ”€โ”€ organization/
โ”‚   โ”œโ”€โ”€ index.ts
โ”‚   โ”œโ”€โ”€ OrganizationSelector.tsx
โ”‚   โ”œโ”€โ”€ OrganizationForm.tsx
โ”‚   โ””โ”€โ”€ hooks/
โ”œโ”€โ”€ subscription/
โ”‚   โ”œโ”€โ”€ index.ts
โ”‚   โ”œโ”€โ”€ SubscriptionCard.tsx
โ”‚   โ”œโ”€โ”€ PlanSelector.tsx
โ”‚   โ””โ”€โ”€ hooks/
โ””โ”€โ”€ checkout-stripe/
    โ”œโ”€โ”€ index.ts
    โ”œโ”€โ”€ CheckoutForm.tsx
    โ”œโ”€โ”€ PaymentElement.tsx
    โ””โ”€โ”€ hooks/

Service Organization (ShipSaaS Monolith):

services/
โ”œโ”€โ”€ authentication/                    # Auth domain
โ”‚   โ”œโ”€โ”€ strategies/                   # Auth strategies
โ”‚   โ””โ”€โ”€ session-management.ts
โ”œโ”€โ”€ authorization/                     # Access control
โ”‚   โ”œโ”€โ”€ rbac/                         # Role-based control
โ”‚   โ”œโ”€โ”€ user-authorization.ts         # User permissions
โ”‚   โ”œโ”€โ”€ organization-authorization.ts
โ”‚   โ””โ”€โ”€ [domain]-authorization.ts
โ”œโ”€โ”€ validation/                        # Input validation
โ”‚   โ”œโ”€โ”€ user-validation.ts
โ”‚   โ”œโ”€โ”€ subscription-validation.ts
โ”‚   โ””โ”€โ”€ [domain]-validation.ts
โ”œโ”€โ”€ facades/                           # Public service APIs
โ”‚   โ”œโ”€โ”€ interceptors/                 # Middleware (logging, errors)
โ”‚   โ”œโ”€โ”€ user-service-facade.ts
โ”‚   โ”œโ”€โ”€ organization-service-facade.ts
โ”‚   โ””โ”€โ”€ [domain]-service-facade.ts
โ”œโ”€โ”€ errors/                            # Custom errors
โ”‚   โ”œโ”€โ”€ AppError.ts
โ”‚   โ”œโ”€โ”€ ValidationError.ts
โ”‚   โ”œโ”€โ”€ AuthorizationError.ts
โ”‚   โ””โ”€โ”€ NotFoundError.ts
โ”œโ”€โ”€ types/                             # Domain types
โ”‚   โ”œโ”€โ”€ domain/
โ”‚   โ”‚   โ”œโ”€โ”€ user-types.ts
โ”‚   โ”‚   โ”œโ”€โ”€ organization-types.ts
โ”‚   โ”‚   โ””โ”€โ”€ [domain].ts
โ”‚   โ””โ”€โ”€ common.ts
โ”œโ”€โ”€ user-service.ts                    # User domain service
โ”œโ”€โ”€ organization-service.ts
โ”œโ”€โ”€ subscription-service.ts
โ”œโ”€โ”€ email-service.ts
โ”œโ”€โ”€ notification-service.ts
โ”œโ”€โ”€ file-service.ts
โ””โ”€โ”€ __tests__/
    โ”œโ”€โ”€ user-service.test.ts
    โ””โ”€โ”€ [domain]-service.test.ts

Database Organization (Drizzle ORM):

db/
โ”œโ”€โ”€ models/                            # Schema definitions
โ”‚   โ”œโ”€โ”€ user.ts                       # User schema
โ”‚   โ”œโ”€โ”€ organization.ts               # Org schema
โ”‚   โ”œโ”€โ”€ subscription.ts
โ”‚   โ””โ”€โ”€ [entity].ts
โ”œโ”€โ”€ repositories/                      # Data access
โ”‚   โ”œโ”€โ”€ user-repository.ts            # User queries
โ”‚   โ”œโ”€โ”€ organization-repository.ts
โ”‚   โ”œโ”€โ”€ subscription-repository.ts
โ”‚   โ””โ”€โ”€ [entity]-repository.ts
โ””โ”€โ”€ scripts/
    โ”œโ”€โ”€ seed.ts                       # Database seeding
    โ””โ”€โ”€ migrate.ts                    # Migration utilities

Test File Organization:

src/
โ”œโ”€โ”€ services/
โ”‚   โ”œโ”€โ”€ user-service.ts
โ”‚   โ””โ”€โ”€ __tests__/               # Tests alongside source
โ”‚       โ”œโ”€โ”€ user-service.test.ts
โ”‚       โ””โ”€โ”€ user-service.integration.test.ts
โ”œโ”€โ”€ components/
โ”‚   โ”œโ”€โ”€ UserProfile.tsx
โ”‚   โ””โ”€โ”€ __tests__/
โ”‚       โ”œโ”€โ”€ UserProfile.test.tsx
โ”‚       โ””โ”€โ”€ UserProfile.stories.tsx  # Storybook stories
โ””โ”€โ”€ __tests__/                   # Global test utilities
    โ”œโ”€โ”€ setup.ts                 # Test setup
    โ”œโ”€โ”€ mocks/                   # Mock implementations
    โ””โ”€โ”€ fixtures/                # Test data

Test Naming Conventions:

โœ… GOOD TEST FILE NAMES:

# Unit tests
user-service.test.ts
UserProfile.test.tsx
date-helper.test.ts

# Integration tests
user-service.integration.test.ts
checkout-flow.integration.test.ts

# End-to-end tests
login-flow.e2e.test.ts
subscription-purchase.e2e.test.ts

# Test utilities
test-utils.ts
mock-data.ts
test-setup.ts

Best Practices

๐Ÿ“

File Organization

โ€ข Feature-based organization in components
โ€ข Barrel exports (index.ts) for clean paths
โ€ข Consistent kebab-case for files/directories
โ€ข Single responsibility per file
โ€ข Co-locate related code (components + hooks + types)
โ€ข Tests alongside source code (tests/)
โš™๏ธ

Service Layer Pattern

โ€ข Validate input with Zod schemas
โ€ข Check authorization before operations
โ€ข Use repositories for data access
โ€ข Expose via facades (public API only)
โ€ข Handle errors with custom classes
โ€ข Return typed results
๐Ÿ“ฅ

Import Management

โ€ข Grouped imports by type (libs, services, components)
โ€ข Use path aliases (@/, @/services, etc.)
โ€ข Import from facades (never direct services)
โ€ข Type-only imports for types (import type )
โ€ข Relative imports for local components
โ€ข Prevent cycles with layered imports
๐Ÿท๏ธ

Naming Consistency

โ€ข PascalCase: Components & Context (UserProfile.tsx)
โ€ข kebab-case: Services & utilities (user-service.ts)
โ€ข camelCase: Hooks & functions (useUserData, getData)
โ€ข SCREAMING_SNAKE_CASE: Constants only
โ€ข Suffixes: -service, -facade, -validation, -helper
โ€ข Prefixes: use (hooks), can/has/is (booleans)
๐Ÿ—„๏ธ

Database Layer

โ€ข Define schemas in models/ (Drizzle)
โ€ข Create repositories for data access
โ€ข Use in services (never in components)
โ€ข Export types from models for services
โ€ข Handle migrations via drizzle-kit
โ€ข Type-safe queries with Drizzle ORM
๐Ÿงช

Testing Strategy

โ€ข Unit tests for services and utilities
โ€ข Component tests with Testing Library
โ€ข Integration tests for service workflows
โ€ข E2E tests with Playwright
โ€ข Mock external services (Stripe, email)
โ€ข Test both authorized & unauthorized access
๐Ÿ”’

Security & Authorization

โ€ข Check auth at service layer entry
โ€ข Validate permissions before operations
โ€ข Use authorization modules (RBAC)
โ€ข Protect API routes with middleware
โ€ข Validate input with Zod schemas
โ€ข Handle errors gracefully and securely
๐Ÿ“ฆ

Monolithic Structure

โ€ข Single Next.js app (not monorepo)
โ€ข Clear layer separation: Routes โ†’ Components โ†’ Services โ†’ DB
โ€ข Feature-based grouping in components
โ€ข Domain-based organization in services
โ€ข Shared lib/ for utilities
โ€ข Scalable for growth with clear patterns

ShipSaaS structure mastered! Your codebase follows clean, layered patterns that make development fast and maintainable. The monolithic structure with clear separation of concerns allows you to scale features efficiently while keeping the code organized and type-safe.