Next.js 14 website with landing page, documentation, and interactive playground featuring server-side rendering.
- Server-Side Rendering (SSR) - Fast initial page loads with fresh data
- Automatic API Detection - Seamlessly works in dev and production
- Interactive Documentation - Live API info and schema exploration with search guide
- Enhanced Playground - Modern 50/50 split-screen layout:
- Tabbed Navigation: Quick, Pagination, Filters, Middleware, Path
- Request Builder (left): Endpoint type selector, all controls organized in tabs
- Response Viewer (right): Live JSON response with syntax highlighting
- Pagination controls: Page, limit, offset with visual feedback
- Sorting controls: Field selector with asc/desc order
- Search: Full-text search with field targeting
- Field selection: Multi-select with preview
- Middleware: 11+ options (delay, flaky, cache bypass, etc.)
- Headers & Metrics: Request timing, cache status, request ID
- 5 utility tools: Echo, Status, Delay, Middleware, Chaos
- Modern UI - Beautiful, responsive design with Tailwind CSS
- Comprehensive Sitemaps - 130+ URLs indexed (XML + HTML)
- Mobile Friendly - Fully responsive across all devices
- Type Safe - Full TypeScript support with auto-generated types
pnpm install
pnpm run devWebsite runs on http://localhost:3000
pnpm run build
pnpm startpnpm run type-checkfrontend/
├── app/ # Next.js pages (App Router)
│ ├── page.tsx # Home page (SSR)
│ ├── docs/ # Documentation (SSR)
│ └── playground/ # Interactive tester (CSR)
├── components/ # React components
│ ├── Header.tsx
│ ├── Footer.tsx
│ ├── ResourceCard.tsx
│ └── CodeExample.tsx
├── lib/
│ └── api.ts # API configuration
├── types/
│ └── api.ts # TypeScript definitions
└── shared/
└── schemas/ # JSON schemas
Environment variables are optional. The app automatically detects the API URL:
| Environment | API URL |
|---|---|
| Production | https://api.mockly.codes |
| Development | http://localhost:8080 |
Create .env.local in the frontend directory:
NEXT_PUBLIC_API_URL=https://api.mockly.codesThe lib/api.ts file automatically detects the environment:
export const getApiUrl = () => {
// Browser
if (typeof window !== "undefined") {
return window.location.hostname !== "localhost"
? "https://api.mockly.codes"
: "http://localhost:8080";
}
// Server-side
return (
process.env.NEXT_PUBLIC_API_URL ||
(process.env.NODE_ENV === "production"
? "https://api.mockly.codes"
: "http://localhost:8080")
);
};| Page | Rendering | Cache | Purpose |
|---|---|---|---|
/ (Home) |
SSR + ISR | 5 min | Fresh resources list |
/docs |
SSR + ISR | 5 min | Live API info + schemas |
Benefits:
- ⚡ Faster initial page load
- 🔍 Better SEO (search engine indexable)
- 📊 Fresh data on each visit
- 🌐 Works without JavaScript
Example:
// app/page.tsx
async function getResources() {
const res = await fetch("https://api.mockly.codes/", {
next: { revalidate: 300 }, // ISR: 5 minutes
});
return res.json();
}
export default async function Home() {
const resources = await getResources();
// Server-rendered with fresh data
}| Page | Rendering | Purpose |
|---|---|---|
/playground |
Client-Side | Interactive API testing |
Benefits:
- 🎮 Full interactivity
- 📡 Dynamic data fetching
- ⚙️ User-driven actions
Example:
"use client"; // Client component
const [data, setData] = useState(null);
const fetchData = async () => {
const res = await fetch("https://api.mockly.codes/users");
setData(await res.json());
};- Server-side rendered with ISR
- Fetches available resources from API
- Displays feature cards and quick examples
- Falls back to static resources if API unavailable
- Server-side rendered with ISR
- Shows live API status, version, and resource count
- Displays all resource schemas with properties
- Interactive "Try It" buttons for each endpoint
- Client-side rendered for full interactivity
- 50/50 split layout: Request builder (left) and response viewer (right)
- Tabbed navigation: Quick, Pagination, Filters, Middleware, Path tabs
- Compact header: Reduced size for more screen space
- Full-width layout: No max-width constraints for wider content area
- Test any endpoint with custom parameters
- Live JSON response viewer with syntax highlighting
- Real-time URL preview with path options (direct/group)
- Code examples dropdown with cURL, JavaScript, and Python
- Framework: Next.js 16 (App Router)
- UI Library: React 19 (Server Components + Client Components)
- Language: TypeScript 5.6+
- Styling: Tailwind CSS
- HTTP Client: pingpong-fetch (Universal HTTP client)
- Rendering: SSR + ISR (5-minute revalidation)
- Deployment: Vercel
- API: https://api.mockly.codes
- Type Generation: Automated from JSON schemas
TypeScript types are auto-generated from JSON schemas in types/api.ts:
// Resource interfaces
export interface User {
id: number;
username: string;
email: string;
// ... more fields
}
export interface Post {
id: number;
user_id: number;
title: string;
// ... more fields
}
// API response types
export type CollectionResponse<T extends ResourceName> = ResourceMap[T][];
export type SingleResponse<T extends ResourceName> = ResourceMap[T];
// Root API response
export interface ApiRootResponse {
message: string;
version: string;
resources: string[];
docs: string;
}This project is a monorepo with backend and frontend. The frontend is deployed separately to Vercel.
Important: Since the Next.js app is in the frontend/ subdirectory, you must configure Vercel's Root Directory.
- Go to your project Settings → General
- Under Root Directory, click Edit
- Set to:
frontend - Under Build & Development Settings:
- Build Command: Auto-detect (Next.js) or
pnpm run build - Install Command: Auto-detect or
pnpm install - Output Directory:
.next(auto-detected)
- Build Command: Auto-detect (Next.js) or
- Redeploy
# From project root
vercel --prod
# When prompted, set Root Directory to: frontend- Your git repo stays at the project root (✅ backend/, frontend/, shared/)
- Vercel treats
frontend/as the deployment root - This is standard for monorepos - one repo, multiple deployable apps
- Backend deploys separately (fly.io), frontend deploys to Vercel
Set in Vercel dashboard or CLI:
vercel env add NEXT_PUBLIC_API_URL
# Enter: https://api.mockly.codesNote: Environment variables are optional. The frontend defaults to https://api.mockly.codes in production.
Create a new file in app/:
// app/about/page.tsx
export default function AboutPage() {
return <div>About Mockly</div>
}Add components in components/:
// components/MyComponent.tsx
export function MyComponent() {
return <div>My Component</div>
}We use pingpong-fetch, a universal HTTP client that works in both browser and Node.js environments.
import { createApiClient } from '@/lib/api'
async function getData() {
const client = createApiClient()
const res = await client.get('/users')
return res.json()
}
export default async function Page() {
const data = await getData()
return <div>{JSON.stringify(data)}</div>
}'use client'
import { apiClient } from '@/lib/api'
const MyComponent = () => {
const [data, setData] = useState(null)
useEffect(() => {
const fetchData = async () => {
const res = await apiClient.get('/users')
setData(res.json())
}
fetchData()
}, [])
return <div>{JSON.stringify(data)}</div>
}- ✅ Universal - Works in Node.js (SSR) and browsers
- ✅ Fast - Uses undici in Node.js, native fetch in browsers
- ✅ Type-Safe - Full TypeScript support
- ✅ Retry Logic - Automatic retry with exponential backoff
- ✅ Chainable -
.json(),.text(),.ok(),.isError()methods - ✅ Small - ~5-6KB gzipped
The apiClient is pre-configured with:
- Base URL (auto-detected: production or localhost)
- 30-second timeout
- Automatic JSON content-type
- Retry logic (2 retries with exponential backoff)
See lib/api.ts for configuration.
- Project Overview: ../README.md
- API Documentation: https://www.mockly.codes/docs
- Backend Setup: ../backend/README.md
- Contributing: ../CONTRIBUTING.md
# Clear cache and rebuild
rm -rf .next
pnpm run build# Check for type errors
pnpm run type-checkCheck that:
- Backend is running on http://localhost:8080 (dev)
- Production API is accessible: https://api.mockly.codes
- CORS is enabled on the API
| Command | Description |
|---|---|
pnpm run dev |
Start development server |
pnpm run build |
Build for production |
pnpm start |
Start production server |
pnpm run lint |
Run ESLint |
pnpm run type-check |
TypeScript type checking |
- Create a new branch
- Make your changes
- Run
pnpm run build - Run
pnpm run type-check - Submit a pull request
See ../CONTRIBUTING.md for detailed guidelines.
MIT License - see ../LICENSE