Architecture

Following a monorepo architecture, the NextJet starter kit is designed to help you build scalable and maintainable applications.

The kit uses a Turborepo monorepo, making it easy to extend your project with features like a mobile app and share code and configs between applications.

With NextJet's modular architecture, you can add or remove features and customize the app to fit your needs.

You can manage code for different projects, like marketing sites and web apps, all in one place.

Each application gets its own subdomain, boosting your branding and adding a professional touch. Plus, it promotes teamwork by allowing code sharing between projects.

monorepo structure

Folder Structure

In a TurboRepo setup, different parts of the project are often organized into separate folders such as apps and packages to facilitate modular development, reuse, and maintenance.

Inside the apps folder are different applications we can deploy, like marketing sites, web apps, and mobile apps.

Everything inside the packages directory consists of reusable packages that can be shared among multiple applications or packages.

  • marketing: Public facing marketing site, including blog, docs and legal pages.
  • dashboard: Main application for the SaaS product.
  • auth: Authentication logic.
  • configs: Shared configurations for ESLint, Prettier, Tailwind, and TypeScript.
  • db: Prisma database schema and migrations.
  • email: Email templates and provider.
  • stripe: Stripe payment logic.
  • ui: Shared UI components (ShadCN and custom).
  • utils: Shared constants and utility functions.

Feature Based Folder Structure

The NextJet starter kit uses a feature-based folder structure to organize code.

Inside dashboard/src/features and marketing/src/features, you'll find folders for each feature, such as landing, profile, admin, and onboarding.

Each feature is a self-contained module that includes all the necessary code specific to that feature, keeping things nicely separated. This way of organizing code makes it easier to maintain and scale the project.

For example the admin feature might contain everything related to the admin dashboard.

index.ts
index.ts

You don't need all folders for every feature. Only include the ones that are necessary for the feature.

In the index.ts file, you can export all the essential components, hooks, and pages for the feature you want to make available to the rest of the project.

We typically export the page components and import it in a page.tsx file, like so:

apps/dashboard/src/app/(dashboard)/admin/page.tsx
import type { Metadata } from "next"

import { OverviewPage } from "@/features/admin/"

export const metadata: Metadata = {
  title: "Admin",
  description: "Admin",
}

export default OverviewPage

To avoid circular dependencies, use relative paths when importing within the same feature folder (e.g., the admin feature). Use absolute paths only when importing from different features.

I've added ESLint rules that require you to export any file inside the feature folder you want to make available to the rest of the project. If you try to import something that isn't exported, you'll get a linting error.

Import Paths

We employ absolute import paths to make it easier to import files and components across the project.

It also makes it easier to move files around without breaking imports.

Importing From The Root Of The Project

To import from the root of the project, you can use the ~ alias, like so:

import dashboard from "~/public/images/landing/dashboard.jpg"

Importing From The src Directory

The @ alias is used to import from the src directory, like so:

import { Providers } from "@/app/providers"

Importing From Packages

In order to import from a package, you can use the package name as the alias, like so:

import { sendEmail, SuccessfulPayment } from "@package/email"
import { stripe } from "@package/stripe"
import { sendError } from "@package/utils"

Last updated on