Mock API
How the server routes and mock data layer work, and how to replace them with a real backend.
How Server Routes Work
Haze Dashboard uses Nuxt's built-in server engine (Nitro) to serve mock API routes. Files in the server/api/ directory automatically become API endpoints. The filename determines the URL and HTTP method:
| File | Method | URL |
|---|---|---|
| server/api/orders.get.ts | GET | /api/orders |
| server/api/orders.post.ts | POST | /api/orders |
| server/api/orders/[id].get.ts | GET | /api/orders/123 |
| server/api/dashboard/overview.get.ts | GET | /api/dashboard/overview |
Pagination Utility
All list endpoints use a shared paginate() function from server/utils/pagination.ts. It accepts query parameters for pagination, search, filtering, and sorting:
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Current page number |
| per_page | number | 10 | Items per page (max 100) |
| search | string | — | Search term (matches against specified fields, supports nested paths like customer.name) |
| status | string | — | Filter by status field |
| sort | string | — | Field name to sort by |
| order | string | desc | Sort direction: asc or desc |
Response Format
All paginated endpoints return a consistent response structure:
{
"data": [
{ "id": 1, "orderNumber": "ORD-001", "status": "active", "total": 245.00 },
{ "id": 2, "orderNumber": "ORD-002", "status": "pending", "total": 189.50 }
],
"meta": {
"total": 248,
"page": 1,
"perPage": 10,
"lastPage": 25
}
} The meta object provides everything needed to render pagination controls.
Anatomy of a Server Route
Here is a typical list endpoint. It imports JSON data and passes it through the pagination utility:
// server/api/orders.get.ts
import orders from '../data/orders.json'
import { paginate } from '../utils/pagination'
export default defineEventHandler((event) => {
return paginate(event, orders, ['orderNumber', 'customer.name', 'customer.email'])
}) The third argument to paginate() specifies which fields to search when the search parameter is provided. Nested fields like customer.name are supported using dot notation.
Mock Datasets
All mock data lives in server/data/ as JSON files:
| File | Records | Used By |
|---|---|---|
| orders.json | Orders list | /orders, /api/orders |
| products.json | Product catalog | /products, /api/products |
| customers.json | Customer records | /customers, /api/customers |
| invoices.json | Invoice records | /invoices, /api/invoices |
| dashboard-*.json | Dashboard data | 5 dashboard variants |
| chat-messages.json, mail.json, kanban.json, etc. | App data | Chat, Mail, Kanban, Calendar, Files |
Adding a New Resource
To add a new API resource (e.g., tasks), follow these steps:
1. Create the data file:
// server/data/tasks.json
[
{ "id": 1, "title": "Review pull request", "status": "pending", "priority": "high" },
{ "id": 2, "title": "Update documentation", "status": "in_progress", "priority": "medium" },
{ "id": 3, "title": "Fix navigation bug", "status": "completed", "priority": "high" }
]2. Create the API route handler:
// server/api/tasks.get.ts
import tasks from '../data/tasks.json'
import { paginate } from '../utils/pagination'
export default defineEventHandler((event) => {
return paginate(event, tasks, ['title'])
}) The endpoint is immediately available at /api/tasks with full pagination, search, and filter support.
Replacing with a Real API
When you connect a real backend (Laravel, Django, Express, etc.), you have two options:
- Option A: Replace server routes — Update the handlers in
server/api/to proxy requests to your real backend using$fetchorproxyRequest. - Option B: Point useFetch directly — Change the
useFetch('/api/orders')calls in page components to point to your external API URL. Delete the server routes you no longer need.
The key requirement is that your real API returns the same { data: [], meta: {} } response format, or you update the page components to handle the new shape.
Tip
The mock API routes work in production too — Nitro bundles them as serverless functions on platforms like Vercel and Cloudflare, or as Node.js endpoints on a traditional server. This means your demo stays fully functional when deployed.
Next Steps
Learn about mock authentication in the Authentication guide, or see how to add new pages that consume these API routes.