A comprehensive starter template for building Next.js applications with strongly typed API endpoints, leveraging the next-vibe framework.
- Next.js API routes are used for the backend
- Zod schema based api definitions
- Provide input and output schema and let AI fill the blanks
- each api automatically provides hooks to mutate or query the data
- Optionally use the form query and mutation hooks
- Hooks can then be use accross the code base
- Code uses the next.js app route scheme
- Compiles down to a next.js app for web and API's
-
- Also compiles to native apps using expo
This template provides a complete development environment for creating Next.js applications with type-safe, validated API endpoints. It includes the next-vibe package, which delivers strongly typed APIs, role-based access control, data providers, and client-side hooks.
- Strongly Typed APIs: Define endpoints with full TypeScript support and Zod validation
- Role-Based Access Control: Built-in user role management and authorization
- Data Providers: Flexible data access with Prisma integration
- Client Hooks: React hooks for data fetching and mutation
- Form Integration: Form handling with validation and API integration
- Cross-Platform: Works with both browser and React Native environments
Start by forking this repository to use as your project foundation. This allows you to:
- Begin development immediately with all configurations in place
- Easily merge updates when new versions are released
- Customize the template to fit your specific project needs
# Clone your forked repository
git clone https://github.com/your-username/next-portal.git
cd next-portal
# Install dependencies
yarn install
# Copy the example environment file
cp .env.example .env
Edit the .env file to configure your environment variables.
# Start the development server
yarn run dev
# Build the application
yarn run build
This template offers two ways to use the next-vibe package:
The package is included in the ./src/packages/next-vibe directory. This approach allows you to:
- Directly modify the package code if needed
- Debug and step through the package code
- Make local customizations
Configure in next.portal.config.ts:
export default {
useNextQueryPortalPackage: false
};
Alternatively, you can use the published npm package:
TODO handle removing the next-vibe before installing package version
yarn add next-vibe
And update next.portal.config.ts:
export default {
useNextQueryPortalPackage: true
};
├── src/
│ ├── app/ # Next.js app directory
│ ├── components/ # React components
│ ├── config/ # Application configuration
│ ├── hooks/ # Custom React hooks
│ └── packages/ # Local packages including next-vibe
├── prisma/
│ └── schema.prisma # Prisma database schema
├── .env.example # Example environment variables
├── next.config.ts # Next.js configuration
└── next.portal.config.ts # Portal-specific configuration
This template includes a ready-to-use API endpoint example in the src/app/api/template-api
directory. Explore this folder to see a complete implementation with schemas, endpoint definition, and even email integration:
- definition.ts: Defines the API endpoint configuration
- schema.ts: Contains Zod schemas for request/response validation
- email.tsx: Example of how to integrate email sending with your API
To create a new API endpoint, follow this structure:
- Define your schemas (similar to
schema.ts
):
import { z } from 'zod';
export const userCreateRequestSchema = z.object({
name: z.string().min(2, { message: "Name must be at least 2 characters" }),
email: z.string().email({ message: "Please provide a valid email" }),
});
export const userCreateResponseSchema = z.object({
id: z.string().uuid(),
name: z.string(),
email: z.string().email(),
createdAt: z.date(),
});
// Export types derived from schemas
export type UserCreateRequestType = z.infer<typeof userCreateRequestSchema>;
export type UserCreateResponseType = z.infer<typeof userCreateResponseSchema>;
- Create the endpoint definition (similar to
definition.ts
):
import { createEndpoint } from "next-vibe/client";
import { UserRoleValue } from "next-vibe/shared";
import { userCreateRequestSchema, userCreateResponseSchema } from "./schema";
export default createEndpoint({
description: "Create a new user",
method: "POST",
requestSchema: userCreateRequestSchema,
responseSchema: userCreateResponseSchema,
requestUrlSchema: z.undefined(), // No URL parameters for this endpoint
apiQueryOptions: {
queryKey: ["users", "create"],
},
fieldDescriptions: {
name: "User's full name",
email: "User's email address",
},
allowedRoles: [UserRoleValue.ADMIN], // Only admins can create users
errorCodes: {
400: "Invalid request data",
409: "Email already in use",
500: "Internal server error",
},
dirname: __dirname,
examples: {
payloads: {
default: {
name: "John Doe",
email: "[email protected]",
},
},
},
});
- Implement the route handler (in
route.ts
):
import { apiHandler } from "next-vibe/server";
import { db } from "../../db";
import endpoint from "./definition";
import type { UserCreateRequestType, UserCreateResponseType } from "./schema";
export const POST = apiHandler<UserCreateRequestType, UserCreateResponseType>(
endpoint,
async ({ requestData, user }) => {
// Create user in database
const newUser = await db.user.create({
data: {
name: requestData.name,
email: requestData.email,
createdById: user.id,
},
});
// Return created user data
return {
id: newUser.id,
name: newUser.name,
email: newUser.email,
createdAt: newUser.createdAt,
};
}
);
The template automatically discovers your endpoints and generates type definitions, making them available throughout your application.
import { useApiForm } from "next-vibe/client";
import { endpoints } from "@/app/api/generated/endpoints";
function CreateUserForm() {
const {
register,
handleSubmit,
formState,
submitForm,
isSubmitting,
errorMessage
} = useApiForm(endpoints.users.create);
return (
<form onSubmit={handleSubmit(submitForm)}>
<div>
<label>Name</label>
<input {...register('name')} />
{formState.errors.name && (
<p>{formState.errors.name.message}</p>
)}
</div>
<div>
<label>Email</label>
<input {...register('email')} />
{formState.errors.email && (
<p>{formState.errors.email.message}</p>
)}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Submitting..." : "Create User"}
</button>
{errorMessage && <p>{errorMessage}</p>}
</form>
);
}
This template is optimized for deployment on Vercel:
- Connect your GitHub repository to Vercel
- Configure environment variables in the Vercel dashboard
- Deploy with the default settings (Vercel automatically detects Next.js)
# Or deploy via Vercel CLI
npm install -g vercel
vercel
- Docker: Use the included Dockerfile for containerized deployments
- Node.js Server: Build and run on any Node.js hosting platform
- Static Export: For simple applications, use
next export
for static site generation
When new versions of the template or next-vibe are released:
- Add the original repository as a remote:
git remote add upstream https://github.com/techfreaque/next-vibe.git
- Fetch the latest changes:
git fetch upstream
- Merge changes (resolve conflicts as needed):
git merge upstream/main
- Template App: MIT
- next-vibe Package: GPL-3.0-only