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:
+11
@@ -0,0 +1,11 @@
|
||||
import createClient from "openapi-fetch";
|
||||
import type { paths } from "@/types/api";
|
||||
|
||||
export const api = createClient<paths>({
|
||||
baseUrl: "/",
|
||||
});
|
||||
|
||||
// Typed convenience wrappers for the template's own API routes.
|
||||
export const healthApi = {
|
||||
get: () => api.GET("/api/health"),
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { createAuthClient } from "better-auth/react";
|
||||
|
||||
export const authClient = createAuthClient({
|
||||
baseURL: process.env.NEXT_PUBLIC_BETTER_AUTH_URL ?? "http://localhost:3000",
|
||||
});
|
||||
|
||||
export const { useSession, signIn, signUp, signOut } = authClient;
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { betterAuth } from "better-auth";
|
||||
import { memoryAdapter } from "better-auth/adapters/memory";
|
||||
|
||||
/**
|
||||
* Better Auth server instance.
|
||||
*
|
||||
* Uses the in-memory adapter so the template builds and runs without a
|
||||
* database. Swap to a real adapter (drizzle/kysely + Postgres) when a DB is
|
||||
* wired up:
|
||||
*
|
||||
* import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||
* database: drizzleAdapter(db, { provider: "pg" })
|
||||
*
|
||||
* Required env (see .env.example):
|
||||
* BETTER_AUTH_SECRET — run `bunx @better-auth/cli secret` to generate
|
||||
* BETTER_AUTH_URL — full URL of the deployed app
|
||||
*/
|
||||
export const auth = betterAuth({
|
||||
database: memoryAdapter({}),
|
||||
secret: process.env.BETTER_AUTH_SECRET,
|
||||
baseURL: process.env.BETTER_AUTH_URL,
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
},
|
||||
session: {
|
||||
expiresIn: 60 * 60 * 24 * 7, // 7 days
|
||||
updateAge: 60 * 60 * 24, // refresh every 24h
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
maxAge: 5 * 60,
|
||||
},
|
||||
},
|
||||
advanced: {
|
||||
cookiePrefix: "nextjs-template",
|
||||
},
|
||||
});
|
||||
|
||||
export type Session = typeof auth.$Infer.Session;
|
||||
Reference in New Issue
Block a user