Files

117 lines
4.2 KiB
TypeScript

import { tmpdir } from "node:os";
import { join } from "node:path";
import type { AppConfig } from "@wrnexus/styles";
/**
* App configuration. Optional — delete this file and the app still runs.
*
* `head` injects raw HTML into every page's <head>. This is the zero-build way
* to use any CDN-delivered CSS framework. `seo` defines global metadata
* defaults. `styles` configures the bundled global stylesheet (and lets you
* swap in Tailwind/PostCSS/Sass via `process`). `security` configures
* framework-level headers and optional CORS.
*/
const config: AppConfig = {
head: [
// --- Use a CSS framework via CDN (uncomment one) ---
// Bootstrap:
// `<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />`,
// Tailwind (Play CDN — dev/prototyping only):
// `<script src="https://cdn.tailwindcss.com"></script>`,
],
seo: {
title: "WrNexus Basic App",
titleTemplate: "%s | WrNexus",
description:
"A Bun-first SSR framework demo with API routes, realtime, islands, and .wrn pages.",
siteName: "WrNexus",
canonicalBase: "http://localhost:3000",
robots: "index,follow",
type: "website",
twitterCard: "summary",
themeColor: "#6c8cff",
},
// Design-token themes. Built-in `light`/`dark` are provided; here we set the
// default and choose one of eight complete semantic color palettes. Users
// can still override individual tokens through `themes` when needed.
theme: {
palette: "violet",
default: "dark",
},
// Database connection for `wrnexus db` migrations (and, later, ctx.db).
db: {
driver: "sqlite",
url: "file:./dev.db",
},
styles: {
entry: "app/styles/global.css",
// Real Tailwind v4 build. Runs once at dev-serve time (cached, re-run on a
// restart) and at `wrnexus build`. `@tailwindcss/cli` writes to stdout by
// default, so we just capture and return the final CSS string.
process: async ({ entryPath, appRoot, mode }) => {
const args = ["@tailwindcss/cli", "-i", entryPath!];
if (mode === "production") args.push("--minify");
return await Bun.$.cwd(appRoot)`bunx ${args}`.text();
},
},
security: {
// Defaults already include CSP, COOP, X-Frame-Options, Trusted Types in
// production, strong HSTS in production, nosniff, referrer policy, and a
// restrictive Permissions-Policy. CORS is opt-in:
cors: {
enabled: true,
origin: ["http://localhost:5173", "http://localhost:3000"],
methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization"],
credentials: true,
maxAge: 600,
},
// Example: allow a CDN script/style if you uncomment one in `head`.
// contentSecurityPolicy: {
// directives: {
// "script-src": ["'self'", "https://cdn.tailwindcss.com"],
// "style-src": ["'self'", "'unsafe-inline'", "https://cdn.jsdelivr.net"],
// },
// },
// trustedTypes: {
// // Optional stricter production allow-list:
// policyNames: ["wrnexus", "default"],
// },
},
// Config profiles: select with `wrnexus dev --profile=uat` (or WRNEXUS_PROFILE).
// Each block is DEEP-MERGED over the base config above. Combine with per-profile
// .env files (.env.<profile>) for secrets — see `wrnexus profiles`.
profiles: {
// `production` also applies automatically on `wrnexus build`.
production: {
db: { driver: "postgres", url: process.env.DATABASE_URL ?? "postgres://localhost/app" },
seo: { canonicalBase: "https://example.com" },
},
uat: {
db: { driver: "postgres", url: process.env.DATABASE_URL ?? "postgres://localhost/uat" },
seo: { title: "WrNexus (UAT)", robots: "noindex,nofollow" },
},
test: {
// A fresh database per run. A file checked into the working tree would
// carry a schema from an earlier run, and a migration such as
// 0003_add_password then re-applies against a column that already
// exists, failing the suite on developer machines but not on CI.
db: {
driver: "sqlite",
url: `file:${join(tmpdir(), `wrnexus-test-${process.pid}.db`)}`,
},
},
},
};
export default config;