Next Starter Kit
Getting Started

Project Structure

Understand the organization and architecture of the Next.js Full-Stack Starter Kit

Project Structure

Learn how the codebase is organized to help you navigate and extend the starter kit effectively.

Overview

The project follows Next.js 16 App Router conventions with a clear separation of concerns:

nextjs-starter-kit/
├── src/                    # Source code
│   ├── app/               # Next.js App Router pages
│   ├── components/        # React components
│   ├── db/                # Database schema and config
│   ├── lib/               # Utilities and helpers
│   ├── hooks/             # Custom React hooks
│   ├── stores/            # Zustand state stores
│   ├── providers/         # React context providers
│   └── config/            # Configuration files
├── public/                # Static assets
├── scripts/               # Automation scripts
├── e2e/                   # End-to-end tests
├── drizzle/               # Database migrations
└── ...config files

Directory Breakdown

/src/app - Application Routes

The app directory uses Next.js App Router for file-based routing with route groups:

app/
├── (auth)/                 # Authentication pages (grouped layout)
│   ├── sign-in/           # Sign in page
│   ├── sign-up/           # Sign up page
│   ├── verify-email/      # Email verification
│   ├── forgot-password/   # Password reset request
│   └── reset-password/    # Password reset form

├── (marketing)/           # Public pages (grouped layout)
│   ├── blog/              # Blog listing and posts
│   ├── pricing/           # Pricing plans page
│   ├── contact-us/        # Contact form
│   ├── changelog/         # Product changelog
│   ├── waitlist/          # Waitlist signup
│   ├── privacy-policy/    # Privacy policy
│   └── terms-of-service/  # Terms of service

├── dashboard/             # Protected dashboard area
│   ├── admin/             # Admin-only pages
│   │   ├── blog/          # Blog management
│   │   ├── email-templates/ # Email template editor
│   │   ├── user-management/ # User & role management
│   │   ├── subscription-plans/ # Manage pricing
│   │   ├── security-logs/ # Security audit logs
│   │   ├── testimonials/  # Testimonial management
│   │   ├── faqs/          # FAQ management
│   │   ├── changelog/     # Changelog management
│   │   ├── contact-submissions/ # Contact form entries
│   │   ├── waitlist/      # Waitlist entries
│   │   ├── marketing/     # Marketing controls
│   │   └── feedback/      # User feedback
│   │
│   └── user/              # User dashboard
│       ├── settings/      # User settings and profile
│       ├── billing/       # Subscription management
│       └── testimonial/   # Submit testimonials

├── api/                   # API routes
│   ├── auth/              # Authentication endpoints
│   ├── blog/              # Blog CRUD operations
│   ├── admin/             # Admin operations
│   ├── subscription/      # Subscription management
│   ├── stripe/            # Stripe webhooks
│   ├── uploadthing/       # File upload handlers
│   ├── ai/                # AI writing assistant
│   ├── contact/           # Contact form submission
│   ├── testimonials/      # Testimonial CRUD
│   ├── faqs/              # FAQ CRUD
│   ├── changelog/         # Changelog CRUD
│   ├── waitlist/          # Waitlist management
│   ├── users/             # User profile operations
│   └── me/                # Current user data

├── actions/               # Server actions
├── layout.tsx             # Root layout
├── globals.css            # Global styles
└── page.tsx               # Homepage

Note: Route Groups: Folders wrapped in parentheses like (auth) and (marketing) are route groups. They organize routes without affecting the URL structure.

/src/components - React Components

Organized by feature and purpose:

components/
├── ui/                    # Base UI components (shadcn/ui)
│   ├── button.tsx
│   ├── input.tsx
│   ├── dialog.tsx
│   ├── table.tsx
│   └── ...50+ components

├── auth/                  # Authentication components
│   ├── sign-in-form.tsx
│   ├── sign-up-form.tsx
│   ├── forgot-password-form.tsx
│   └── oauth-buttons.tsx

├── blog/                  # Blog-related components
│   ├── blog-card.tsx
│   ├── blog-editor.tsx
│   ├── tiptap-editor.tsx
│   ├── ai-assistant.tsx
│   ├── category-select.tsx
│   └── tag-input.tsx

├── admin/                 # Admin dashboard components
│   ├── user-table.tsx
│   ├── role-manager.tsx
│   ├── security-log-table.tsx
│   └── stats-cards.tsx

├── dashboard/             # Dashboard layouts
│   ├── sidebar.tsx
│   ├── header.tsx
│   └── mobile-nav.tsx

├── marketing/             # Marketing components
│   ├── hero.tsx
│   ├── features.tsx
│   ├── pricing-cards.tsx
│   ├── testimonials.tsx
│   ├── faq.tsx
│   ├── footer.tsx
│   └── navbar.tsx

├── changelog/             # Changelog components
│   ├── changelog-card.tsx
│   └── changelog-editor.tsx

├── sections/              # Page sections
│   └── contact-section.tsx

├── icons/                 # Custom icon components
│   └── logo.tsx

└── providers/             # Client-side providers wrapper
    └── client-providers.tsx

/src/db - Database Layer

Database schema and configuration using Drizzle ORM:

db/
├── schema/                # Drizzle schema definitions
│   ├── auth.ts           # Users, sessions, accounts
│   ├── blog.ts           # Posts, categories, tags
│   ├── subscription.ts   # Plans, subscriptions
│   ├── email.ts          # Email templates
│   ├── testimonials.ts   # Testimonials
│   ├── faqs.ts           # FAQs
│   ├── changelog.ts      # Changelog entries
│   └── security.ts       # Audit logs

├── schema.ts              # Combined schema export
└── index.ts               # Database instance

Note: Type Safety: Drizzle provides full TypeScript support. All database operations are type-safe!

/src/lib - Utilities & Libraries

Core utilities, configurations, and helper functions:

lib/
├── auth.ts                # Better Auth configuration
├── auth-client.ts         # Client-side auth helpers
├── auth-guard.tsx         # Route protection HOC
├── auth-redirect.tsx      # Redirect logic
├── requireAuth.ts         # Server-side auth check
├── adminUtils.ts          # Admin role utilities

├── stripe/                # Stripe integration
│   ├── index.ts          # Stripe client
│   ├── subscription.ts   # Subscription helpers
│   ├── webhook.ts        # Webhook handlers
│   └── checkout.ts       # Checkout session creation

├── email/                 # Email system
│   ├── index.ts          # Email service factory
│   ├── nodemailer.ts     # SMTP provider
│   ├── resend.ts         # Resend provider
│   ├── sendgrid.ts       # SendGrid provider
│   ├── mailgun.ts        # Mailgun provider
│   └── templates/        # Email templates

├── validations/           # Zod schemas
│   └── blog.ts           # Blog validation schemas

├── ai.ts                  # AI integration (OpenRouter)
├── blog.ts                # Blog utilities
├── blog-client.ts         # Client-side blog helpers
├── blog-likes.ts          # Blog like system
├── utils.ts               # General utilities (cn, etc.)
├── seo.ts                 # SEO metadata generation
├── rate-limit.ts          # Rate limiting logic
├── security-audit.ts      # Security logging
├── html-utils.ts          # HTML sanitization (DOMPurify)
├── page-titles.ts         # Page title generation
├── image-metadata.ts      # Image processing
└── uploadthing-client.ts  # Upload client config

/src/hooks - Custom React Hooks

Reusable React hooks for common functionality:

hooks/
├── use-blog.ts            # Blog data fetching
├── use-user.ts            # User data
├── use-subscription.ts    # Subscription status
├── use-is-mobile.ts       # Responsive design
└── ...                    # More hooks

/src/stores - State Management

Zustand stores for global state:

stores/
├── use-sidebar-store.ts   # Sidebar collapse state
├── use-theme-store.ts     # Theme preferences
└── ...                    # More stores

/src/providers - React Context Providers

Context providers for app-wide functionality:

providers/
├── query-provider.tsx     # TanStack Query setup
├── theme-provider.tsx     # next-themes provider
└── auth-provider.tsx      # Session provider

/src/config - Configuration

Application configuration files:

config/
├── site.ts                # Site metadata
├── navigation.ts          # Navigation menus
└── ...                    # Other configs

/public - Static Assets

Static files served directly:

public/
├── images/                # Images and graphics
├── favicon.ico            # Site favicon
└── ...                    # Other static assets

/scripts - Automation Scripts

Utility scripts for setup and maintenance:

scripts/
├── setup.ts               # Automated project setup
├── promote-first-admin.ts # Admin promotion
├── setup-subscription-plans.ts # Seed plans
├── seed-blog.ts           # Seed blog data
├── seed-testimonials.ts   # Seed testimonials
├── seed-email-templates.ts # Seed email templates
└── test-results-summary.md # Test documentation

/e2e - End-to-End Tests

Playwright tests for critical user flows:

e2e/
├── 01-security-headers.spec.ts
├── 02-authentication.spec.ts
├── 03-authorization.spec.ts
├── 04-xss-protection.spec.ts
├── 05-file-upload-security.spec.ts
├── 06-blog.spec.ts
├── 07-admin.spec.ts
├── 08-payments.spec.ts
├── 09-waitlist.spec.ts
├── 10-user-settings.spec.ts
├── 11-public-pages.spec.ts
├── 99-rate-limiting.spec.ts
├── fixtures/
│   ├── auth.setup.ts      # Generates Playwright storageState files
│   └── seed-test-users.ts # Creates test users in the DB
└── helpers/
    └── test-utils.ts      # Shared test helpers

/drizzle - Database Migrations

Migration files and snapshots:

drizzle/
├── migrations/            # SQL migration files
└── meta/                  # Migration metadata

Key Files

Configuration Files

FilePurpose
next.config.tsNext.js configuration with security headers
tailwind.config.tsTailwind CSS configuration
tsconfig.jsonTypeScript configuration
drizzle.config.tsDrizzle ORM configuration
playwright.config.tsE2E test configuration
components.jsonshadcn/ui configuration
.env.exampleEnvironment variable template
package.jsonDependencies and scripts

Root Layout Files

FilePurpose
src/app/layout.tsxRoot layout with providers
src/app/globals.cssGlobal styles and Tailwind imports
src/app/page.tsxHomepage
src/middleware.tsNext.js middleware (if exists)

File Naming Conventions

The project follows these naming conventions:

Components

  • PascalCase for component files: UserTable.tsx, BlogCard.tsx
  • kebab-case for directories: blog-editor/, user-settings/

Routes

  • kebab-case for route directories: sign-in/, forgot-password/
  • Special Next.js files: page.tsx, layout.tsx, loading.tsx, error.tsx

Utilities & Hooks

  • camelCase for utility files: blogUtils.ts, formatDate.ts
  • use- prefix for hooks: use-blog.ts, use-user.ts

API Routes

  • kebab-case for directories
  • route.ts for API handlers

Architecture Patterns

Server vs Client Components

The starter kit uses React Server Components (RSC) by default:

  • Server Components (default): Fetch data on the server, no client JavaScript
  • Client Components ("use client"): Interactive components with state/effects
// Server Component (default)
// app/blog/page.tsx
export default async function BlogPage() {
  const posts = await db.query.posts.findMany();
  return <BlogList posts={posts} />;
}

// Client Component
// components/blog-card.tsx
("use client");
export function BlogCard({ post }) {
  const [liked, setLiked] = useState(false);
  // ... interactive logic
}

Data Fetching Patterns

  • Server Components: Direct database queries with Drizzle
  • Client Components: TanStack Query for API calls
  • API Routes: For mutations and client-side data fetching

Authentication Flow

Client Request

Middleware (optional)

Auth Guard (requireAuth, AuthGuard)

Better Auth Session Check

Role Validation (isAdmin, isUser)

Component/Page Render

Common Patterns

Protected Routes

Server-side protection:

// app/dashboard/admin/page.tsx
import { requireAuth } from "@/lib/requireAuth";

export default async function AdminPage() {
  const session = await requireAuth("admin");
  // Only admin users reach here
}

Client-side protection:

// components/protected-content.tsx
"use client";
import { AuthGuard } from "@/lib/auth-guard";

export function ProtectedContent() {
  return (
    <AuthGuard allowedRoles={["admin"]}>
      {/* Content only for admins */}
    </AuthGuard>
  );
}

API Routes with Auth

// app/api/blog/route.ts
import { auth } from "@/lib/auth";
import { NextRequest, NextResponse } from "next/server";

export async function POST(request: NextRequest) {
  const session = await auth.api.getSession({
    headers: request.headers,
  });

  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  // Handle authenticated request
}

Database Queries

import { db } from "@/db";
import { posts } from "@/db/schema";
import { eq } from "drizzle-orm";

// Select
const allPosts = await db.query.posts.findMany();

// Select with filter
const post = await db.query.posts.findFirst({
  where: eq(posts.id, postId),
});

// Insert
await db.insert(posts).values({
  title: "New Post",
  content: "Content here",
});

// Update
await db.update(posts).set({ title: "Updated" }).where(eq(posts.id, postId));

// Delete
await db.delete(posts).where(eq(posts.id, postId));

Extending the Starter Kit

Adding a New Feature

  1. Create database schema in /src/db/schema/
  2. Push schema with pnpm db:push
  3. Create API routes in /src/app/api/
  4. Build UI components in /src/components/
  5. Add pages in /src/app/
  6. Update navigation if needed

Adding a New Page

# Create route directory
mkdir -p src/app/(marketing)/new-page

# Create page component
touch src/app/(marketing)/new-page/page.tsx

Adding a New API Route

# Create API directory
mkdir -p src/app/api/new-endpoint

# Create route handler
touch src/app/api/new-endpoint/route.ts

Next Steps

On this page