File-System API
The File-System API is the simplest way to serve mock data. Just point to a directory and VitePress automatically serves files as API endpoints.
Overview
With File-System API, your directory structure becomes your API:
mock/
├── users.json → GET /api/users
├── posts/
│ └── index.json → GET /api/posts
└── products/
├── 1.json → GET /api/products/1
└── 2.json → GET /api/products/2Basic Setup
// vite.config.ts
import { defineConfig } from 'vite'
// import mockApi from '@ndriadev/vite-plugin-universal-api' //Default export
import { universalApi } from '@ndriadev/vite-plugin-universal-api' // Named export
export default defineConfig({
plugins: [
universalApi({
endpointPrefix: '/api',
fsDir: 'mock' // Points to ./mock directory
})
]
})File Lookup Strategy
When a request comes in, the plugin tries multiple strategies to find the file:
1. Exact File Match
Request: GET /api/users
Looks for: mock/users (exact match)2. Directory with index.json
Request: GET /api/posts
Looks for: mock/posts/index.json3. File with Extension
Request: GET /api/data
Looks for:
- mock/data.json
- mock/data.xml
- mock/data.txt
(any extension)Supported HTTP Methods
GET - Retrieve Data
GET /api/usersReturns the entire file content.
With Pagination:
GET /api/users?limit=10&skip=0&sortBy=name&order=ascWith Filters:
GET /api/users?status=active&minAge=18POST - Create or Query
Create new resource (file doesn't exist):
POST /api/users/123
Content-Type: application/json
{"name": "John", "email": "john@example.com"}Creates mock/users/123.json
Query existing data (file exists + pagination/filters):
POST /api/users?status=active&limit=10Returns filtered data without modifying the file.
PUT - Create or Replace
PUT /api/users/123
Content-Type: application/json
{"name": "John Updated"}- Creates file if doesn't exist (201)
- Replaces entire file if exists (200)
PATCH - Partial Update
Only works with JSON files.
Merge Patch:
PATCH /api/users/123
Content-Type: application/json
{"email": "newemail@example.com"}JSON Patch (RFC 6902):
PATCH /api/users/123
Content-Type: application/json-patch+json
[
{"op": "replace", "path": "/email", "value": "new@example.com"},
{"op": "add", "path": "/phone", "value": "555-1234"}
]DELETE - Remove Data
Delete entire file:
DELETE /api/users/123Partial delete (with filters on JSON arrays):
DELETE /api/users?status=inactiveRemoves matching items from array.
Pagination
Enable pagination in configuration:
universalApi({
endpointPrefix: '/api',
fsDir: 'mock',
pagination: {
GET: {
type: 'query-param',
limit: 'limit',
skip: 'skip',
sort: 'sortBy',
order: 'order'
}
}
})Usage:
GET /api/users?limit=10&skip=20&sortBy=name&order=descRequirements:
- ✅ File must contain JSON array
- ✅ Method must be GET, POST, HEAD, or DELETE
- ❌ Does NOT work with JSON objects or non-JSON files
Filters
Enable filtering in configuration:
universalApi({
filters: {
GET: {
type: 'query-param',
filters: [
{
key: 'status',
valueType: 'string',
comparison: 'eq'
},
{
key: 'minAge',
field: 'age',
valueType: 'number',
comparison: 'gte'
}
]
}
}
})Usage:
GET /api/users?status=active&minAge=18Comparison Operators:
eq- equalsneq- not equalsgt- greater thangte- greater than or equallt- less thanlte- less than or equalin- value in arraynin- value not in arraycontains- string contains (case-insensitive)
File Upload
Single file upload:
POST /api/documents/report
Content-Type: multipart/form-data
(file data)⚠️ Important: Only the FIRST file is written. Multiple files are not supported.
Examples
Simple JSON Data
// mock/users.json
[
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"status": "active"
},
{
"id": 2,
"name": "Jane Smith",
"email": "jane@example.com",
"status": "active"
}
]# Get all users
GET /api/users
# Get paginated users
GET /api/users?limit=10&skip=0
# Get active users only
GET /api/users?status=activeNested Resources
mock/
├── users/
│ ├── 1.json
│ ├── 2.json
│ └── 3.json
└── posts/
└── user-1/
├── 1.json
└── 2.jsonGET /api/users/1 → mock/users/1.json
GET /api/posts/user-1/1 → mock/posts/user-1/1.jsonBinary Files
mock/
├── images/
│ └── logo.png
└── documents/
└── report.pdfGET /api/images/logo → Returns logo.png
GET /api/documents/report → Returns report.pdfBest Practices
1. Organize by Resource
mock/
├── users/
├── posts/
├── products/
└── orders/2. Use index.json for Collections
mock/
└── users/
└── index.json # List of all users3. Individual Resources
mock/
└── users/
├── index.json # All users
├── 1.json # User 1
├── 2.json # User 2
└── 3.json # User 34. Realistic Data
Use tools like Faker.js to generate realistic mock data:
import { faker } from '@faker-js/faker'
const users = Array.from({ length: 100 }, (_, i) => ({
id: i + 1,
name: faker.person.fullName(),
email: faker.internet.email(),
avatar: faker.image.avatar(),
status: faker.helpers.arrayElement(['active', 'inactive'])
}))
// Save to mock/users.jsonLimitations
- ❌ POST with multiple files not supported (only first file is written)
- ❌ Pagination/filters only work with JSON arrays
- ❌ PATCH only works with JSON files
- ❌ OPTIONS method not supported in FS mode
- ✅ All other HTTP methods fully supported
Next Steps
- REST Handlers - Add custom logic
- Pagination & Filters - Detailed configuration
- HTTP Methods - Complete reference
