Overview
Echoes of the Past uses a feature-based architecture to organize code by domain functionality rather than technical layers. Each feature encapsulates its own components, hooks, actions, and utilities, making the codebase scalable and maintainable.Feature Directory Structure
The application is organized into self-contained feature modules located infeatures/:
Core Architecture Patterns
Actions Pattern (Server-Side Logic)
Each feature contains anactions.ts file with server-side functions marked with 'use server'. These handle database operations, API calls, and business logic.
- Character Actions
- Quiz Actions
- Call Actions
features/character/actions.ts
Components Pattern (UI Layer)
Components are organized by feature and follow Next.js App Router conventions:Server vs Client Components
Server vs Client Components
Server Components (default in Next.js 13+):
- No
'use client'directive - Can directly access server-side resources
- Better performance, smaller bundles
- Used for static content, data fetching
- Must include
'use client'at top of file - Required for interactivity (hooks, state, events)
- Used for forms, real-time features, browser APIs
features/call/components/call-interface.tsx
Hooks Pattern (Reusable Logic)
Custom hooks encapsulate feature-specific logic and state management:features/call/hooks/useVapi.ts
Lib Pattern (Utilities)
Each feature can have alib/ directory for feature-specific utilities:
features/call/lib/generate-feedback.ts
Type Definitions
Features define their own types in dedicatedtypes.ts files:
features/call/types.ts
Best Practices
When to Create a New Feature
When to Create a New Feature
Create a new feature module when:
- Functionality is logically independent
- Multiple related components/hooks are needed
- Feature has its own server actions
- Code reuse across multiple pages is expected
call feature includes call interface, transcription, feedback, and related utilities.Organizing Feature Components
Organizing Feature Components
Within
components/, organize by:- Specificity: More specific components in subdirectories
- Reusability: Shared components at root level
- Naming: Use descriptive, feature-specific names
Server Actions vs API Routes
Server Actions vs API Routes
Use Server Actions (
actions.ts) when:- Direct database operations
- Form submissions
- Server-side mutations
- Type-safe data fetching
/app/api/) when:- Webhooks from external services
- Public APIs
- Non-Next.js clients
- Complex streaming responses
Feature Integration Example
Here’s how features work together in a page:app/app/call/[id]/page.tsx
Related Documentation
- Prompt Engineering - Learn how to craft AI prompts
- Voice Integration - Vapi SDK and voice features