@questpie/next
v3.33.0
Published
Next.js App Router adapter for QUESTPIE
Readme
@questpie/next
Next.js App Router adapter for QUESTPIE. Exports catch-all route handlers that mount CRUD, auth, storage, custom app routes, and realtime routes.
Installation
bun add @questpie/next questpieSetup
1. Route Handler
// app/api/[...path]/route.ts
import { questpieNextRouteHandlers } from "@questpie/next";
import { app } from "#questpie";
export const { GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD } =
questpieNextRouteHandlers(app, {
basePath: "/api",
});
export const dynamic = "force-dynamic";accessMode: "system" remains available in QUESTPIE 3.x only for a trusted
host boundary that cannot receive untrusted HTTP traffic. Canonical Next route
handlers should use the default user mode. This compatibility option is
scheduled for removal from the Next adapter in QUESTPIE 4.0.
2. Client
// lib/client.ts
import { createClient } from "questpie/client";
import type { AppConfig } from "#questpie";
export const appClient = createClient<AppConfig>({
baseURL: process.env.NEXT_PUBLIC_URL!,
basePath: "/api",
});3. Server Component
// app/posts/page.tsx
import { appClient } from "@/lib/client";
export default async function PostsPage() {
const { docs } = await appClient.collections.posts.find({
where: { published: { eq: true } },
orderBy: { publishedAt: "desc" },
limit: 10,
});
return (
<ul>
{docs.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}4. Client Component with TanStack Query
"use client";
import { useQuery } from "@tanstack/react-query";
import { createQuestpieQueryOptions } from "@questpie/tanstack-query";
import { appClient } from "@/lib/client";
const appQueries = createQuestpieQueryOptions(appClient);
export function PostsList() {
const { data } = useQuery(appQueries.collections.posts.find({ limit: 10 }));
return (
<ul>
{data?.docs.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}5. Server Actions
"use server";
import { app } from "#questpie";
import { revalidatePath } from "next/cache";
export async function createPost(formData: FormData) {
const post = await app.collections.posts.create({
title: formData.get("title") as string,
content: formData.get("content") as string,
});
revalidatePath("/posts");
return post;
}Routes
The adapter creates catch-all handlers under your base path:
| Method | Route | Description |
| ------ | ------------------------------------- | --------------------- |
| GET | /api/collections/:name | List items |
| POST | /api/collections/:name | Create item |
| GET | /api/collections/:name/:id | Get item |
| PATCH | /api/collections/:name/:id | Update item |
| DELETE | /api/collections/:name/:id | Delete item |
| POST | /api/collections/:name/:id/restore | Restore soft-deleted |
| GET | /api/collections/:name/:id/versions | List item versions |
| POST | /api/collections/:name/:id/revert | Revert item version |
| GET | /api/globals/:name | Get global |
| PATCH | /api/globals/:name | Update global |
| GET | /api/globals/:name/versions | List global versions |
| POST | /api/globals/:name/revert | Revert global version |
| POST | /api/collections/:name/upload | Upload file |
| ALL | /api/auth/* | Better Auth routes |
| ANY | /api/:route* | Custom app routes |
| GET | /api/collections/:name/subscribe | SSE realtime |
Environment Variables
DATABASE_URL=postgresql://...
NEXT_PUBLIC_URL=http://localhost:3000
AUTH_SECRET=your-secret-keyDocumentation
Full documentation: https://questpie.com/docs
License
MIT
