App Structure Guide¶
This document describes the structure and conventions for the app application located in packages/app/src/. This guide explains what each folder contains conceptually and the naming patterns used throughout the codebase.
Folder Structure Overview¶
src/
├── app/ # Next.js App Router pages and layouts
├── components/ # Reusable UI components
├── constants/ # Application constants and configuration
├── hooks/ # Custom React hooks
├── lib/ # Utility libraries and helpers
├── providers/ # React context providers
├── schemas/ # Zod validation schemas
├── sana/ # WhatsApp bot integration module
├── services/ # Data access layer services
├── styles/ # Global styles and CSS files
├── types/ # TypeScript type definitions
└── utils/ # Utility functions and helpers
Detailed Folder Descriptions¶
/app - Next.js App Router Pages¶
Purpose: Contains all pages, layouts, and route-specific components using Next.js 14 App Router.
Structure:
(auth)/- Authentication pages (login, register) - route group(authenticated)/- Protected pages requiring authentication - route groupapi/- API routes and server-side functions- Route files:
page.tsx,layout.tsx,not-found.tsx,error.tsx
Naming Conventions:
- Folders: kebab-case for routes (e.g.,
projects/,user-profile/) - Files: camelCase for components (e.g.,
page.tsx,layout.tsx) - Route groups: parentheses
(groupName)/ - Dynamic routes: brackets
[paramName]/ - Catch-all routes:
[...slug]/
Key Patterns:
- Each route can have its own
layout.tsxfor nested layouts - Client components should be in separate
-client.tsxfiles when needed - Every component should have a corresponding
.test.tsxfile
/components - Reusable UI Components¶
Purpose: Houses all reusable React components organized by domain and type.
Structure:
auth/- Authentication-related componentslayout/- Application layout components (header, sidebar, footer)projects/- Project-specific componentsui/- Base UI components (buttons, inputs, cards, etc.)__mocks__/- Mock components for testing
Naming Conventions:
- Folders: PascalCase matching component name
- Components: PascalCase (e.g.,
Button.tsx,CreateProjectForm.tsx) - Each component folder contains:
ComponentName.tsx,ComponentName.test.tsx,index.ts - UI components additionally have:
ComponentName.stories.tsx - CSS modules:
ComponentName.module.css
Key Patterns:
- Components in
ui/folder must have Storybook stories - Use ShadCN UI components via
npx shadcn@latest add <component> - Replace
data-slotwithdata-testidafter adding ShadCN components - Import components from specific files, not barrel exports
- Always include WAI-ARIA attributes for accessibility
/constants - Application Constants¶
Purpose: Centralized location for application-wide constants and configuration values.
Structure:
database.ts- Database-related constantsurls.ts- URL constants and routesindex.ts- Barrel export for constants
Naming Conventions:
- Files: camelCase with descriptive names
- Constants: UPPER_SNAKE_CASE for immutable values
- Objects: camelCase for configuration objects
/hooks - Custom React Hooks¶
Purpose: Custom React hooks for reusable stateful logic.
Structure:
- Hook files:
useHookName.ts - Test files:
useHookName.test.ts - Mock files:
__mocks__/useHookName.ts - Barrel export:
index.ts
Naming Conventions:
- Files: camelCase starting with
useprefix - Hook functions: camelCase with
useprefix - Export the hook as default from individual files
Key Patterns:
- Server state managed via React Query with Supabase
- Use helper functions from
lib/for data fetching - Always include comprehensive tests
- Create mock implementations in
__mocks__/folder
/lib - Utility Libraries and Helpers¶
Purpose: Contains utility functions, helper modules, and third-party integrations.
Structure:
supabase/- Supabase client configurationsauthHelper.ts- Authentication utility functionsdatabaseHelper.ts- Database query helpersstorageHelper.ts- File storage utilitiesclientLogger.ts- Client-side logging utilityenvironment.ts- Environment variable helpers__mocks__/- Mock implementations for testing
Naming Conventions:
- Files: camelCase with descriptive names ending in
Helper.tsor purpose - Functions: camelCase with descriptive names
- Always include corresponding
.test.tsfiles
Key Patterns:
- Always use helper functions instead of Supabase directly
- Use
clientLoggerfor all logging (error, warn, info, debug) - Environment variables should be accessed through
environment.ts - Export types from
types/folder, not from implementation files
/providers - React Context Providers¶
Purpose: React context providers for global state management.
Structure:
- Individual providers:
ProviderName.tsx - Test files:
ProviderName.test.tsx - Root provider:
RootProviders.tsx - Mock providers:
__mocks__/ProviderName.tsx
Naming Conventions:
- Files: PascalCase ending with
Provider.tsx - Context names: PascalCase ending with
Context - Hook names: camelCase starting with
useprefix
Key Patterns:
- Use TypeScript interfaces for context values
- Always provide default values for contexts
- Include error boundaries where appropriate
- Combine all providers in
RootProviders.tsx
/schemas - Zod Validation Schemas¶
Purpose: Zod validation schemas for data validation and type inference.
Structure:
- Schema files:
feature.schema.ts - Test files:
feature.schema.test.ts - One schema file per domain/feature
Naming Conventions:
- Files: camelCase ending with
.schema.ts - Schema variables: camelCase ending with
Schema - Type exports: PascalCase matching the schema purpose
Key Patterns:
- Export schema definitions, inferred types, and transform functions
- Use
z.infer<typeof SchemaName>for type inference - Create transform functions for API data conversion
- Always include comprehensive tests
Database Integration:
- When adding operations for a new database table:
- Create the validation schema in this folder
- Create corresponding types in
/typesfolder if needed - Create a service in
/servicesfolder for data operations
/services - Data Access Layer¶
Purpose: Service layer for all data operations, API calls, and external integrations.
Structure:
- Service files:
featureService.ts - Test files:
featureService.test.ts - Mock files:
__mocks__/featureService.ts
Naming Conventions:
- Files: camelCase ending with
Service.ts - Functions: camelCase with descriptive action names
- Follow the ServiceResponse pattern from SERVICE_PATTERNS.md
Key Patterns:
- Use helper functions from
lib/instead of Supabase directly - Always return
ServiceResponse<T>with{ data, error }structure - Include comprehensive error handling and logging
- Use
clientLogger.error()for error logging - Never throw errors - always return them in response object
Database Integration:
- For new database tables, create corresponding service files
- Include CRUD operations as needed
- Follow authentication patterns from SERVICE_PATTERNS.md
- Use cleanup patterns for multi-step operations
/styles - Global Styles¶
Purpose: Global CSS files and style configurations.
Structure:
globals.css- Global styles and CSS variables
Key Patterns:
- Use TailwindCSS for utility classes
- Component-specific styles should use CSS modules
- Design system colors defined in
tailwind.config.js - Use
cn()utility from@/lib/utilsfor conditional classes
/sana - WhatsApp Bot Integration¶
Purpose: WhatsApp bot functionality integrated within the app.
Structure:
src/- Source code for the WhatsApp botindex.ts- Main entry pointlib/- Library utilities (logger, helpers)services/- WhatsApp-specific services- API Route:
/app/api/sana/webhook/route.ts
Naming Conventions:
- Same as the rest of the app
- Services: camelCase (e.g.,
messageService.ts) - Functions: camelCase for functionality
Key Patterns:
- Deployed as Vercel API Function
- Direct imports from app services and types
- Uses its own logger for WhatsApp-specific logging
/types - TypeScript Type Definitions¶
Purpose: TypeScript type definitions and interfaces.
Structure:
- Feature types:
feature.ts - Testing types:
testing/subfolder - Barrel export:
index.ts
Naming Conventions:
- Files: camelCase with descriptive names
- Interfaces: PascalCase with descriptive names
- Types: PascalCase with descriptive names
- Enums: PascalCase with descriptive names
Key Patterns:
- Always export types from this folder, not from implementation files
- Group related types in single files
- Use interfaces for object shapes
- Use types for unions, primitives, and computed types
- Include testing-specific types in
testing/subfolder
/utils - Utility Functions¶
Purpose: Pure utility functions and helper methods.
Structure:
- Utility files:
purpose.ts - Test files:
purpose.test.ts - Mock files:
__mocks__/purpose.ts
Naming Conventions:
- Files: camelCase with descriptive names
- Functions: camelCase with descriptive names
Key Patterns:
- Functions should be pure when possible
- Include comprehensive tests
- Use TypeScript strictly - avoid
anytypes - Export individual functions, not default exports
File Naming and Development Conventions¶
General File Naming¶
- Components: PascalCase (e.g.,
CreateProjectForm.tsx) - Pages/Layouts: kebab-case for routes, camelCase for files
- Hooks: camelCase starting with
use - Services: camelCase ending with
Service - Utilities: camelCase with descriptive names
- Types: camelCase for files, PascalCase for definitions
- Constants: camelCase for files, UPPER_SNAKE_CASE for values
Development Process¶
Every time you create or modify a file, follow this process:
- Main File:
- Run prettier:
npx prettier --write path/to/file.ts - Run lint:
npx eslint path/to/file.ts --fix - Run typecheck:
yarn typecheck - Run prettier again if changes were made
-
Save file (auto-sorts imports)
-
Tests:
- Create/update corresponding test file
- Run prettier on test file
- Run lint on test file:
npx eslint path/to/file.test.ts --fix - Run typecheck
- Run the specific test:
yarn test path/to/file.test.ts -
Save file
-
UI Components:
- Create Storybook story for UI components
- Run prettier, lint, typecheck on story file
-
Save file
-
E2E Tests:
- Consider if E2E tests needed for user flows
- Create/update E2E tests in
e2e/tests/ - Run specific E2E test to verify
Import Conventions¶
- Use
@/path alias for src directory - Import from specific component files, not barrel exports
- Use
@mocks/for root-level mocks - Avoid dependency cycles between modules
Code Quality Standards¶
- TypeScript: Never use
anytype - create proper interfaces - Testing: 80% statement/function coverage, 75% branch coverage
- Accessibility: Include WAI-ARIA attributes
- Logging: Use
clientLoggerfor all app logging - Error Handling: Use ServiceResponse pattern in services
- Linting: Run
npx eslint file --fixto sort imports and fix formatting - Formatting: Do not manually add extra lines - let prettier/eslint handle it
Helper Usage Guidelines¶
Database Operations¶
Always use helper functions instead of Supabase directly:
// ✅ Correct - Use helper
import { databaseHelper } from '@/lib/databaseHelper';
const result = await databaseHelper.query(/* ... */);
// ❌ Wrong - Direct Supabase usage
import { supabaseClient } from '@/lib/database/client/browser';
const result = await supabaseClient.from('table').select();
Storage Operations¶
Use storage helper for file operations:
// ✅ Correct - Use helper
import { storageHelper } from '@/lib/storageHelper';
const url = await storageHelper.upload(file, path);
// ❌ Wrong - Direct Supabase storage
import { supabaseClient } from '@/lib/database/client/browser';
const result = await supabaseClient.storage.from('bucket').upload();
Authentication¶
Use auth helper for authentication operations:
// ✅ Correct - Use helper
import { authHelper } from '@/lib/authHelper';
const user = await authHelper.getCurrentUser();
// ❌ Wrong - Direct Supabase auth
import { supabaseClient } from '@/lib/database/client/browser';
const {
data: { user },
} = await supabaseClient.auth.getUser();
This structure ensures consistency, maintainability, and follows established patterns throughout the codebase.