docs: expand full-width guides and package navigation

This commit is contained in:
2026-08-10 14:18:31 +05:30
parent 19b3c9a7cd
commit c767435cc0
94 changed files with 1442 additions and 236 deletions
+231 -3
View File
@@ -210,12 +210,16 @@ const documentationNavigation = [
["/search", "Search"],
] as const;
const packageNavigation = packageNames
.map((name) => `<a href="/packages/${name}">@wrnexus/${name}</a>`)
.join("");
const sectionNavigation = `<aside class="docs-section-menu" aria-label="Documentation sections">
<nav>
<section><strong>Get started</strong><a href="/getting-started">Quick start</a><a href="/tutorial">Tutorial</a><a href="/guides/full-stack-auth-demo">Auth dashboard demo</a><a href="/guides/project-structure">Project structure</a><a href="/guides/configuration-and-profiles">Configuration</a></section>
<section><strong>Build</strong><a href="/guides/pages-and-components">Pages and components</a><a href="/guides/routing">Routing</a><a href="/guides/server-data">Server data</a><a href="/guides/forms-and-validation">Forms and validation</a><a href="/guides/database">Database</a></section>
<section><strong>Auth and security</strong><a href="/guides/authentication">Authentication</a><a href="/guides/authorization">Authorization</a><a href="/guides/security">Application security</a><a href="/security">Security policy</a></section>
<section><strong>Reference</strong><a href="/packages">Packages</a><a href="/packages/cli">CLI</a><a href="/language">.wrn language</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/examples">Examples</a></section>
<section><strong>Reference</strong><a href="/packages">Packages overview</a><a href="/packages/cli">CLI</a><a href="/language">.wrn language</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/examples">Examples</a></section>
<section class="package-menu"><strong>Packages</strong>${packageNavigation}</section>
</nav>
</aside>`;
@@ -668,12 +672,222 @@ bunx wrnexus preview . --port=3000`)}<p>Tests should prove anonymous dashboard a
<h2>9. Demo checklist</h2><ul><li>Public home, pricing, privacy, and terms pages render without authentication.</li><li>Login creates and rotates a secure session.</li><li>Dashboard navigation changes by permission, while APIs enforce every permission independently.</li><li>Member lists and mutations are tenant-scoped on the server.</li><li>Development and production profiles resolve explicitly.</li><li>Typecheck, API tests, browser tests, security audit, contract check, build, and preview all pass.</li></ul>`,
],
};
const guideExamples: Record<string, [string, string]> = {
"project-structure": [
"Generate files through the CLI so routes and application types stay synchronized.",
`bunx wrnexus generate page account/settings
bunx wrnexus generate component account-card
bunx wrnexus generate api account/profile
bunx wrnexus generate routes
bunx wrnexus generate types .`,
],
routing: [
"This creates a dynamic, server-rendered account route and verifies that the router discovered it.",
`// app/pages/accounts/[id].wrn
page Account { view { <main><h1>Account {params.id}</h1></main> } }
bunx wrnexus inspect routes .`,
],
"pages-and-components": [
"Declare the reusable contract in a component, then pass data from the owning page.",
`component StatusCard {
prop title = "Status"
prop value = "Unknown"
view { <article><h2>{title}</h2><p>{value}</p><slot /></article> }
}
page Dashboard { view { <StatusCard title="API" value="Healthy" /> } }`,
],
"server-data": [
"Fetch on the server and render useful HTML before browser JavaScript loads.",
`page Accounts {
ssr { api result GET /api/accounts { return result.accounts } }
view { <ul>{#each result as account}<li>{account.name}</li>{:empty}<li>No accounts</li>{/each}</ul> }
}`,
],
"api-routes": [
"Validate a mutation and return an explicit HTTP result.",
`import { v, parseBody } from "@wrnexus/validation";
const input = v.object({ name: v.string().trim().min(2).max(80) });
export const POST = async (ctx) => {
const parsed = await parseBody(input, ctx.req);
return parsed.ok ? Response.json(parsed.value, { status: 201 }) : parsed.response;
};`,
],
middleware: [
"Add a request identifier and reject unsupported methods before application handlers run.",
`export default async function requestContext(ctx, next) {
ctx.state.requestId = crypto.randomUUID();
if (!["GET", "HEAD", "POST"].includes(ctx.req.method))
return new Response("Method not allowed", { status: 405 });
return next();
}`,
],
"forms-and-validation": [
"Use the same named schema in the browser form and authoritative API handler.",
`page Signup { view {
<form data-schema="signup" action="/api/signup" method="post">
<input name="email" type="email" /><span data-error="email"></span>
<button type="submit">Create account</button>
</form>
} }`,
],
authentication: [
"Require an authenticated session in middleware and redirect browser requests to login.",
`export default async function requireSession(ctx, next) {
const user = await readAuthenticatedUser(ctx);
if (!user) return Response.redirect(new URL("/login", ctx.url), 303);
ctx.state.user = user;
return next();
}`,
],
authorization: [
"Check the exact permission at the mutation boundary; hiding UI is only a convenience.",
`export const DELETE = async (ctx) => {
await requirePermission(ctx, "member:delete");
await deleteMember(ctx.params.id, ctx.state.user.tenantId);
return new Response(null, { status: 204 });
};`,
],
security: [
"Enable the main browser and request protections in application configuration, then audit the resolved production profile.",
`// wrnexus.config.ts
export default {
security: {
contentSecurityPolicy: true,
csrf: true,
trustedTypes: true,
frameOptions: "deny",
referrerPolicy: "strict-origin-when-cross-origin",
requestLimit: { maxBytes: 1_048_576 },
cors: { origins: ["https://app.example.com"] },
},
};
bunx wrnexus config . --explain --profile=production
bunx wrnexus security audit .`,
],
database: [
"Create a migration from models, apply it, and regenerate typed database functions.",
`bunx wrnexus db status
bunx wrnexus db new create_accounts --from-models
bunx wrnexus db migrate
bunx wrnexus db generate`,
],
uploads: [
"Keep size and type policy server-owned and serve private objects through an authorized route.",
`export default {
uploads: { stores: { avatars: {
driver: "local", directory: "./data/avatars",
maxBytes: 2_000_000, accept: ["image/png", "image/jpeg"],
} } },
};`,
],
realtime: [
"Authorize room membership and validate every incoming message before broadcasting.",
`export default defineRoom("team", {
async connect(client, ctx) { await requireTeamMember(ctx, ctx.params.teamId); },
async message(client, raw) {
const message = chatMessage.parse(JSON.parse(raw));
client.room.broadcast(JSON.stringify(message));
},
});`,
],
pubsub: [
"Use Redis when events must cross processes; use a namespaced channel contract.",
`const bus = createRedisPubSub({ url: env.REDIS_URL });
await bus.subscribe("team:42:events", (event) => handleTeamEvent(event));
await bus.publish("team:42:events", JSON.stringify({ type: "member.invited" }));`,
],
queues: [
"Make jobs idempotent and bound retry behavior before processing external effects.",
`const emails = queue("emails", { concurrency: 4, retries: 3 });
emails.process(async (job) => sendInviteOnce(job.data.invitationId));
await emails.add({ invitationId }, { delay: 1_000 });`,
],
testing: [
"Cover successful output and the denial path, then run the built server smoke check.",
`import { describe, expect, test } from "bun:test";
describe("members API", () => {
test("denies anonymous requests", async () => {
const response = await request("/api/members");
expect(response.status).toBe(401);
});
});`,
],
"workspaces-and-gateway": [
"Register applications explicitly and verify host routing through the gateway port.",
`bunx wrnexus workspace company-platform
cd company-platform
bunx wrnexus workspace add admin --domain=admin.localhost
bunx wrnexus gateway --port=3000`,
],
deployment: [
"Build once, apply migrations before traffic, and run the immutable Bun server artifact.",
`bun install --frozen-lockfile
bunx wrnexus typecheck .
bunx wrnexus db migrate
bunx wrnexus build .
bun dist/server.js`,
],
"configuration-and-profiles": [
"Keep shared defaults at the root and make production differences explicit.",
`export default {
server: { port: 3000 },
profiles: {
development: { envFiles: [".env", ".env.development"] },
production: { envFiles: [".env", ".env.production"] },
},
};
bunx wrnexus config . --explain --profile=production`,
],
"i18n-and-themes": [
"Configure one default locale and theme, then reference translation keys in server-rendered markup.",
`export default {
i18n: { defaultLocale: "en", locales: ["en", "fr"] },
theme: { default: "system", palette: "violet" },
};
page Home { view { <h1>{t:home.title}</h1><button data-wire-theme-toggle>Theme</button> } }`,
],
mobile: [
"Generate the mobile surface, compile it, and inspect supported native capabilities before relying on one.",
`bunx wrnexus generate mobile
bunx wrnexus mobile compile
bunx wrnexus native list`,
],
observability: [
"Redact credentials at the sink boundary and attach a stable request identifier.",
`const tracking = createTracking({
redact: ["authorization", "cookie", "password", "token"],
sampleRate: 0.1,
});
export default tracking.middleware();`,
],
upgrading: [
"Preview migrations first, review the report, then update the aligned package set.",
`git status --short
bunx wrnexus update . --latest --dry-run
bunx wrnexus update . --latest
bunx wrnexus typecheck .
bunx wrnexus build .`,
],
troubleshooting: [
"Collect deterministic diagnostics without exposing application secrets.",
`bun --version
bunx wrnexus doctor .
bunx wrnexus config . --explain
bunx wrnexus inspect routes .
bunx wrnexus report . --file=app/pages/index.wrn`,
],
};
for (const [slug, [title, desc, text]] of Object.entries(guides))
page(
`/guides/${slug}`,
title,
desc,
`<article class="documentation prose standalone"><span class="status status-beta">Preview guide · ${version}</span><h1>${title}</h1>${text.startsWith("<") ? text : `<p>${text}</p>`}<h2>Configuration</h2><p>Keep configuration in <code>wrnexus.config.ts</code>, select an explicit profile, and store secrets only in validated environment variables. Use <code>wrnexus config . --explain</code> to review the resolved non-secret configuration.</p><h2>Implementation workflow</h2>${code(`bunx wrnexus doctor .
`<article class="documentation prose standalone"><span class="status status-beta">Preview guide · ${version}</span><h1>${title}</h1>${text.startsWith("<") ? text : `<p>${text}</p>`}${guideExamples[slug] ? `<h2>Practical example</h2><p>${guideExamples[slug][0]}</p>${code(guideExamples[slug][1])}<h3>What to verify</h3><p>Run this against the selected profile, inspect the generated or returned result, and add a test for both the successful path and its most important failure path.</p>` : ""}<h2>Configuration</h2><p>Keep configuration in <code>wrnexus.config.ts</code>, select an explicit profile, and store secrets only in validated environment variables. Use <code>wrnexus config . --explain</code> to review the resolved non-secret configuration.</p><h2>Implementation workflow</h2>${code(`bunx wrnexus doctor .
bunx wrnexus typecheck .
bunx wrnexus inspect routes .
bunx wrnexus build .`)}<p>Start from the exact installed package page, implement the smallest server-owned contract, and add browser behavior only where interaction requires it. Run the production build because development-only success does not prove deployability.</p><h2>Verification checklist</h2><ul><li>Inputs are validated at the authoritative server boundary.</li><li>Authentication and resource authorization are tested independently.</li><li>Generated routes and application types are current.</li><li>Error, empty, loading, denied, and success states are documented.</li><li>The production artifact starts and serves the expected route.</li></ul><h2>Release scope</h2><p>This guide describes installed ${version} capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.</p><p><a href="/packages">Browse package APIs</a> · <a href="/packages/cli">CLI reference</a> · <a href="/guides/troubleshooting">Troubleshooting</a> · <a href="/support">Support</a></p></article>`,
@@ -740,7 +954,21 @@ page(
"/security",
"Security",
"WRNexusJS security defaults, limits, supported release status, and reporting process.",
`<article class="documentation prose standalone"><h1>Security</h1><p>WRNexusJS provides primitives for CSP, CSRF, Trusted Types, sessions, validation, authorization, encryption, upload restrictions, request limits, and WebSocket-origin checks. Applications remain responsible for correct configuration, business authorization, secrets, dependencies, data protection, and operations.</p><h2>Supported releases</h2><p>Only the current private-preview release ${version} is documented here. A formal old-release support window is not yet published.</p><h2>Report a vulnerability</h2><p>Use WorkRoots approved private contact path at <a href="https://workroot.in/">workroot.in</a>. Do not publish exploit details or secrets. Include affected version, impact, reproduction, and a safe contact method. Response targets, encryption key, bounty, audit, and certification are not currently claimed.</p><h2>Deployment controls</h2><p>Use restrictive CSP and permissions policies, HSTS only on HTTPS production origins, MIME sniffing protection, restrictive referrers, explicit CORS, secure cookies, CSRF validation, request limits, and origin checks. See <a href="/guides/security">application security</a>.</p></article>`,
`<article class="documentation prose standalone"><h1>Security</h1><p>WRNexusJS provides primitives for CSP, CSRF, Trusted Types, sessions, validation, authorization, encryption, upload restrictions, request limits, and WebSocket-origin checks. Applications remain responsible for correct configuration, business authorization, secrets, dependencies, data protection, and operations.</p><h2>Start with a production policy</h2><p>The following baseline blocks framing, restricts referrers and cross-origin access, enables CSRF and Trusted Types, and caps request bodies. Replace the example origin with the exact browser origin that calls your application.</p>${code(`// wrnexus.config.ts
export default {
security: {
contentSecurityPolicy: true,
csrf: true,
trustedTypes: true,
frameOptions: "deny",
referrerPolicy: "strict-origin-when-cross-origin",
cors: { origins: ["https://app.example.com"], credentials: true },
requestLimit: { maxBytes: 1_048_576 },
},
};`)}<h3>What you can change</h3><ul><li>Add only required API origins to CORS; never use a wildcard with credentialed requests.</li><li>Lower request limits for JSON APIs and define separate upload limits for accepted file types.</li><li>Extend CSP only for origins your application actually loads; avoid unsafe inline script exceptions.</li><li>Enable HSTS only after HTTPS works on every production hostname and subdomain you include.</li><li>Set session expiry, rotation, secure, HTTP-only, and SameSite behavior for your authentication flow.</li></ul><h2>Verify the resolved controls</h2>${code(`bunx wrnexus config . --explain --profile=production
bunx wrnexus security audit .
bunx wrnexus typecheck .
bunx wrnexus build .`)}<p>Review the resolved production configuration, then test a valid request, an invalid CSRF token, an oversized body, an unapproved origin, an anonymous protected request, and a permission-denied request. Security configuration is complete only when denial behavior is tested.</p><h2>Supported releases</h2><p>Only the current private-preview release ${version} is documented here. A formal old-release support window is not yet published.</p><h2>Report a vulnerability</h2><p>Use WorkRoots approved private contact path at <a href="https://workroot.in/">workroot.in</a>. Do not publish exploit details or secrets. Include affected version, impact, reproduction, and a safe contact method. Response targets, encryption key, bounty, audit, and certification are not currently claimed.</p><h2>Deployment controls</h2><p>Terminate TLS at a trusted edge, forward only expected proxy headers, store secrets outside source control, apply database migrations before traffic, and monitor rejected requests without logging credentials. Continue with the complete <a href="/guides/security">application security guide</a>.</p></article>`,
"Trust",
);
page(