feat: add CI, Docker, auth, typed API client, shiki code blocks, e2e tests
CI / lint + typecheck + test + build (push) Canceled after 0s
CI / lint + typecheck + test + build (push) Canceled after 0s
- CI: GitHub Actions (bun 1.3.14, lint/typecheck/test/build/format gates) - Docker: multi-stage standalone build + .dockerignore (next.config output=standalone) - Auth: better-auth server (memory adapter, drizzle-swap-ready) + react client + /api/auth/[...all] route handler - API: /api/health + /api/openapi routes, openapi-typescript codegen to types/api.ts, typed openapi-fetch client (lib/api, lib/http) - Shiki: server-side CodeBlock component (escaped HTML) - E2E: playwright home + health specs on dedicated :3100 (chromium 1243 installed from GCS after CDN timeout) - Dev: allow 127.0.0.1/localhost dev origins (HMR for local tooling)
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
import { auth } from "@/lib/auth";
|
||||
import { toNextJsHandler } from "better-auth/next-js";
|
||||
|
||||
export const { GET, POST } = toNextJsHandler(auth);
|
||||
@@ -0,0 +1,12 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export function GET() {
|
||||
return NextResponse.json({
|
||||
ok: true,
|
||||
service: "nextjs-template",
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
/**
|
||||
* Minimal OpenAPI document describing the template's own API routes.
|
||||
* Kept in sync with app/api/** — regenerate client types with:
|
||||
* bun run api:generate
|
||||
*/
|
||||
export function GET() {
|
||||
return NextResponse.json({
|
||||
openapi: "3.1.0",
|
||||
info: {
|
||||
title: "Next.js Template API",
|
||||
version: "0.1.0",
|
||||
},
|
||||
paths: {
|
||||
"/api/health": {
|
||||
get: {
|
||||
operationId: "getHealth",
|
||||
responses: {
|
||||
"200": {
|
||||
description: "Service health",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
ok: { type: "boolean" },
|
||||
service: { type: "string" },
|
||||
timestamp: { type: "string", format: "date-time" },
|
||||
},
|
||||
required: ["ok", "service", "timestamp"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/auth/{action}": {
|
||||
parameters: [
|
||||
{
|
||||
name: "action",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
],
|
||||
get: {
|
||||
operationId: "authAction",
|
||||
responses: {
|
||||
"200": {
|
||||
description: "Auth route (Better Auth handler)",
|
||||
content: { "application/json": { schema: { type: "object" } } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user