Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7982b67
docs: establish contract-driven documentation foundation
bordumb Aug 14, 2026
99b5a18
docs: ship progressive product journey
bordumb Aug 14, 2026
e822539
docs: qualify executable cross-language examples
bordumb Aug 14, 2026
691afa6
docs: generate deep SDK and runtime references
bordumb Aug 14, 2026
2f841a3
docs: publish architecture operations integrations and assurance
bordumb Aug 14, 2026
4e85096
docs: publish agent-first machine-readable surfaces
bordumb Aug 14, 2026
f931a5c
docs: qualify cross-repository documentation release
bordumb Aug 14, 2026
4576625
docs: enforce platform and editorial ownership
bordumb Aug 14, 2026
fff25d1
docs: publish topic landings and global navigation
bordumb Aug 14, 2026
21dec44
docs: publish getting started chooser and paths
bordumb Aug 14, 2026
c2fe2ec
docs: publish semantic tours and lifecycle concepts
bordumb Aug 14, 2026
56aede8
docs: publish outcome quickstarts
bordumb Aug 14, 2026
0ab3083
docs: publish developer resources and reference guides
bordumb Aug 14, 2026
8e99dc6
docs: publish agent and integration journeys
bordumb Aug 14, 2026
79130f0
docs: publish incremental adoption journeys
bordumb Aug 14, 2026
3587d6b
docs: publish operations and incident guidance
bordumb Aug 14, 2026
fd4ac30
docs: define documentation ownership and maintenance
bordumb Aug 14, 2026
d3dc5db
docs: establish canonical documentation hierarchy
bordumb Aug 14, 2026
dacd29b
docs: enforce topic shell and page contracts
bordumb Aug 14, 2026
01d1649
docs: rebuild executable get started journey
bordumb Aug 14, 2026
134a5f9
docs: complete identity and trust journey
bordumb Aug 14, 2026
746d40d
docs: complete progressive authority journey
bordumb Aug 14, 2026
3d75a4e
docs: complete agents and MCP journey
bordumb Aug 14, 2026
6e6458f
docs: complete production operations journey
bordumb Aug 14, 2026
9e7cdaa
docs: complete developer and integration journey
bordumb Aug 14, 2026
4ef5175
docs: complete reference and assurance utilities
bordumb Aug 14, 2026
32b56ef
docs: qualify complete documentation site
bordumb Aug 14, 2026
fd020bb
fix: keep topic navigation visible on long pages
bordumb Aug 14, 2026
f6552f5
docs: rebuild source-backed documentation site
bordumb Aug 15, 2026
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
43 changes: 43 additions & 0 deletions .github/workflows/qualify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Qualify documentation

on:
pull_request:
branches: [main]
push:
branches: [main]
workflow_dispatch:

concurrency:
group: docs-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
qualify:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version-file: .nvmrc
cache: npm
- name: Reject a superseded source head
env:
EXPECTED_HEAD: ${{ github.event.pull_request.head.sha || github.sha }}
run: test "$(git rev-parse HEAD)" = "$EXPECTED_HEAD"
- run: npm ci --ignore-scripts
- run: npm run qualify
- name: Preserve qualified static output
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: auths-docs-static-${{ github.event.pull_request.head.sha || github.sha }}
path: dist/client/
if-no-files-found: error
retention-days: 7
compression-level: 9
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# misc
.DS_Store
*.pem
*.tsbuildinfo

# debug
npm-debug.log*
Expand Down
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.19.0
57 changes: 36 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
# Auths Documentation Prototype
# Auths Documentation

This repository is the visual and authoring prototype for `docs.auths.dev`.
It deliberately stops before AP-SPEC-040 implementation: no generated SDK
reference, release contract ingestion, cross-repository automation, search
index, or deployment qualification exists yet.
This repository builds the public `docs.auths.dev` experience from free-form
editorial MDX and an immutable, checksum-addressed Auths product snapshot.

The current template proves four things:
The product contract is:

- a concrete design language for Auths documentation;
- a product-led landing page with progressive disclosure;
- MDX as an authoring format for technical guides; and
- synchronized Rust, TypeScript, and Python examples on one semantic page.
- begin with outcomes and five stable verbs;
- progressively disclose protocol and operational depth;
- generate reference facts from installed SDK and runtime artifacts;
- render maintained TypeScript and Python recipes from pinned product source; and
- publish equivalent HTML and canonical Markdown for people and agents.

## Pages
## Information architecture

- `/` — main documentation landing page
- `/guides/protect-rest-effect` — representative multi-language guide
`content-v2/navigation.json` owns the homepage route, the public documentation
routes, top navigation placement, left navigation groups, and page ordering.
The four primary destinations are:

- `/start` — choose a first workflow and run a maintained quickstart;
- `/guides` — integrate Auths and understand the authority and verification models;
- `/examples` — inspect production-shaped examples by security question; and
- `/reference` — look up the exact SDK, protocol, outcome, and evidence surfaces.

Conceptual material lives inside Guides rather than in a separate top-level
section. The custom homepage layout reads its copy from the registry-owned
`content-v2/home.json`, which also generates `/index.md` and machine-readable
discovery entries.

## Local development

Expand All @@ -29,20 +39,25 @@ npm run dev
Run the production build and checks:

```bash
npm run docs:build
npm run routes:check
npm run typecheck
npm run build
npm run lint
npm test
npm run audit:docs
```

## Prototype decisions
## Architecture decisions

Read:

- [`docs/TOOLING.md`](docs/TOOLING.md)
- [`docs/DESIGN_LANGUAGE.md`](docs/DESIGN_LANGUAGE.md)

This prototype uses Vinext/Vite for a fast preview and deploy loop while using
MDX for the representative guide. It does not silently replace AP-SPEC-040's
Astro/Starlight implementation decision. Before the full epic work begins, use
this prototype to decide which shell to carry forward; the design tokens,
components, MDX content, and interaction contract are intentionally portable.
- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
- [`docs/MAINTENANCE.md`](docs/MAINTENANCE.md)

The site is static-first. Product facts enter only through `product-snapshot/`;
editorial explanations live under `content-v2/`. The site has no production
database, provider credentials, or runtime authority. Client JavaScript is
reserved for search, navigation state, synchronized language selection, and
copy actions.
22 changes: 22 additions & 0 deletions app/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { DocsShell } from "../components/docs/DocsShell";
import { docsPage, docsPages } from "../lib/docs-content";

export function generateStaticParams() {
return docsPages.map((page) => ({ slug: page.path.slice(1).split("/") }));
}

export async function generateMetadata({ params }: { params: Promise<{ slug: string[] }> }): Promise<Metadata> {
const { slug } = await params;
const page = docsPage(`/${slug.join("/")}`);
if (!page) return {};
return { title: page.frontmatter.title, description: page.frontmatter.description, alternates: { canonical: page.path } };
}

export default async function Page({ params }: { params: Promise<{ slug: string[] }> }) {
const { slug } = await params;
const page = docsPage(`/${slug.join("/")}`);
if (!page) notFound();
return <DocsShell page={page} />;
}
3 changes: 3 additions & 0 deletions app/components/AuthsLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function AuthsLogo() {
return <span aria-hidden="true" className="auths-logo" />;
}
93 changes: 21 additions & 72 deletions app/components/CodeGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,90 +1,39 @@
"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import {
isSdkLanguage,
sdkLanguageEvent,
sdkLanguageStorageKey,
type SdkLanguage,
} from "../lib/sdk-languages";
import type { SdkLanguage } from "../lib/sdk-languages";
import { CodeBlock } from "./code";
import { SdkLanguageTabs, useSynchronizedSdkLanguage } from "./code/SdkLanguageControl";

type Snippet = {
label: string;
language: SdkLanguage;
code: string;
};

export function CodeGroup({ snippets, filename }: { snippets: Snippet[]; filename?: string }) {
const available = useMemo(() => snippets.map((snippet) => snippet.language), [snippets]);
const [selected, setSelected] = useState<SdkLanguage>(snippets[0]?.language ?? "typescript");
const [copied, setCopied] = useState(false);
const copyTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

useEffect(() => {
const stored = window.localStorage.getItem(sdkLanguageStorageKey);
const hydrationTimer = isSdkLanguage(stored) && available.includes(stored)
? window.setTimeout(() => setSelected(stored), 0)
: null;

const sync = (event: Event) => {
const language = (event as CustomEvent<SdkLanguage>).detail;
if (available.includes(language)) setSelected(language);
};
window.addEventListener(sdkLanguageEvent, sync);
return () => {
if (hydrationTimer !== null) window.clearTimeout(hydrationTimer);
window.removeEventListener(sdkLanguageEvent, sync);
if (copyTimer.current) clearTimeout(copyTimer.current);
};
}, [available]);
export function CodeGroup({
snippets,
filename,
isBash = false,
}: {
snippets: Snippet[];
filename?: string;
isBash?: boolean;
}) {
const options = snippets.map(({ label, language }) => ({ label, language }));
const [selected, choose] = useSynchronizedSdkLanguage(options);

const snippet = snippets.find((item) => item.language === selected) ?? snippets[0];

function choose(language: SdkLanguage) {
setSelected(language);
window.localStorage.setItem(sdkLanguageStorageKey, language);
window.dispatchEvent(new CustomEvent(sdkLanguageEvent, { detail: language }));
}

async function copy() {
if (!snippet) return;
await navigator.clipboard.writeText(snippet.code);
setCopied(true);
if (copyTimer.current) clearTimeout(copyTimer.current);
copyTimer.current = setTimeout(() => setCopied(false), 1600);
}

if (!snippet) return null;

return (
<div className="code-group">
<div className="code-toolbar">
<div className="language-tabs" role="tablist" aria-label="Choose SDK language">
{snippets.map((item) => (
<button
aria-selected={item.language === snippet.language}
className={item.language === snippet.language ? "active" : ""}
key={item.language}
onClick={() => choose(item.language)}
role="tab"
type="button"
>
<span className={`language-dot language-dot-${item.language}`} aria-hidden="true" />
{item.label}
</button>
))}
</div>
<div className="code-actions">
{filename && <code>{filename}</code>}
<button onClick={copy} type="button" aria-label="Copy code">
{copied ? "Copied" : "Copy"}
</button>
</div>
</div>
<pre role="tabpanel" tabIndex={0}>
<code>{snippet.code}</code>
</pre>
</div>
<CodeBlock
code={snippet.code}
isBash={isBash}
label={filename}
language={snippet.language}
languageControl={<SdkLanguageTabs onSelect={choose} options={options} selected={snippet.language} />}
/>
);
}

Expand Down
76 changes: 0 additions & 76 deletions app/components/DocsLayout.tsx

This file was deleted.

Loading
Loading