Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion website/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,25 @@ website/
docs/ /docs/<topic>, the reference documentation (#1098 moved
it here from docs.webjs.dev). layout.ts holds the nav
tree + docs-scoped metadata; the shell itself is shared,
see lib/ui/docs-shell.ts.
see lib/ui/docs-shell.ts. Nav labels and section titles
are Title Case (the Next.js and Rails convention, not
Tailwind's sentence case). A word whose casing is fixed
Comment thread
vivek7405 marked this conversation as resolved.
by something other than prose keeps it, which covers
code tokens (createAuth, @webjsdev/ui) and brands that
start lowercase (macOS, npm). Recasing either one
misspells it. Casing is the only thing pinned
sidebar-wide: a nav label NEED NOT match the page's
own h1, several deliberately do not, and those are
correct as they stand. The one exception is the
/docs/auth and /docs/authentication pair, where each
page's h1 is held byte-equal to its OWN label after
Comment thread
vivek7405 marked this conversation as resolved.
one of them once rendered a heading that named the
other page (#1103).
Do NOT generalise that pin to other pages. The /ui
sidebar is exempt from all of the above, since its
labels are component names from the live registry.
Both rules are enforced in test/ssr/docs-links.test.ts,
Comment thread
vivek7405 marked this conversation as resolved.
which carries the specifics and the current counts.
ui/ /ui, the @webjsdev/ui component gallery (#1099 moved it
here from ui.webjs.dev). page.ts is the introduction,
[name]/page.ts one page per component, layout.ts the
Expand Down
4 changes: 2 additions & 2 deletions website/app/docs/auth/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export const metadata = {

export default function Auth() {
return html`
<h1>Auth providers (createAuth)</h1>
<h1>Auth Providers (createAuth)</h1>
<p>WebJs ships <code>createAuth()</code>, a NextAuth-style auth surface with OAuth providers, credentials login, and JWT sessions. Reach for this page when you want providers and sessions handled for you, and no external auth library in the dependency tree.</p>
<p>It is not the only route. If you want to own the session format, the password hashing, and the route-protection rules yourself, build on the framework primitives instead, which is what <a href="/docs/authentication">Build your own authentication</a> covers and what the blog example does. Pick <code>createAuth()</code> for OAuth and a batteries-included setup, pick the primitives when you want full control of the session.</p>
<p>It is not the only route. If you want to own the session format, the password hashing, and the route-protection rules yourself, build on the framework primitives instead, which is what <a href="/docs/authentication">Build Your Own Authentication</a> covers and what the blog example does. Pick <code>createAuth()</code> for OAuth and a batteries-included setup, pick the primitives when you want full control of the session.</p>

<h2>Setup</h2>
<code-block>// lib/auth.server.ts: create once
Expand Down
4 changes: 2 additions & 2 deletions website/app/docs/authentication/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export const metadata = {

export default function Authentication() {
return html`
<h1>Build your own authentication</h1>
<h1>Build Your Own Authentication</h1>
<p>This page is the hand-rolled route: session-based auth built on the framework primitives, where you own the session format, the password hashing, and the route-protection rules. The blog example is a complete implementation of it, using scrypt password hashing, session tokens in cookies, and middleware-based route protection.</p>
<p>WebJs does ship a batteries-included option, so this is a choice rather than a necessity. <a href="/docs/auth">Auth providers (createAuth)</a> gives you OAuth providers, credentials login, and JWT sessions out of the box. Take that page if you want OAuth or do not want to own the session. Stay here if you want full control over how a session is minted, stored, and checked.</p>
<p>WebJs does ship a batteries-included option, so this is a choice rather than a necessity. <a href="/docs/auth">Auth Providers (createAuth)</a> gives you OAuth providers, credentials login, and JWT sessions out of the box. Take that page if you want OAuth or do not want to own the session. Stay here if you want full control over how a session is minted, stored, and checked.</p>

<h2>Architecture</h2>
<code-block>lib/
Expand Down
2 changes: 1 addition & 1 deletion website/app/docs/cache/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ setStore(redisStore({ url: process.env.REDIS_URL }));</code-block>
<h2>Next Steps</h2>
<ul>
<li><a href="/docs/sessions">Sessions</a>: session middleware built on the cache store</li>
<li><a href="/docs/auth">Auth providers (createAuth)</a>: NextAuth-style auth with providers</li>
<li><a href="/docs/auth">Auth Providers (createAuth)</a>: NextAuth-style auth with providers</li>
<li><a href="/docs/middleware">Middleware</a>: rate limiting and other middleware that uses the cache</li>
</ul>
`;
Expand Down
8 changes: 4 additions & 4 deletions website/app/docs/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import '#components/code-block.ts';
*
* Doc page bodies are plain HTML with no component wrapper, so their
* typography is styled through the shell's `.prose-docs` rules rather than
* per-element utility classes across 45 pages.
* per-element utility classes across 43 pages.
Comment thread
vivek7405 marked this conversation as resolved.
*/
const NAV_SECTIONS = [
{
Expand Down Expand Up @@ -61,7 +61,7 @@ const NAV_SECTIONS = [
{ href: '/docs/api-routes', label: 'API Routes' },
{ href: '/docs/websockets', label: 'WebSockets' },
{ href: '/docs/database', label: 'Database (Drizzle)' },
{ href: '/docs/authentication', label: 'Build your own authentication' },
{ href: '/docs/authentication', label: 'Build Your Own Authentication' },
{ href: '/docs/backend-only', label: 'Backend-Only Mode' },
],
},
Expand All @@ -71,7 +71,7 @@ const NAV_SECTIONS = [
{ href: '/docs/cache', label: 'Caching' },
{ href: '/docs/file-storage', label: 'File Storage' },
{ href: '/docs/sessions', label: 'Sessions' },
{ href: '/docs/auth', label: 'Auth providers (createAuth)' },
{ href: '/docs/auth', label: 'Auth Providers (createAuth)' },
{ href: '/docs/rate-limiting', label: 'Rate Limiting' },
{ href: '/docs/security', label: 'Security' },
{ href: '/docs/metadata-routes', label: 'Metadata Routes' },
Expand Down Expand Up @@ -114,7 +114,7 @@ const NAV_SECTIONS = [
* one field each page sets.
*
* Without this the docs inherit the marketing pitch: the deleted docs root
* layout carried its own title and description, so dropping it left all 45
* layout carried its own title and description, so dropping it left all 43
* pages advertising "the web framework for AI agents" as their search snippet
* and social card.
*
Expand Down
2 changes: 1 addition & 1 deletion website/app/docs/rate-limiting/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ REDIS_URL=redis://localhost:6379</code-block>
<ul>
<li><a href="/docs/middleware">Middleware</a>: how middleware chains work</li>
<li><a href="/docs/cache">Caching</a>: the underlying cache store that powers rate limiting</li>
<li><a href="/docs/authentication">Build your own authentication</a>: protect routes with auth</li>
<li><a href="/docs/authentication">Build Your Own Authentication</a>: protect routes with auth</li>
</ul>
`;
}
2 changes: 1 addition & 1 deletion website/app/docs/security/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function Security() {
<p>Cross-origin vendor modules (resolved from jspm.io) carry a standard SRI <code>integrity</code> hash so a swapped or compromised CDN response cannot execute unverified. This now applies on both paths: a pinned app (<code>webjs vendor pin</code>) ships the hashes in its committed importmap, and an un-pinned app computes them live at warmup. SRI computation is fail-open: a CDN fetch failure during the live path skips that one hash with a warning rather than taking the app down. For reproducible hashes and zero warmup fetches, pin. See <a href="/docs/no-build">No-Build Model</a>.</p>

<h2>Sessions and secret management</h2>
<p>Session cookies are signed, so set a strong <code>AUTH_SECRET</code> (and <code>SESSION_SECRET</code> where used), 32 or more random characters, in production. Keep all secrets server-only: any <code>process.env</code> name WITHOUT the <code>WEBJS_PUBLIC_</code> prefix never reaches the browser (reading <code>process.env.DATABASE_URL</code> from a component returns <code>undefined</code>, the same as a typo). The prefix is fail-closed, so a secret cannot leak by accident. Prefer your platform's secret injection over a committed <code>.env</code> file. See <a href="/docs/sessions">Sessions</a> and <a href="/docs/auth">Auth providers (createAuth)</a>.</p>
<p>Session cookies are signed, so set a strong <code>AUTH_SECRET</code> (and <code>SESSION_SECRET</code> where used), 32 or more random characters, in production. Keep all secrets server-only: any <code>process.env</code> name WITHOUT the <code>WEBJS_PUBLIC_</code> prefix never reaches the browser (reading <code>process.env.DATABASE_URL</code> from a component returns <code>undefined</code>, the same as a typo). The prefix is fail-closed, so a secret cannot leak by accident. Prefer your platform's secret injection over a committed <code>.env</code> file. See <a href="/docs/sessions">Sessions</a> and <a href="/docs/auth">Auth Providers (createAuth)</a>.</p>

<h2>Rate limiting</h2>
<p>Protect auth endpoints and other abuse-prone routes with the <code>rateLimit({ window, max })</code> middleware, placed at any route level (it applies to that subtree). Behind a reverse proxy or CDN, set <code>trustProxy: true</code> so it keys on the forwarded client IP, make sure the proxy strips an inbound <code>X-Forwarded-For</code> before adding its own, and leave <code>WEBJS_NO_TRUST_PROXY=1</code> unset, since that env var outranks the option and puts the limiter back on the stamped socket IP. See <a href="/docs/rate-limiting">Rate Limiting</a>.</p>
Expand Down
2 changes: 1 addition & 1 deletion website/app/docs/sessions/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const message = s.get('success'); // 'Post published!', only this request</code
<h2>Next Steps</h2>
<ul>
<li><a href="/docs/cache">Caching</a>: the cache store that backs server-side sessions</li>
<li><a href="/docs/auth">Auth providers (createAuth)</a>: NextAuth-style auth built on top of sessions</li>
<li><a href="/docs/auth">Auth Providers (createAuth)</a>: NextAuth-style auth built on top of sessions</li>
<li><a href="/docs/middleware">Middleware</a>: run session checks before route handlers</li>
</ul>
`;
Expand Down
2 changes: 1 addition & 1 deletion website/app/docs/typescript/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ events[0].createdAt.toLocaleDateString(); // works</code-block>
<code-block>const { auth } = createAuth&lt;AppUser&gt;({ secret, providers });
const session = await auth();
session?.user.role; // typed, no cast</code-block>
<p>Un-augmented and un-parameterised, <code>AuthUser</code> is empty and resolves back to <code>Record&lt;string, unknown&gt;</code>, so pre-existing untyped code keeps compiling. The declared fields should mirror what the callbacks write onto <code>session.user</code>. See <a href="/docs/auth">Auth providers (createAuth)</a>.</p>
<p>Un-augmented and un-parameterised, <code>AuthUser</code> is empty and resolves back to <code>Record&lt;string, unknown&gt;</code>, so pre-existing untyped code keeps compiling. The declared fields should mirror what the callbacks write onto <code>session.user</code>. See <a href="/docs/auth">Auth Providers (createAuth)</a>.</p>

<h2>JSDoc Alternative</h2>
<p>If you prefer <code>.js</code> files, you can achieve the same type safety using JSDoc annotations with <code>checkJs: true</code> in your tsconfig:</p>
Expand Down
Loading
Loading