Technical & Customization

Common questions about extending, customizing, and scaling CareNova for developers.

Written By Dev010

Last updated 19 days ago

Can I add a new module?

Yes β€” and the architecture is designed to make this straightforward. Every existing module follows the same pattern, so adding a new one means replicating that pattern rather than figuring out a new approach each time.

The steps for a new module from scratch:

1. Define the table

Add the table definition to lib/db/schema.ts following the same structure as existing tables β€” uuid primary key, timestamps, foreign keys where needed.

2. Apply the schema

npm run db:push        # local development
npm run db:generate    # generate migration for production

3. Create the Zod schema

Add a validation file to lib/validations/{entity}.ts with schemas for create and update operations.

4. Create server actions

Add lib/actions/{entity}-actions.ts following the standard pattern β€” getCachedCurrentUser, requireRole or requirePermission, Zod parse, Drizzle mutation, revalidatePath.

5. Add the route

Create the page at app/(dashboard)/dashboard/{entity}/page.tsx as a Server Component that fetches data and passes it to a list component.

6. Add permissions (if needed)

Add new permission keys to PERMISSION_KEYS and DEFAULT_ROLE_PERMISSIONS in lib/constants/permissions.ts.

7. Add the nav item

Add the module to the relevant section in nav-main.tsx with the appropriate roles array and optional permissionKey.

The Architecture Overview article covers the full pattern in detail including a code example.

Can I disable a module I don't need?

There is no toggle to disable modules from the UI. The practical approach depends on how completely you want to remove it.

Hide it from the sidebar β€” the lightest option. Remove or comment out the nav item in nav-main.tsx. The route still exists but is no longer accessible via navigation.

Revoke permissions for all roles β€” go to Dashboard β†’ Permissions and revoke all permission keys for the module across every role. Staff can no longer access the module's server actions even if they navigate to the URL directly.

Remove the route entirely β€” delete the page folder under app/(dashboard)/dashboard/{module}/. Next.js will return a 404 for that route. Also remove the corresponding server actions and nav item to keep the codebase clean.

For the Odontogram module specifically β€” it is already conditionally rendered. It only appears in the sidebar when the clinic type is set to dental. Changing the clinic type to general or ophthalmology removes it from navigation without any code change.

How do I upgrade to a newer version of CareNova?

CareNova does not have an automatic update mechanism. Updates are released as new downloads on CodeCanyon.

The general upgrade process:

1. Review the changelog

Check what changed between your current version and the new release before touching anything. Schema changes and breaking changes will be documented there.

2. Back up your database

Before applying any changes, take a full backup via Supabase Dashboard β†’ Project Settings β†’ Backups or pg_dump.

3. Apply schema changes

If the new version includes schema changes, a migration file will be provided. Run it in the Supabase SQL Editor or via:

npm run db:migrate

4. Update the codebase

Copy the updated source files into your project. If you have made customizations, reconcile them with the new version carefully β€” particularly in files that change frequently like nav-main.tsx, lib/db/schema.ts, and lib/constants/permissions.ts.

5. Test before deploying

Run the updated version locally against a copy of your production data before deploying. Confirm the build passes:

npm run build

If you have made significant customizations to the codebase, upgrading becomes a manual merge process. The more your local version diverges from the base, the more careful the upgrade needs to be.

Does CareNova support multi-tenancy out of the box?

No. CareNova is a single-tenant system β€” one installation serves one clinic. The data model has no tenant isolation layer.

The Extended License on CodeCanyon grants the rights to build a SaaS product on top of CareNova. However the multi-tenancy architecture itself is not implemented β€” the license grants the right, not the feature.

Building multi-tenancy on CareNova would require at minimum:

  • Adding clinic_id to every patient-facing table β€” patients, appointments, medical records, invoices, payments, expenses, inventory, staff, and all related tables

  • Enforcing clinic_id filtering on every Drizzle query in every server action

  • Routing and subdomain logic to identify which clinic a request belongs to

  • Enabling Row Level Security in Supabase to prevent cross-tenant data leakage at the database level

  • A tenant provisioning flow for new clinic signups

This is substantial work. For multiple independent clinics in the near term, a separate installation per clinic is the practical approach.

Can I use a different database provider instead of Supabase?

Partially. The database layer uses Drizzle ORM with a standard PostgreSQL connection β€” any PostgreSQL provider works at the query level. Neon, Railway, Render, or a self-hosted PostgreSQL instance can replace Supabase's PostgreSQL.

However Supabase also provides Auth and Storage, which are used throughout the application. Replacing just the database while keeping Supabase Auth and Storage is straightforward β€” update DATABASE_URL to point to your PostgreSQL provider and leave the Supabase Auth and Storage configuration unchanged.

Replacing Supabase entirely β€” database, auth, and storage β€” requires replacing:

  • lib/supabase/ β€” auth client and session management

  • lib/auth/ β€” all auth helpers

  • middleware.ts β€” session validation

  • All storage upload calls in server actions β€” currently call Supabase Storage SDK directly

It is technically possible but represents a significant rewrite of the auth and storage layers.

Can I use CareNova as a starting point for a different type of business β€” not a clinic?

Yes, with the understanding that the data model and UI vocabulary are built around clinical workflows. The underlying architecture β€” Next.js App Router, Drizzle, Supabase Auth, Server Actions, RBAC, role-specific dashboards β€” is solid and reusable for any multi-role SaaS application.

What you would adapt:

  • lib/db/schema.ts β€” replace or extend clinical tables with your domain entities

  • lib/constants/permissions.ts β€” redefine permission keys for your domain

  • nav-main.tsx β€” update navigation to reflect your modules

  • Landing page components β€” replace clinic-specific copy and assets

What carries over unchanged:

  • Auth system, session handling, rate limiting, audit logs

  • RBAC enforcement pattern

  • Server Action architecture

  • Form handling and validation pattern

  • UI component system (shadcn/ui + Tailwind)

  • Deployment and infrastructure setup

How do I customize the dashboard design β€” colors, fonts, or layout?

The dashboard design is controlled by CSS variables defined in app/globals.css and configured in tailwind.config.ts.

To change dashboard colors: Update the CSS variable values in globals.css for both light and dark mode β€” variables like --primary, --background, --foreground, --muted, and --sidebar control the core palette.

To change fonts: Update app/fonts.ts to load different font files and update the font-heading and font-sans references in tailwind.config.ts.

To change the sidebar layout: Edit app/(dashboard)/dashboard/ _components/app-sidebar.tsx and nav-main.tsx.

Dashboard design changes affect all roles and all pages. The public landing page has its own separate theme system β€” changes in globals.css do not affect it. Landing page colors are controlled via Dashboard β†’ Landing Settings β†’ Colors tab.