Skip to content

binczakmartin/nuxt-boilerplate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

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.

Navigation Menu

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