Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
# invoice
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The `invoiceTemplate` is the receipt / invoice / order-confirmation
email. It renders a heading carrying the invoice number, a metadata line
(date, optional due date), a line-items table with description /
quantity / unit-price / total columns, a subtotal-tax-total summary, and
an optional "Pay Now" CTA when `paymentUrl` is supplied.
The template is intentionally generic — it does not assume a specific
tax-jurisdiction or currency formatting; consumers pass pre-formatted
strings (date, currency symbol) and pre-computed numbers (subtotal,
tax, total). The template focuses on layout, not arithmetic.
## Features
- Line-items table with description, quantity, unit price, total columns.
- Subtotal + optional tax + total summary at right-align.
- Optional `paymentUrl` renders a "Pay Now" CTA.
- Currency symbol is configurable (`currency` defaults to `"$"`).
- Optional `dueDate` appears alongside the invoice date.
## Usage: Basic
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { invoiceTemplate } from "@suaveplan/email-templates/templates";
renderToHtml(invoiceTemplate, {
recipientName: "Jane",
invoiceNumber: "INV-001",
invoiceDate: "2026-01-15",
items: [
{ description: "Pro plan – Jan 2026", quantity: 1, unitPrice: 29, total: 29 },
],
subtotal: 29,
total: 29,
});
```
## Usage: Advanced
A multi-line invoice with tax, a due date, a payment CTA, and a
non-USD currency:
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { invoiceTemplate } from "@suaveplan/email-templates/templates";
renderToHtml(invoiceTemplate, {
recipientName: "Jane",
invoiceNumber: "INV-001",
invoiceDate: "2026-01-15",
dueDate: "2026-01-31",
currency: "€",
items: [
{ description: "Pro plan – Jan 2026", quantity: 1, unitPrice: 29, total: 29 },
{ description: "Add-on: extra seat", quantity: 2, unitPrice: 5, total: 10 },
],
subtotal: 39,
tax: 3.9,
total: 42.9,
paymentUrl: "https://billing.example.test/pay?invoice=INV-001",
});
```
## API Reference
| Symbol | Kind | Description |
| ----------------- | -------- | ---------------------------------------------------- |
| `invoiceTemplate` | const | `EmailTemplate<InvoiceProps>`. |
| `InvoiceEmail` | function | Component returning a `VNode`. |
| `InvoiceProps` | type | `{ recipientName, invoiceNumber, invoiceDate, dueDate?, items, subtotal, tax?, total, currency?, paymentUrl?, companyName? }` |
| `InvoiceLineItem` | type | `{ description, quantity, unitPrice, total }`. |
## Implementation Notes
Currency formatting uses `Number.prototype.toFixed(2)` — locale-agnostic
two-decimal-place rendering. Consumers needing locale-aware grouping
separators (e.g. `1,234.56` vs `1 234,56`) should pre-format the strings
upstream; the template intentionally does not depend on `Intl.NumberFormat`
because email-template environments span Node, Bun, and browsers where
the Intl data sets vary.
The line-items table renders a single `<tbody>` per call; the table
header sits in its own `<thead>` so accessibility scanners report the
correct table-with-headers structure even though most email clients
ignore the distinction.

View File

@@ -0,0 +1,83 @@
# notification
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The `notificationTemplate` is the generic system-notification email — a
configurable severity callout suitable for product-health alerts,
audit-trail events, account-status changes, and similar operational
messages. The `level` prop drives both the accent border colour and the
container background, giving recipients an at-a-glance severity cue.
## Features
- Four severity levels — `info`, `success`, `warning`, `error` — each
selecting a distinct accent / background colour pair.
- Optional `timestamp` (rendered as a muted caption above the action).
- Optional `action` button (`{ label, url }`).
- Subject derives from the `title` prop.
- Validation: unknown level raises `EmailTemplatesError(INVALID_OPTIONS)`
and bumps an OTel counter.
## Usage: Basic
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { notificationTemplate } from "@suaveplan/email-templates/templates";
renderToHtml(notificationTemplate, {
recipientName: "Jane",
title: "Heads up",
message: "Your subscription renews tomorrow.",
level: "info",
});
```
## Usage: Advanced
A warning notification with a timestamp and a follow-up action:
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { notificationTemplate } from "@suaveplan/email-templates/templates";
renderToHtml(notificationTemplate, {
recipientName: "Jane",
title: "Failed login from a new device",
message: "We blocked an attempt from a device we don't recognise. If this was you, you can dismiss this message.",
level: "warning",
timestamp: "2026-05-25 14:32 UTC",
action: {
label: "Review device activity",
url: "https://app.example.test/security/devices",
},
});
```
## API Reference
| Symbol | Kind | Description |
| ----------------------- | -------- | ---------------------------------------------------- |
| `notificationTemplate` | const | `EmailTemplate<NotificationProps>`. |
| `NotificationEmail` | function | Component returning a `VNode`. |
| `NotificationProps` | type | `{ recipientName, title, message, level?, action?, companyName?, timestamp? }` |
| `NotificationLevel` | type | `"info" \| "success" \| "warning" \| "error"`. |
| `NotificationAction` | type | `{ label, url }`. |
## Implementation Notes
The accent colour for `info`/`success`/`warning`/`error` resolves from
the theme's colour palette (`primary` for info; `success`/`warning`/`error`
respectively). The container background, however, is a fixed lighter
tint per level — those values are not in the theme because they're
visually-tuned washes specific to this template's callout pattern.
Consumers wanting a theme-driven wash can override via `EmailContainer`
directly.
The accent-bar effect is achieved with a `<div>` carrying
`border-left: 4px solid <accent>`. The bar lives inside the
`EmailContainer` cell so the container's themed border-radius rounds the
outer edges while the bar stays sharp.

View File

@@ -0,0 +1,83 @@
# password-reset
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The `passwordResetTemplate` is the canonical password-reset message. It
explains the request, exposes a reset CTA, communicates the link's
expiry, and includes a "you can safely ignore" caution to reassure
recipients who did not initiate the request.
The template reproduces the reset URL as plain text underneath the CTA
button — a deliberate redundancy that ensures recipients on
text-stripping clients (some webmail security scanners) can still
complete the flow.
## Features
- Themed reset CTA pointing at `resetUrl`.
- Configurable `expiresInMinutes` (defaults to `60`).
- Tinted callout container with the "safely ignore" caution copy.
- Plain-URL fallback below the divider.
- Footer with injectable `Clock`.
## Usage: Basic
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { passwordResetTemplate } from "@suaveplan/email-templates/templates";
const { html, text, subject } = renderToHtml(passwordResetTemplate, {
recipientName: "Jane",
resetUrl: "https://app.example.test/reset?token=abc",
});
```
## Usage: Advanced
A 30-minute expiry tied to a tenant-specific brand:
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { createTheme } from "@suaveplan/email-templates/theme";
import { passwordResetTemplate } from "@suaveplan/email-templates/templates";
const theme = createTheme({
colors: { primary: "#22d3ee" },
branding: { companyName: "Acme" },
});
renderToHtml(
passwordResetTemplate,
{
recipientName: "Jane",
resetUrl: "https://acme.test/reset?token=abc",
expiresInMinutes: 30,
companyName: "Acme",
},
{ theme },
);
```
## API Reference
| Symbol | Kind | Description |
| ------------------------ | -------- | ---------------------------------------------------- |
| `passwordResetTemplate` | const | `EmailTemplate<PasswordResetProps>`. |
| `PasswordResetEmail` | function | Component returning a `VNode`. |
| `PasswordResetProps` | type | `{ recipientName, resetUrl, expiresInMinutes?, companyName? }` |
## Implementation Notes
The 60-minute default mirrors the most common security-team-approved
upper bound for password-reset links; tenants needing tighter security
should pass an explicit `expiresInMinutes` and ensure their token-issue
back-end uses the same value.
The "safely ignore" line lives inside the tinted callout to visually
separate it from the CTA, which discourages anxious recipients from
clicking the reset link they did not request — a known social-engineering
attack vector when the caution is text-only.

View File

@@ -0,0 +1,83 @@
# verification
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The `verificationTemplate` is the standard email-address verification
flow message. It greets the recipient, optionally displays a one-time
code in a centred tinted container with tracked letter-spacing for
readability, exposes the verify-link CTA, and includes an expiry
notice.
The template handles both code-only and link-only verification flows by
making the `code` field optional. When omitted, the code container is
skipped entirely.
## Features
- Optional one-time code rendering in a tinted container (32 px,
bold, 8 px letter-spacing — the conventional "OTP display" treatment).
- Configurable `expiresInMinutes` (defaults to `30`).
- Themed verify-email CTA pointing at `verificationUrl`.
- Footer with injectable `Clock` for deterministic year.
- "If you didn't create an account" caution paragraph.
## Usage: Basic
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { verificationTemplate } from "@suaveplan/email-templates/templates";
const { html, text, subject } = renderToHtml(verificationTemplate, {
recipientName: "Jane",
verificationUrl: "https://app.example.test/verify?token=abc",
code: "ABC123",
});
```
## Usage: Advanced
Link-only verification with a tighter expiry and a tenant-specific
brand:
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { createTheme } from "@suaveplan/email-templates/theme";
import { verificationTemplate } from "@suaveplan/email-templates/templates";
const theme = createTheme({ branding: { companyName: "Acme" } });
renderToHtml(
verificationTemplate,
{
recipientName: "Jane",
verificationUrl: "https://acme.test/verify?token=abc",
expiresInMinutes: 5,
companyName: "Acme",
},
{ theme },
);
```
## API Reference
| Symbol | Kind | Description |
| ----------------------- | -------- | ------------------------------------------------- |
| `verificationTemplate` | const | `EmailTemplate<VerificationProps>`. |
| `VerificationEmail` | function | Component returning a `VNode`. |
| `VerificationProps` | type | `{ recipientName, verificationUrl, code?, expiresInMinutes?, companyName? }` |
## Implementation Notes
The empty-string check on `code` is intentional: an upstream sanitiser
that strips whitespace from a missing-value form field commonly produces
`""` rather than `undefined`. Treating both as "no code" keeps the
template stable against caller-side variance without requiring a Zod
schema at the boundary.
The OTP container's `letter-spacing: 8px` is wide enough that 6-digit
codes render as visually-grouped pairs in most clients, which improves
copy-by-eye accuracy. The font size (32 px) is large enough to remain
legible on a phone-sized email preview without dominating the layout.

View File

@@ -0,0 +1,84 @@
# welcome
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The `welcomeTemplate` is the canonical post-signup onboarding email. It
greets the recipient by name, summarises why they received the email,
exposes the primary CTA, and reproduces the CTA URL as plain text
underneath in case the button does not survive a link-rewriting proxy.
The template is intentionally minimal — it covers the most common
post-signup flow. Consumers needing additional structure (feature
highlights, social-proof imagery, multi-step onboarding) should compose
their own template using the same components.
## Features
- Themed heading + body copy + primary CTA + plain-URL fallback +
divider + footer.
- Configurable `ctaLabel` (defaults to `"Get Started"`).
- Configurable `companyName` (defaults to `theme.branding.companyName`).
- Subject function: `Welcome to ${companyName}!`.
- Optional preview text via the `previewText` prop.
## Usage: Basic
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { welcomeTemplate } from "@suaveplan/email-templates/templates";
const { html, text, subject } = renderToHtml(welcomeTemplate, {
recipientName: "Jane",
ctaUrl: "https://app.example.test/get-started",
});
```
## Usage: Advanced
Brand-customised with a preview text and a non-default CTA label:
```ts
import { renderToHtml } from "@suaveplan/email-templates/renderer";
import { createTheme } from "@suaveplan/email-templates/theme";
import { welcomeTemplate } from "@suaveplan/email-templates/templates";
const theme = createTheme({
colors: { primary: "#22d3ee" },
branding: { companyName: "Acme Corp" },
});
const result = renderToHtml(
welcomeTemplate,
{
recipientName: "Jane",
ctaUrl: "https://acme.test/welcome",
ctaLabel: "Continue",
previewText: "You're in! Let's get you set up.",
},
{ theme },
);
```
## API Reference
| Symbol | Kind | Description |
| ------------------ | -------- | ---------------------------------------------------- |
| `welcomeTemplate` | const | `EmailTemplate<WelcomeProps>`. |
| `WelcomeEmail` | function | Direct component access (returns a `VNode`). |
| `WelcomeProps` | type | `{ recipientName, ctaUrl, ctaLabel?, companyName?, previewText? }` |
## Implementation Notes
The plain-URL fallback paragraph is rendered as a muted caption — small
type, low contrast — so it doesn't compete with the CTA visually. The
fallback line uses the same `ctaUrl` value as the button, so any later
URL change touches one source of truth.
The footer's clock is intentionally not threaded through this template
— consumers wanting a deterministic copyright year supply a `clock` to
`renderToHtml`, which passes it to the component as part of the merged
props bag.