GitHunt

Nuxt 4 Boilerplate

A modern, production-ready Nuxt 4 boilerplate with authentication, dashboard navigation, and a clean dark theme design system.

๐Ÿณ Docker Ready: Full Docker support with PostgreSQL and Adminer. See DOCKER.md for complete guide.

โœจ Features

๐ŸŽจ Modern Design System

  • Dark Theme: Professional dark color scheme with purple gradient accents
  • Responsive: Mobile-first design that works on all screen sizes
  • Customizable: Centralized theme configuration in /config/theme.ts
  • Smooth Animations: Polished micro-interactions and transitions

๐Ÿ” Authentication System

  • JWT-based: Secure authentication with HTTP-only cookies
  • Protected Routes: Middleware-based route protection
  • Login/Register: Pre-built authentication pages
  • User Management: Profile and logout functionality

๐Ÿงญ Advanced Navigation

  • Public Navbar: Clean marketing navbar with mobile drawer
  • Dashboard Sidebar: Professional sidebar with nested menu support
  • Config-Driven: Easy to add/remove menu items via configuration
  • Auto-Active States: Highlights current route and auto-expands parent items
  • Mobile Optimized: Drawer pattern for mobile navigation

๐Ÿ› ๏ธ Technical Stack

  • Nuxt 4: Latest Nuxt with all modern features
  • Vue 3: Composition API with <script setup>
  • TypeScript: Fully typed codebase
  • Nuxt UI: Beautiful UI components
  • Drizzle ORM: Type-safe database queries
  • PostgreSQL: Production-ready database
  • Tailwind CSS: Utility-first styling

๐Ÿ“ฆ Component Library

  • Modular Components: Reusable UI components in /components/ui/
  • Layout Components: Navigation and layout components
  • Auth Components: Authentication-specific components
  • Demo Pages: Example dashboard pages with nested routes

๐Ÿš€ Quick Start

Prerequisites

  • Node.js 22+
  • pnpm (recommended) or npm
  • Docker & Docker Compose (for Docker setup)

Option 1: Local Development

Installation

  1. Clone the repository
git clone <your-repo-url>
cd nuxt-boilerplate
  1. Install dependencies
pnpm install
  1. Set up environment variables
cp .env.example .env

Edit .env and configure:

DATABASE_URL="postgresql://postgres:postgres@localhost:5433/nuxt_boilerplate"
JWT_SECRET="your-super-secret-jwt-key-change-this"
  1. Start PostgreSQL with Docker
docker compose up postgres -d
  1. Run database migrations
pnpm db:push
  1. Start development server
pnpm dev

Open http://localhost:3000 in your browser.

Option 2: Full Docker Setup ๐Ÿณ

Run the entire application stack (App + PostgreSQL + Adminer) with Docker:

  1. Clone and configure
git clone <your-repo-url>
cd nuxt-boilerplate
cp .env.example .env
  1. Build and start all services
docker compose up --build

This will start:

  1. Access Adminer
    Open http://localhost:8080 and login with:
  • System: PostgreSQL
  • Server: postgres
  • Username: postgres
  • Password: postgres
  • Database: nuxt_boilerplate
  1. Stop services
docker compose down
  1. Stop and remove volumes (clears database)
docker compose down -v

Docker Commands

# Start only database and Adminer
docker compose up postgres adminer -d

# Start only the app (requires DB running)
docker compose up app

# View logs
docker compose logs -f app

# Rebuild app after code changes
docker compose up --build app

# Execute commands in running container
docker compose exec app pnpm db:push
docker compose exec app sh

๐Ÿ“ Project Structure

nuxt-boilerplate/
โ”œโ”€โ”€ components/
โ”‚   โ”œโ”€โ”€ layout/              # Navigation components
โ”‚   โ”‚   โ”œโ”€โ”€ AppNavbar.vue
โ”‚   โ”‚   โ”œโ”€โ”€ DashboardSidebar.vue
โ”‚   โ”‚   โ”œโ”€โ”€ DashboardMenuItem.vue
โ”‚   โ”‚   โ””โ”€โ”€ MobileDrawer.vue
โ”‚   โ”œโ”€โ”€ ui/                  # Reusable UI components
โ”‚   โ”‚   โ”œโ”€โ”€ UiButton.vue
โ”‚   โ”‚   โ”œโ”€โ”€ UiCard.vue
โ”‚   โ”‚   โ””โ”€โ”€ UiInput.vue
โ”‚   โ””โ”€โ”€ auth/                # Auth-specific components
โ”‚       โ”œโ”€โ”€ AuthWrapper.vue
โ”‚       โ”œโ”€โ”€ AuthPanelContent.vue
โ”‚       โ””โ”€โ”€ AuthFormHeader.vue
โ”‚
โ”œโ”€โ”€ pages/
โ”‚   โ”œโ”€โ”€ index.vue            # Landing page
โ”‚   โ”œโ”€โ”€ login.vue            # Login page
โ”‚   โ”œโ”€โ”€ register.vue         # Register page
โ”‚   โ””โ”€โ”€ dashboard/           # Dashboard pages
โ”‚       โ”œโ”€โ”€ index.vue
โ”‚       โ”œโ”€โ”€ settings.vue
โ”‚       โ”œโ”€โ”€ analytics/
โ”‚       โ””โ”€โ”€ users/
โ”‚
โ”œโ”€โ”€ server/
โ”‚   โ”œโ”€โ”€ api/                 # API routes
โ”‚   โ”‚   โ”œโ”€โ”€ auth/
โ”‚   โ”‚   โ””โ”€โ”€ user/
โ”‚   โ”œโ”€โ”€ middleware/          # Server middleware
โ”‚   โ””โ”€โ”€ utils/               # Server utilities
โ”‚
โ”œโ”€โ”€ config/
โ”‚   โ”œโ”€โ”€ navigation.ts        # Navigation configuration
โ”‚   โ”œโ”€โ”€ theme.ts             # Theme configuration
โ”‚   โ””โ”€โ”€ NAVIGATION.md        # Navigation docs
โ”‚
โ”œโ”€โ”€ composables/
โ”‚   โ””โ”€โ”€ useAuth.ts           # Auth composable
โ”‚
โ”œโ”€โ”€ middleware/
โ”‚   โ””โ”€โ”€ auth.ts              # Auth middleware
โ”‚
โ”œโ”€โ”€ db/
โ”‚   โ”œโ”€โ”€ index.ts             # Database connection
โ”‚   โ””โ”€โ”€ schema.ts            # Database schema
โ”‚
โ””โ”€โ”€ app.vue                  # Root component

๐ŸŽจ Customization

Theme Configuration

Edit /config/theme.ts to customize the light/dark tokens that power the global CSS variables:

export const themeConfig = {
  storageKey: 'app-theme',
  cookieName: 'app-theme',
  themes: {
    light: {
      page: '#f6f8fb',
      surface: '#ffffff',
      text: '#0f172a',
      accent: '#6366f1',
      // ...extend tokens as needed
    },
    dark: {
      page: '#050a14',
      surface: '#0f172a',
      text: '#e5e7eb',
      accent: '#818cf8',
      // ...extend tokens as needed
    }
  }
}

Theme System

  • Toggle: Drop <ThemeToggle /> anywhere (already wired into the public navbar and dashboard sidebar). Add with-label to show text.
  • Composable: const { theme, isDark, toggleTheme, setTheme } = useTheme() for programmatic control.
  • Persistence & defaults: Preference is stored in both localStorage and a app-theme cookie; first visit falls back to prefers-color-scheme with an inline pre-paint script to avoid flashes.
  • Classes & variables: The active theme class (light/dark) lives on <html> and drives the CSS variables like --bg-page, --surface, --text-primary, --accent, etc. Use these in component styles for theme-safe colors.
  • Extending tokens: Add new keys under themeConfig.themes.light/dark and consume them via CSS variables or by extending the variable list in plugins/theme.ts if you introduce new tokens.

Edit /config/navigation.ts to add/remove menu items:

// Public navbar links
export const publicNavLinks: NavLink[] = [
  { label: 'Features', to: '/#features' },
  { label: 'Pricing', to: '/#pricing' },
]

// Dashboard sidebar menu
export const dashboardMenuItems: DashboardMenuItem[] = [
  {
    label: 'Analytics',
    icon: 'i-heroicons-chart-bar',
    children: [
      { label: 'Reports', to: '/dashboard/analytics/reports', icon: 'i-heroicons-document-text' },
    ],
  },
]

Adding New Pages

  1. Create the page file
touch pages/dashboard/your-page.vue
  1. Add to navigation config
// In config/navigation.ts
{
  label: 'Your Page',
  to: '/dashboard/your-page',
  icon: 'i-heroicons-sparkles',
}

That's it! The navigation will automatically include your new page.

๐Ÿ” Authentication

Register a New User

const { register } = useAuth()

await register({
  email: 'user@example.com',
  password: 'securepassword'
})

Login

const { login } = useAuth()

await login({
  email: 'user@example.com',
  password: 'securepassword'
})

Protect Routes

Add middleware: 'auth' to your page:

<script setup lang="ts">
definePageMeta({
  middleware: 'auth'
})
</script>

Access Current User

const { user } = useAuth()

console.log(user.value?.email)

๐Ÿงช Database

Schema

The database schema is defined in /db/schema.ts using Drizzle ORM:

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  email: varchar('email', { length: 255 }).notNull().unique(),
  password: varchar('password', { length: 255 }).notNull(),
  createdAt: timestamp('created_at').defaultNow(),
})

Migrations

Push schema changes to database:

pnpm db:push

Generate migrations:

pnpm db:generate

๐Ÿ“ฑ Responsive Design

Breakpoints

  • Mobile: < 768px

    • Drawer navigation
    • Stacked layouts
  • Tablet: 768px - 1023px

    • Full navbar
    • Drawer for dashboard
  • Desktop: โ‰ฅ 1024px

    • Full navbar
    • Fixed sidebar for dashboard

Mobile Navigation

Both public and dashboard layouts use a professional drawer pattern on mobile:

  • Smooth slide-in animation
  • Dark backdrop with blur
  • Close triggers: X button, backdrop click, escape key, route change
  • Body scroll prevention

๐Ÿš€ Production

Local Build

pnpm build

Preview

pnpm preview

Docker Production Deployment

  1. Set production environment variables

Create a .env.production file:

DATABASE_URL="postgresql://postgres:secure_password@postgres:5432/nuxt_boilerplate"
JWT_SECRET="production-secret-min-32-characters-long"
NODE_ENV="production"
  1. Build and deploy with Docker
# Build the production image
docker compose build app

# Start all services in production mode
docker compose up -d

# Check logs
docker compose logs -f app
  1. Health checks

The containers include health checks for:

  • PostgreSQL: Automatic readiness checks
  • App: Waits for database to be ready before starting

Docker Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                         โ”‚
โ”‚         Docker Compose Stack            โ”‚
โ”‚                                         โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚    Nuxt App (Port 3000)          โ”‚  โ”‚
โ”‚  โ”‚    - Built with Node 20 Alpine    โ”‚  โ”‚
โ”‚  โ”‚    - Production optimized         โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                 โ”‚                       โ”‚
โ”‚                 โ”‚ connects to           โ”‚
โ”‚                 โ†“                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚   PostgreSQL 16 (Port 5433)      โ”‚  โ”‚
โ”‚  โ”‚   - Persistent volume             โ”‚  โ”‚
โ”‚  โ”‚   - Health checks enabled         โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                 โ”‚                       โ”‚
โ”‚                 โ”‚ managed by            โ”‚
โ”‚                 โ†“                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚   Adminer (Port 8080)            โ”‚  โ”‚
โ”‚  โ”‚   - Web-based DB admin            โ”‚  โ”‚
โ”‚  โ”‚   - No setup required             โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Environment Variables

Make sure to set these in production:

DATABASE_URL="your-production-database-url"
JWT_SECRET="your-production-jwt-secret"
NODE_ENV="production"

๐Ÿ“š Documentation

  • ๐Ÿณ Docker Guide: Complete Docker setup and deployment - DOCKER.md
  • Navigation System: See /config/NAVIGATION.md
  • Navigation Refactoring: See /NAVIGATION_REFACTOR.md
  • Theme Configuration: See /config/README.md

๐ŸŽฏ Key Concepts

Component Naming Convention

Nuxt auto-imports components with folder prefixes:

components/layout/AppNavbar.vue     โ†’ <LayoutAppNavbar>
components/ui/UiButton.vue          โ†’ <UiButton>
components/auth/AuthWrapper.vue     โ†’ <AuthWrapper>

Route Middleware

  • Global: Applied to all routes (defined in nuxt.config.ts)
  • Named: Applied via definePageMeta({ middleware: 'auth' })
  • Anonymous: Inline functions in definePageMeta

Composables

Reusable reactive logic in /composables/:

  • useAuth(): Authentication state and methods
  • Auto-imported throughout the app

๐Ÿ› ๏ธ Development

Code Quality

# Type checking
pnpm typecheck

# Linting
pnpm lint

# Formatting (if configured)
pnpm format

VS Code

Recommended extensions:

  • Vue - Official
  • Tailwind CSS IntelliSense
  • ESLint
  • TypeScript Vue Plugin (Volar)

๐Ÿ“„ License

MIT

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


Built with Nuxt 4 โ€ข Documentation โ€ข Nuxt UI

binczakmartin/nuxt-boilerplate | GitHunt