Next.js Version โ
HaloLight Next.js version is built on Next.js 14 App Router with React 18 + TypeScript.
Live Preview: https://halolight.h7ml.cn/
GitHub: https://github.com/halolight/halolight
Features โ
- ๐๏ธ Next.js 14 App Router - Server components & streaming rendering
- โก Zustand State Management - Lightweight state management solution
- ๐จ Theme System - 11 skins, dark/light mode, View Transitions
- ๐ Authentication System - Complete login/register/password recovery flow
- ๐ Dashboard - Data visualization & business management
- ๐ก๏ธ Permission Control - RBAC fine-grained permission management
- ๐ Multi-Tab Navigation - Tab bar management
- โ Command Palette - Keyboard shortcut navigation
Tech Stack โ
| Technology | Version | Description |
|---|---|---|
| Next.js | 14.x | React full-stack framework (App Router) |
| React | 18.x | UI library |
| TypeScript | 5.x | Type safety |
| Tailwind CSS | 4.x | Atomic CSS |
| shadcn/ui | latest | UI component library (28 components) |
| Zustand | 5.x | State management (6 Stores) |
| TanStack Query | 5.x | Server state |
| React Hook Form | 7.x | Form handling |
| Zod | 4.x | Data validation |
| react-grid-layout | 1.x | Drag-and-drop layout |
| Recharts | 3.x | Chart visualization |
| Framer Motion | 12.x | Animation effects |
| Mock.js | 1.x | Data mocking |
| next-pwa | 5.x | PWA support |
Core Features โ
- Configurable Dashboard - 9 widget types, drag-and-drop layout, responsive adaptation
- Multi-Tab Navigation - Browser-style tabs, context menu, state caching
- Permission System - RBAC permission control, route guards, permission components
- Theme System - 11 skins, dark/light mode, View Transitions
- Multi-Account Switching - Quick account switch, remember login state
- Command Palette - Keyboard shortcuts (โK), global search
- Real-time Notifications - WebSocket push, notification center
Directory Structure โ
halolight/
โโโ src/
โ โโโ app/ # App Router pages
โ โ โโโ (auth)/ # Auth route group
โ โ โ โโโ login/ # Login
โ โ โ โโโ register/ # Register
โ โ โ โโโ forgot-password/ # Forgot password
โ โ โ โโโ reset-password/ # Reset password
โ โ โ โโโ layout.tsx # Auth layout
โ โ โโโ (dashboard)/ # Dashboard route group
โ โ โ โโโ page.tsx # Dashboard home (configurable)
โ โ โ โโโ accounts/ # Account & permissions
โ โ โ โโโ analytics/ # Analytics
โ โ โ โโโ calendar/ # Calendar
โ โ โ โโโ docs/ # Help docs
โ โ โ โโโ documents/ # Document management
โ โ โ โโโ files/ # File storage
โ โ โ โโโ messages/ # Message center
โ โ โ โโโ notifications/ # Notification center
โ โ โ โโโ profile/ # User profile
โ โ โ โโโ users/ # User management
โ โ โ โโโ settings/ # System settings
โ โ โ โ โโโ teams/ # Team management
โ โ โ โ โโโ roles/ # Role management
โ โ โ โโโ layout.tsx # Dashboard layout
โ โ โโโ (legal)/ # Legal route group
โ โ โ โโโ privacy/ # Privacy policy
โ โ โ โโโ terms/ # Terms of service
โ โ โ โโโ layout.tsx
โ โ โโโ layout.tsx # Root layout
โ โ โโโ error.tsx # Error page
โ โ โโโ not-found.tsx # 404 page
โ โโโ components/
โ โ โโโ ui/ # shadcn/ui components (28)
โ โ โโโ layout/ # Layout components (11)
โ โ โ โโโ admin-layout.tsx # Admin layout
โ โ โ โโโ sidebar.tsx # Collapsible sidebar
โ โ โ โโโ header.tsx # Header (notifications/errors/user menu)
โ โ โ โโโ footer.tsx # Footer
โ โ โ โโโ tab-bar.tsx # Multi-tab navigation
โ โ โ โโโ command-menu.tsx # Command palette (โK)
โ โ โ โโโ quick-settings.tsx # UI settings panel
โ โ โ โโโ theme-toggle.tsx # Theme toggle
โ โ โ โโโ pending-overlay.tsx # Loading overlay
โ โ โโโ dashboard/ # Dashboard components
โ โ โ โโโ configurable-dashboard.tsx # Configurable dashboard
โ โ โ โโโ charts.tsx # Chart components
โ โ โ โโโ stats-card.tsx # Stats card
โ โ โ โโโ recent-activity.tsx # Recent activity
โ โ โโโ shared/ # Shared components
โ โโโ hooks/ # React Hooks (15)
โ โ โโโ use-users.ts # User CRUD
โ โ โโโ use-teams.ts # Team management
โ โ โโโ use-messages.ts # Message management
โ โ โโโ use-notifications.ts # Notification management
โ โ โโโ use-calendar.ts # Calendar data
โ โ โโโ use-documents.ts # Document management
โ โ โโโ use-files.ts # File management
โ โ โโโ use-dashboard.ts # Dashboard state
โ โ โโโ use-dashboard-data.ts # Dashboard data Hook collection
โ โ โโโ use-chart-palette.ts # Chart palette (theme-aware)
โ โ โโโ use-action-mutation.ts # Server Action wrapper
โ โ โโโ use-keep-alive.tsx # Page state caching
โ โ โโโ use-tdk.ts # TDK management
โ โ โโโ use-title.ts # Page title
โ โโโ stores/ # Zustand Stores (6)
โ โ โโโ auth-store.ts # Auth state (with multi-account)
โ โ โโโ ui-settings-store.ts # UI settings
โ โ โโโ dashboard-store.ts # Dashboard state
โ โ โโโ navigation-store.ts # Navigation state
โ โ โโโ tabs-store.ts # Tab state
โ โ โโโ error-store.ts # Error collection
โ โโโ providers/ # React Providers (8)
โ โ โโโ app-providers.tsx # Provider aggregation
โ โ โโโ auth-provider.tsx # Auth Provider
โ โ โโโ theme-provider.tsx # Theme Provider
โ โ โโโ query-provider.tsx # TanStack Query
โ โ โโโ error-provider.tsx # Error handling
โ โ โโโ permission-provider.tsx # Permission check
โ โ โโโ websocket-provider.tsx # WebSocket real-time notifications
โ โ โโโ keep-alive-provider.tsx # Page keep-alive
โ โโโ actions/ # Server Actions
โ โโโ config/ # Configuration
โ โ โโโ routes.ts # Routes & permissions config
โ โ โโโ tdk.ts # TDK config
โ โโโ lib/ # Utility library
โ โ โโโ api/ # API client
โ โโโ mock/ # Mock data (9 modules)
โ โโโ middleware.ts # Middleware (auth + security headers)
โโโ public/
โ โโโ manifest.json # PWA manifest
โ โโโ sw.js # Service Worker
โ โโโ icons/ # PWA icons (8 sizes)
โ โโโ screenshots/ # PWA screenshots
โ โโโ fonts/ # Self-hosted fonts
โโโ next.config.mjs # Next.js + PWA config
โโโ tailwind.config.js
โโโ tsconfig.json
โโโ package.jsonQuick Start โ
Environment Requirements โ
- Node.js >= 18.0.0
- pnpm >= 9.x
Installation โ
git clone https://github.com/halolight/halolight.git
cd halolight
pnpm installEnvironment Variables โ
cp .env.example .env.local# .env.local example
NEXT_PUBLIC_API_URL=/api
NEXT_PUBLIC_MOCK=true # Enable Mock data
NEXT_PUBLIC_DEMO_EMAIL=admin@halolight.h7ml.cn
NEXT_PUBLIC_DEMO_PASSWORD=123456
NEXT_PUBLIC_SHOW_DEMO_HINT=false
NEXT_PUBLIC_WS_URL= # WebSocket URL
NEXT_PUBLIC_APP_TITLE=Admin Pro
NEXT_PUBLIC_BRAND_NAME=HalolightStart Development โ
pnpm devVisit http://localhost:3000
Build for Production โ
pnpm build
pnpm startDemo Account โ
| Role | Password | |
|---|---|---|
| Admin | admin@halolight.h7ml.cn | 123456 |
| User | user@halolight.h7ml.cn | 123456 |
Core Functionality โ
1. State Management (Zustand) โ
// stores/auth-store.ts
interface AuthState {
user: AccountWithToken | null
accounts: AccountWithToken[] // Multi-account list
activeAccountId: string | null // Current account
login: (data: LoginRequest) => Promise<void>
register: (data: RegisterRequest) => Promise<void>
logout: () => Promise<void>
switchAccount: (accountId: string) => Promise<void> // Quick account switch
forgotPassword: (email: string) => Promise<void>
resetPassword: (token: string, password: string) => Promise<void>
checkAuth: () => Promise<void>
}
// Cookie-based token storage with "Remember me" support (7 days / 1 day)
Cookies.set("token", response.token, {
expires: data.remember ? 7 : 1,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
})2. Data Fetching (TanStack Query) โ
// hooks/use-users.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
export function useUsers() {
const queryClient = useQueryClient()
// Query user list
const { data, isLoading } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
})
// Create user
const createUser = useMutation({
mutationFn: createUserApi,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] })
},
})
return { data, isLoading, createUser }
}3. Permission Control โ
// Route permission config
export const ROUTE_PERMISSIONS: Record<string, Permission> = {
"/": "dashboard:view",
"/users": "users:view",
"/analytics": "analytics:view",
// ...
}
// Permission check
const { hasPermission } = usePermission()
if (hasPermission("users:delete")) {
// Show delete button
}// Permission guard component
<PermissionGuard permission="users:delete" fallback={<Disabled />}>
<DeleteButton />
</PermissionGuard>4. Draggable Dashboard โ
// Dashboard edit mode
const { isEditing, setIsEditing, addWidget, removeWidget, resetToDefault } = useDashboardStore()
// Responsive layout (columns auto-adapt)
// lg: 12 cols, md: 8 cols, sm: 4 cols, xs: 2 cols, mobile: 1 colSupports 9 widget types:
| Widget Type | Description | Data Source |
|---|---|---|
stats | Statistics card (4 metrics) | useDashboardStats |
chart-line | Line chart (visit trends) | useDashboardVisits |
chart-bar | Bar chart (sales statistics) | useDashboardSales |
chart-pie | Pie chart (traffic distribution) | useDashboardPie |
recent-users | Recent users list | useDashboardUsers |
notifications | Notifications list | useDashboardNotifications |
tasks | Todo tasks | useDashboardTasks |
calendar | Today's schedule | useDashboardCalendar |
quick-actions | Quick action shortcuts | Static config |
Theme System โ
Skin Presets โ
Supports 11 skin presets with live preview and smooth transition animations:
| Preset | Name | Description |
|---|---|---|
default | Shadcn ยท Neutral | Official default neutral colors |
blue | Shadcn ยท Blue | Blue primary + cool-toned charts |
emerald | Shadcn ยท Emerald | Fresh green, ideal for data display |
amber | Shadcn ยท Amber | Amber/orange, warm and vibrant |
violet | Shadcn ยท Violet | High-saturation purple, tech feel |
rose | Shadcn ยท Rose | Rose primary, contrasting charts |
teal | Shadcn ยท Teal | Teal primary, modern feel |
slate | Shadcn ยท Slate | Low-saturation gray-blue, utilitarian |
ocean | Legacy ยท Ocean Blue | Blue-green gradient |
sunset | Legacy ยท Sunset Orange | Orange-pink contrast |
aurora | Legacy ยท Aurora Green | Cyan-green + purple |
CSS Variables (OKLch) โ
/* Example variable definitions */
:root {
--background: 100% 0 0;
--foreground: 14.9% 0.017 285.75;
--primary: 51.1% 0.262 276.97;
--primary-foreground: 100% 0 0;
--muted: 96.4% 0.004 285.75;
--accent: 96.4% 0.004 285.75;
/* ... */
}Page Routes โ
| Path | Page | Permission |
|---|---|---|
/ | Redirect to dashboard | - |
/login | Login | Public |
/register | Register | Public |
/forgot-password | Forgot password | Public |
/reset-password | Reset password | Public |
/dashboard | Configurable dashboard | dashboard:view |
/accounts | Account & permissions | settings:view |
/analytics | Analytics | analytics:view |
/calendar | Calendar | calendar:view |
/documents | Document management | documents:view |
/files | File storage | files:view |
/messages | Message center | messages:view |
/notifications | Notification center | notifications:view |
/users | User management | users:view |
/settings | System settings | settings:view |
/settings/teams | Team settings | settings:view |
/settings/teams/roles | Role management | settings:view |
/profile | User profile | settings:view |
/docs | Help docs | documents:view |
/privacy | Privacy policy | Public |
/terms | Terms of service | Public |
Environment Variables โ
Configuration Example โ
cp .env.example .env.local# .env.local
NEXT_PUBLIC_API_URL=/api
NEXT_PUBLIC_MOCK=true
NEXT_PUBLIC_DEMO_EMAIL=admin@halolight.h7ml.cn
NEXT_PUBLIC_DEMO_PASSWORD=123456
NEXT_PUBLIC_SHOW_DEMO_HINT=false
NEXT_PUBLIC_WS_URL=
NEXT_PUBLIC_APP_TITLE=Admin Pro
NEXT_PUBLIC_BRAND_NAME=HalolightVariable Description โ
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_API_URL | API base path | /api |
NEXT_PUBLIC_MOCK | Enable Mock data | true |
NEXT_PUBLIC_DEMO_EMAIL | Demo account email | admin@halolight.h7ml.cn |
NEXT_PUBLIC_DEMO_PASSWORD | Demo account password | 123456 |
NEXT_PUBLIC_SHOW_DEMO_HINT | Show demo hint | false |
NEXT_PUBLIC_WS_URL | WebSocket URL | - |
NEXT_PUBLIC_APP_TITLE | Application title | Admin Pro |
NEXT_PUBLIC_BRAND_NAME | Brand name | Halolight |
Usage โ
// Use in client components
const apiUrl = process.env.NEXT_PUBLIC_API_URL
const isMock = process.env.NEXT_PUBLIC_MOCK === 'true'Common Commands โ
pnpm dev # Start development server
pnpm build # Production build
pnpm start # Preview production build
pnpm lint # Code linting
pnpm lint:fix # Auto fix
pnpm type-check # Type checking
pnpm test # Run tests
pnpm test:coverage # Test coverageTesting โ
pnpm test # Run tests (watch mode)
pnpm test:run # Single run
pnpm test:coverage # Coverage report
pnpm test:ui # Vitest UI interfaceTest Example โ
// __tests__/components/button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react'
import { Button } from '@/components/ui/button'
describe('Button Component', () => {
it('renders correctly', () => {
render(<Button>Click me</Button>)
expect(screen.getByText('Click me')).toBeInTheDocument()
})
it('handles click events', () => {
const handleClick = vi.fn()
render(<Button onClick={handleClick}>Click me</Button>)
fireEvent.click(screen.getByText('Click me'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
})Configuration โ
Next.js Configuration โ
// next.config.mjs
import withPWA from "next-pwa"
const nextConfig = {
// Package import optimization - reduce bundle size
experimental: {
optimizePackageImports: [
"@radix-ui/react-*",
"lucide-react",
"framer-motion",
"@tanstack/react-query",
"recharts",
"zustand",
],
},
// Remove console in production
compiler: {
removeConsole: { exclude: ["error", "warn"] },
},
// Disable source maps
productionBrowserSourceMaps: false,
// Image optimization
images: {
formats: ["image/avif", "image/webp"],
},
}
const pwaConfig = withPWA({
dest: "public",
register: true,
skipWaiting: true,
disable: process.env.NODE_ENV === "development",
})
export default pwaConfig(nextConfig)Deployment โ
Vercel (Recommended) โ
vercelDocker โ
FROM node:18-alpine
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
EXPOSE 3000
CMD ["pnpm", "start"]docker build -t halolight-nextjs .
docker run -p 3000:3000 halolight-nextjsOther Platforms โ
CI/CD โ
The project has a complete GitHub Actions CI workflow configured:
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm type-check
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm test:coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm build
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm audit --audit-level=highAdvanced Features โ
Multi-Tab Navigation โ
// stores/tabs-store.ts
interface Tab {
id: string
title: string
path: string
icon?: string
closable?: boolean // Home tab not closable
}
// Context menu features
- Refresh page
- Close tab
- Close others
- Close right tabs
- Close allPage State Caching (Keep-Alive) โ
// hooks/use-keep-alive.tsx
// Auto save/restore scroll position
useScrollRestore()
// Save form state
const [values, saveValues, clearCache] = useFormCache('filter-form', initialValues)
// Save custom state
const [state, setState] = useStateCache('my-key', initialValue)Command Palette (โK) โ
// components/layout/command-menu.tsx
// Supports keyboard quick navigation, theme switching, account switching, logout, etc.
Shortcuts:
- โK / Ctrl+K - Open command palette
- Search pages - Quick navigation to any page
- Switch theme - Toggle dark/light mode
- Switch account - Quick account switchingReal-time Notifications (WebSocket) โ
// providers/websocket-provider.tsx
const { status, lastMessage, sendMessage, reconnect } = useWebSocket()
// Listen for new notifications
useRealtimeNotifications((notification) => {
console.log('New notification:', notification)
})
// Connection status
status === 'Open' // Connected
status === 'Connecting' // Connecting
status === 'Closed' // DisconnectedPWA Support โ
// next.config.mjs
const pwaConfig = withPWA({
dest: "public",
register: true,
skipWaiting: true,
disable: process.env.NODE_ENV === "development",
runtimeCaching: [
// Font caching (1 year)
{ urlPattern: /\.(?:woff|woff2|ttf)$/i, handler: "CacheFirst" },
// Image caching (24 hours)
{ urlPattern: /\.(?:jpg|png|svg|webp)$/i, handler: "StaleWhileRevalidate" },
// Next.js static assets (1 year)
{ urlPattern: /\/_next\/static\/.+\.(js|css)$/i, handler: "CacheFirst" },
// Page data (1 hour)
{ urlPattern: /\/_next\/data\/.+\.json$/i, handler: "NetworkFirst" },
],
})Features:
- Offline Access - Service Worker caches static assets
- Install to Desktop - Supports Add to Home Screen
- Self-hosted Fonts - Inter + JetBrains Mono
- Icon Support - 8 sizes (72x72 ~ 512x512)
Performance Optimization โ
Image Optimization โ
// Use Next.js Image component
import Image from 'next/image'
<Image
src="/images/hero.png"
alt="Hero"
width={800}
height={600}
priority // Priority loading
placeholder="blur" // Blur placeholder
/>
// next.config.mjs
images: {
formats: ["image/avif", "image/webp"],
}Lazy Loading Components โ
// Dynamic import components
import dynamic from 'next/dynamic'
const DashboardChart = dynamic(
() => import('@/components/dashboard/chart'),
{
loading: () => <Skeleton />,
ssr: false // Disable SSR
}
)Preloading โ
// Route preloading
import Link from 'next/link'
<Link href="/dashboard" prefetch>
Dashboard
</Link>
// Data preloading
queryClient.prefetchQuery({
queryKey: ['users'],
queryFn: fetchUsers,
})Package Import Optimization โ
// next.config.mjs
experimental: {
optimizePackageImports: [
"@radix-ui/react-*",
"lucide-react",
"framer-motion",
"@tanstack/react-query",
"recharts",
"zustand",
],
}FAQ โ
Q: How to disable Mock data? โ
A: Set NEXT_PUBLIC_MOCK=false in .env.local and configure real API address.
NEXT_PUBLIC_MOCK=false
NEXT_PUBLIC_API_URL=https://api.example.comQ: How to add a new page? โ
A: Create a new directory and page.tsx file under src/app/(dashboard).
// src/app/(dashboard)/my-page/page.tsx
export default function MyPage() {
return <div>My Page</div>
}
// Add route permission
// src/config/routes.ts
export const ROUTE_PERMISSIONS = {
// ...
"/my-page": "my-page:view",
}Q: How to customize theme colors? โ
A: Modify CSS variables in tailwind.config.js.
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: {
DEFAULT: 'oklch(var(--primary))',
foreground: 'oklch(var(--primary-foreground))',
},
},
},
},
}/* app/globals.css */
:root {
--primary: 51.1% 0.262 276.97; /* Change to your color */
}Q: How to disable PWA? โ
A: Set disable: true in next.config.mjs.
const pwaConfig = withPWA({
dest: "public",
disable: true, // Disable PWA
})Q: How to deploy to static hosting platforms? โ
A: Configure static export mode.
// next.config.mjs
export default {
output: 'export',
images: {
unoptimized: true, // Need to disable image optimization for static export
},
}pnpm build
# Output to out/ directoryComparison with Other Versions โ
| Feature | Next.js | Vue | Angular |
|---|---|---|---|
| SSR/SSG | โ | โ (Nuxt) | โ (Universal) |
| State Management | Zustand | Pinia | Services + RxJS |
| Router | App Router | Vue Router | Angular Router |
| Build Tool | Next.js | Vite | esbuild + Vite |
| Component Library | shadcn/ui | shadcn-vue | Angular Material |
| Learning Curve | Medium | Low | High |
| Performance | Excellent | Excellent | Excellent |