Folder Structure
A complete walkthrough of CareNova's project directory — what lives where and why it is organized that way.
Written By Dev010
Last updated 8 months ago
CareNova follows a consistent folder structure that mirrors the architecture — every file has a clear home and a clear reason for being there. This guide walks through each directory so you can navigate the codebase confidently from day one.
Root Directory
carenova-app/
├── app/ # Next.js App Router — all routes and pages
├── components/ # Reusable UI components
├── lib/ # Shared logic, actions, DB, cache, auth
├── contexts/ # React contexts (preferences, theme)
├── types/ # Shared TypeScript type definitions
├── messages/ # next-intl translation files
├── docs/ # Internal documentation
├── migrations/ # SQL migration files
├── scripts/ # Seed and utility scripts
├── public/ # Static assets served at /
├── INSTALL.sql # Master database installation SQL
├── middleware.ts # Next.js middleware (auth, routing, license)
├── next.config.js # Next.js configuration
├── tailwind.config.ts # Tailwind CSS configuration
└── tsconfig.json # TypeScript configurationapp/
The app/ directory contains all routes using the Next.js App Router file-system convention.
app/
├── layout.tsx # Root layout — fonts, providers, globals
├── page.tsx # Public landing page (clinic-type branching)
├── fonts.ts # Font loading configuration
├── globals.css # Global CSS and design tokens
├── _components/ # App-level shared components (e.g. landing FAQ)
├── api/ # API route handlers
│ ├── patients/export/ # CSV export for patients
│ ├── appointments/export/# CSV export for appointments
│ ├── teeth-image/ # Teeth image handler for odontogram
│ └── cron/cleanup-auth/ # Auth cleanup cron job endpoint
├── (auth)/ # Auth route group — no dashboard layout
│ ├── login/
│ ├── signup/
│ └── auth/callback/ # Supabase OAuth callback
├── (dashboard)/ # Dashboard route group — sidebar + header layout
│ └── dashboard/ # All dashboard module pages
├── blog/ # Public blog index and post detail
├── appointment/ # Public appointment booking page
├── portal/ # Patient portal (placeholder)
└── policies/[slug]/ # Dynamic policy pagesRoute groups in parentheses — (auth) and (dashboard) — are a Next.js convention. The group name does not appear in the URL. They exist purely to apply a shared layout to everything inside them without affecting the route path.
app/(dashboard)/dashboard/
All dashboard module pages live here. Each module is a folder with its own page.tsx and optional sub-routes.
dashboard/
├── layout.tsx # Dashboard layout — sidebar, header, auth check
├── page.tsx # Role-specific dashboard home
├── _components/ # Dashboard-wide shared components
│ ├── app-sidebar.tsx # Sidebar shell
│ ├── nav-main.tsx # Navigation items with role/permission filters
│ ├── dashboard-header.tsx
│ ├── nav-user.tsx # User menu in sidebar footer
│ ├── theme-switcher.tsx
│ ├── revenue-chart.tsx
│ ├── activity-chart.tsx
│ └── ...
├── patients/
│ ├── page.tsx # Patient list
│ ├── new/page.tsx # Create patient
│ └── [id]/
│ ├── page.tsx # Patient detail
│ └── edit/page.tsx # Edit patient
├── appointments/
│ ├── page.tsx
│ └── [id]/edit/page.tsx
├── calendar/page.tsx
├── medical-records/
│ ├── page.tsx
│ ├── vitals/page.tsx
│ ├── clinical-notes/page.tsx
│ ├── diagnoses/page.tsx
│ ├── attachments/page.tsx
│ └── visit-timeline/page.tsx
├── odontograms/page.tsx
├── prescriptions/
│ ├── page.tsx
│ └── new/page.tsx
├── test-reports/
│ ├── page.tsx
│ ├── new/page.tsx
│ ├── tests/page.tsx
│ ├── methodologies/page.tsx
│ ├── turnaround-times/page.tsx
│ ├── sample-types/page.tsx
│ └── categories/page.tsx
├── invoices/
│ ├── page.tsx
│ ├── new/page.tsx
│ └── [id]/page.tsx
├── payments/page.tsx
├── expenses/
│ ├── page.tsx
│ └── new/page.tsx
├── billing/
│ ├── page.tsx
│ └── new/page.tsx
├── services/page.tsx
├── departments/page.tsx
├── inventory/
│ ├── page.tsx
│ ├── new/page.tsx
│ └── [id]/
│ ├── page.tsx
│ └── edit/page.tsx
├── staff/page.tsx
├── lab-vendors/
│ ├── page.tsx
│ └── new/page.tsx
├── blog/
│ ├── page.tsx
│ └── categories/page.tsx
├── permissions/page.tsx
├── landing-settings/page.tsx
├── pending-approval/page.tsx
├── settings/page.tsx
└── coming-soon/page.tsxcomponents/
Reusable UI components that are referenced across multiple pages or modules.
components/
├── ui/ # shadcn/ui primitives
│ ├── button.tsx
│ ├── card.tsx
│ ├── dialog.tsx
│ ├── input.tsx
│ ├── select.tsx
│ ├── sheet.tsx
│ ├── table.tsx
│ └── ... # All shadcn components
├── landing/ # Public landing page components
│ ├── dental/ # DentalHero, DentalServices, DentalFooter, etc.
│ ├── ophthalmology/ # OphthalmologyHero, OphthalmologyServices, etc.
│ └── general/ # GeneralHero, GeneralServices, etc.
├── dashboard/ # Shared dashboard components
│ ├── full-profile-button.tsx
│ └── ...
└── settings/ # Settings UI components
└── landing/
├── landing-page-settings.tsx
├── colors-tab.tsx
└── content-tab.tsxComponents specific to a single module live inside that module's folder under app/(dashboard)/dashboard/{module}/_components/ rather than in the top-level components/ directory. Only genuinely shared components belong at the top level.
lib/
The core of the application logic — server actions, database access, auth helpers, caching, validation schemas, and constants.
lib/
├── actions/ # Server Actions ("use server")
│ ├── patient-actions.ts
│ ├── appointment-actions.ts
│ ├── invoice-actions.ts
│ ├── payment-actions.ts
│ ├── expense-actions.ts
│ ├── medical-records-actions.ts
│ ├── prescription-actions.ts
│ ├── lab-test-actions.ts
│ ├── staff-actions.ts
│ ├── inventory-actions.ts
│ ├── service-actions.ts
│ ├── department-actions.ts
│ ├── odontogram-actions.ts
│ ├── permission-actions.ts
│ ├── auth-actions.ts
│ ├── clinic-actions.ts
│ ├── landing-settings-actions.ts
│ ├── blog-actions.ts
│ ├── blog-category-actions.ts
│ └── notification-actions.ts
├── auth/ # Auth utilities
│ ├── index.ts # getAuthUser, getCurrentUser, requireRole
│ ├── require-permission.ts # requirePermission, checkPermission
│ ├── audit.ts # Auth audit log, rate limiting
│ ├── session-tracking.ts # Session create, revoke, cleanup
│ └── password-policy.ts # Password validation rules
├── cache/ # Caching helpers
│ ├── index.ts # getCachedCurrentUser, getCachedClinic, etc.
│ └── invalidators.ts # Cache invalidation functions
├── constants/ # Shared constants
│ ├── permissions.ts # PERMISSION_KEYS, DEFAULT_ROLE_PERMISSIONS
│ ├── expenses.ts # Expense category constants
│ └── landing-defaults.ts # Default settings per clinic type
├── data/ # Static default data
│ └── landing-defaults/
│ ├── dental.json
│ ├── ophthalmology.json
│ └── general.json
├── db/ # Database layer
│ ├── index.ts # Drizzle client instance
│ ├── schema.ts # All table definitions (single source of truth)
│ └── seed.ts # Seed script
├── supabase/ # Supabase client helpers
│ ├── server.ts # createClient() for server components/actions
│ ├── middleware.ts # updateSession() for middleware
│ └── admin.ts # getSupabaseAdmin() using service role key
├── validations/ # Zod schemas
│ ├── patient.ts
│ ├── appointment.ts
│ ├── invoice.ts
│ └── ...
├── preferences/ # User/clinic preference constants
│ └── constants.ts # Cookie names, locale options, etc.
├── utils/ # General utility functions
│ └── safe-async.ts # Background task error wrapper
├── config.ts # siteConfig (debug flag, site URL, etc.)
├── debug.ts # Conditional debug logger
└── i18n.ts # next-intl i18n configurationKey Files to Know
These files have outsized importance in the codebase — understanding them makes everything else easier to navigate.
messages/
Translation files for next-intl. Organized by locale at the top level for dashboard strings, and by clinic type and locale for landing page strings.
messages/
├── en.json # Dashboard translations — English
├── fr.json # Dashboard translations — French
├── es.json # Dashboard translations — Spanish
├── ar.json # Dashboard translations — Arabic
└── landing/
├── dental/
│ ├── en.json
│ ├── fr.json
│ ├── es.json
│ └── ar.json
├── general/
│ └── ...
└── ophthalmology/
└── ...public/
Static assets served directly by the web server at the root URL.
public/
├── landing/
│ ├── dental/ # Default dental landing images
│ ├── ophthalmology/ # Default ophthalmology landing images
│ └── general/ # Default general landing images
├── teeth/ # Teeth images for odontogram
│ └── ... # Populated by npm run download-teeth
└── ... # Favicons, og images, etc.Landing images in public/landing/ are the fallback defaults. When a clinic uploads custom images via Landing Settings, those Supabase Storage URLs are used instead.
Was this helpful?
More in Technical
Migrations (push vs migrate)Security ReferenceCloudflare Workers DeploymentStill need help? Ask the team