Skip to content

Documentation Style Guide ​

Connectum documentation serves two readers at once: someone completing a task for the first time and someone looking up one exact interface or option. Pages stay useful when each has one reader outcome, one content type, and one canonical owner.

Verify technical claims against the implementation in packages/<package>/src, exports, and package.json. Documentation and accepted specifications own the behavioral contract. If the implementation contradicts an accepted decision, record both sources and obtain the contract owner's decision before rewriting either side. Generated TypeDoc is the canonical exact API reference; hand-written pages teach, explain, and route readers to it.

Content types ​

Choose one type before drafting a page. Do not combine a tutorial, an exhaustive reference, and architecture history on one URL.

TypeReader outcomeRequired contentExcludeLocation
TutorialComplete a bounded learning pathPrerequisites, goal, sequential steps, verification, next stepsOptional production hardening, exhaustive optionsen/guide/**
How-toAccomplish one real taskProblem, prerequisites, focused steps, verification, failure pathProduct pitch, unrelated alternatives, full API tablesen/guide/**
ConceptUnderstand a mental model or decisionContext, model, boundaries, links to tasksStep-by-step setup, exhaustive symbolsen/guide/**
Section entryChoose a task and a reading pathScope, relationships between topics, canonical child linksRepeated child explanations, separate package marketingen/guide/**
ReferenceLook up exact signatures, fields, defaults, or compatibilityGenerated symbols or a deliberately maintained matrixNarrative tutorials, duplicated rationaleen/api/** or a named canonical matrix
MigrationDetermine whether an upgrade requires actionAffected versions, required action, before/after, verificationComplete release history and unrelated featuresen/migration/**
ADRUnderstand why an architectural decision was madeStatus, context, decision, consequences, alternativesCurrent task instructions that belong in guidesen/contributing/adr/**

Contributor workflow pages are a separate audience. They describe how to work on Connectum itself and use the repository's supported Node.js and pnpm toolchain, not consumer-facing runtime or package-manager choices.

Canonical navigation and ownership ​

Human-written usage and behavior live in Guides. Installation belongs to the Guide that owns a capability; exact signatures, fields and types are generated from framework source into en/api/. Do not recreate separate package overview pages or a hand-written API landing tree.

The header links to Get started, the Guide-section dropdown, generated API and Builder, in that order. Builder has an outlined treatment. Get started is not repeated inside the dropdown. A linked sidebar section heading is its landing page; do not add a second child link to the same page under another label. Section titles, routes and sidebar membership are defined in .vitepress/guide/navigation.ts; section entry pages use GuideSection for their topic links. Testing is a separate section. Local/remote transport and events belong to Communication. Advanced is not collapsible.

Old package/reference addresses are compatibility routes described in .vitepress/data/site.json. Their fragment maps route earlier links to the canonical material. pnpm docs:routes renders the transition pages, while pnpm docs:routes:check detects drift. They are excluded from search, sitemap and LLM bundles and keep usable destination links without JavaScript. Update the map before moving content; preserve a specific fragment whenever its new owner retains that section. Link new content directly to the owner.

Interceptors has one composition guide and focused policy pages. Reuse the existing Validation guide rather than copying it into a second interceptor article. Keep unit, application-integration and deployed E2E tests distinct: in-process tests do not establish network or TLS behavior.

Overview-first Guides ​

The first page of each Guide sidebar topic teaches one idea before asking the reader to configure it. Keep its opening understandable without following an API reference, expanding a disclosure or watching an animation.

  • Start with a concrete problem and a small mental model. Use a short, labelled visual and, where useful, one code excerpt. Say which imports, generated descriptors or surrounding setup an excerpt assumes.
  • Keep the initial reading path short. Move full setup sequences, exhaustive options, matrices, failure behavior and limitations to a focused page one navigation level deeper. Do not delete technical material to shorten the entry.
  • Link deeper by intent: “Run the example”, “Configure the resolver”, or “Read the complete matrix”. Add that destination beneath the overview in the sidebar.
  • Use the same domain example where concepts meet: Orders asks Inventory for stock. Distinguish an illustration from a live RPC and provide an executable counterpart for a claimed runtime result.
  • Preserve prior fragment URLs. GuideSections renders a native disclosure from .vitepress/guide/sections.json, with an anchored link to each preserved section. It works without JavaScript; hydration also opens a targeted section. Keep those destinations and IDs synchronized when moving or renaming content.

The first-service entry is an overview; its complete manual tutorial lives at Build your first service step by step. Compatibility overviews explain the choice; the canonical exact tables live at Runtime requirements and coverage and Transport support and measurements.

Choose a visual mechanism for the explanation, not a universal animation with different labels. The service catalog uses CatalogAssembly: contract files, generation boundaries, package delivery and merging. The resolver walkthrough shows routing. Share colors, accessibility and motion controls, not choreography.

Do not animate an ordered list of cards with a moving highlight or a repeated caption. Prefer a static diagram that exposes the relationship: a dependency graph, a composition boundary or a request/response sequence. For a section root, cover its subsections and their relationships before focusing on one request. Keep implementation details on the focused pages.

Guide roots embed authored, static SVG from self-contained HTML sources through GuideOverview. The overview must be visible without JavaScript. Regenerate the sources and embeds with node scripts/guide-diagrams.mjs; models live under scripts/guide-diagrams/. Choose a layout for the subject and share only the low-level drawing primitives and the approved Connectum skin. Keep the accepted Server composition separate from its configuration/lifecycle overview.

Other technical diagrams can use the shared Mermaid theme. Both mechanisms need a readable caption; neither should introduce a page-local palette. Keep authored diagrams at their native width in a local scroll frame on phones. Release that minimum width and clipping for print. Do not inflate a narrow graph or return to a universal card model.

For a genuinely causal animation, never move, hide or type the page's explanatory text and code. Provide pause/resume and a native transcript; persist the reader's pause choice across navigation. Pause offscreen/hidden work, keep reduced motion static and clean up on navigation. Explicitly distinguish illustrations from live execution. Captions and complete explanations remain readable without JS.

Start each code/result showcase with a successful scenario. Place it first in the controls and select it by default, including without JavaScript and after route navigation. Failure scenarios follow the successful call.

Use shared styling and lifecycle practices; do not duplicate timers per page. Verify motion and pause behavior in a real browser, not only by checking that keyframes exist. Keep the existing resolver walkthrough for its routing scenes. Branching flows, runtime internals and complex relationships deeper in the Guide still use the diagram rules below.

Catalogs describe known contracts; they do not discover running services. Resolvers select remote transports; reflection exposes schemas at a known server address. Do not use “service discovery” as if those were the same job.

Prose and README guidance ​

Write checklists with - [ ] and - [x]. The shared Markdown renderer emits labelled, read-only native checkboxes, including inside runtime and package-manager tabs. Their checked state comes from the source; checking off a personal copy is not saved by the documentation site. Keep ordinary lists as ordinary list items.

  • Put source examples, executable statements and configuration objects in fenced code blocks with an explicit language. Use VitePress's native highlighting, language label, line numbers and copy control. Inline code is for identifiers, option names and file paths, not complete configuration or call examples.

  • Vue-rendered examples follow the same rule: render a fenced block through the Markdown renderer at build time. Do not interpolate plain text into handwritten pre/code elements or replace syntax highlighting with a single code color. Check the actual tokens in both themes, including collapsed details and no-JS.

  • Start with the reader's task or the result the page explains. Prefer concrete verbs and short sentences over greetings, filler, and claims such as “production-ready” or “industry-leading” unless the page defines evidence for them.

  • State technical claims at the level supported by their source. Link to the canonical guide or generated API for full behavior instead of repeating a second explanation.

  • Keep package and tool versions out of explanatory prose and demo labels. Pin reproducible inputs in manifests, lockfiles and generated provenance. Include a version in prose only when it defines a compatibility requirement or migration; keep required version fields in actual protocol documents and executable examples.

  • A repository README identifies that repository, gives the commands needed to start or validate its work, and links to the canonical user documentation. Keep task-specific operational instructions where maintainers need them; do not duplicate a guide or an exhaustive API catalog.

Page templates ​

Tutorial ​

md
---
title: <Outcome>
description: <What the reader will have working>
docType: tutorial
---

# <Outcome>

<One paragraph: goal, expected result, and approximate scope.>

## Prerequisites
## 1. <First step>
## 2. <Next step>
## Verify the result
## Troubleshooting
## Next steps

Keep the mandatory path linear. Production options belong in Next steps unless the tutorial cannot succeed safely without them.

How-to ​

md
---
title: <Verb + task>
description: <Specific result>
docType: how-to
---

# <Verb + task>

## Before you begin
## Configure <task>
## Verify
## Troubleshooting
## Learn / Configure / API reference

Concept ​

md
---
title: <Concept>
description: <Decision or model this page clarifies>
docType: concept
---

# <Concept>

## Why it exists
## Mental model
## Boundaries and trade-offs
## Apply the concept

Section entry ​

md
---
title: <Guide section>
description: <Tasks covered by this section>
docType: section
---

# <Guide section>

<Scope and a short reading path. Explain how the topics relate.>

## Topics

<GuideSection section="<section-id>" />

The shared section definition owns the topic links. Keep task instructions on the child pages and link exact interfaces or functions to generated TypeDoc.

Migration ​

md
---
title: <Version or capability migration>
description: <Who must act>
docType: migration
---

# <Migration>

## Does this apply to you?
## Required changes
## Before and after
## Verify the upgrade
## Related release notes

ADR ​

Use Status, Context, Decision, Consequences, Alternatives, and References. An ADR records rationale; link to current guides rather than turning the ADR into a second operational manual.

An accepted ADR is a dated record. Its Context, Decision, Consequences, and Alternatives (including ratings, estimates, diagrams, and checklists) describe the decision at its date and are not rewritten. Amend an ADR only in these ways:

  • The decision changed. Add ## Current Decision (YYYY-MM-DD) directly after Status, rename the original ## Decision to ## Original Decision (YYYY-MM-DD), and mark each superseded passage in place with one sentence that points to the current decision. Keep the original text. A decision on a new subject is a new ADR that names the ADR it extends.
  • A statement was wrong when it was written (it contradicts the ADR itself, or describes behavior the code never had). Correct it in place and name the correction in the Changelog.
  • A statement became outdated later (code, versions, package inventory, dependency kinds). Add a dated > **Update (YYYY-MM-DD):** note under Status or at the sentence; do not rewrite the sentence. Historical counts and estimates stay; the ADR index states that they are not current guarantees.
  • Headings are anchors. Do not remove sections or headings. Rename a heading only when no page in the three repositories links to its anchor, and record the old heading in the Changelog.
  • Diagrams. Converting a text diagram to Mermaid without changing what it shows is allowed and is recorded in the Changelog; every name in the original diagram stays.
  • Every amendment adds a Changelog row (add the table if the ADR has none). A new or changed decision, or a correction of a wrong statement, also updates the Status line and the index row: Accepted -- YYYY-MM-DD; revised -- YYYY-MM-DD. A pointer or an Update note that leaves the decision as it was needs the Changelog row only.
  • A Current Decision that depends on an unreleased runtime change names the release and the framework pull request, so readers of the published version can tell which behavior they have.

When you change code ​

A change that alters what a user sees updates the documentation in the same piece of work, not in a follow-up. Update each of these that the change touches:

  1. JSDoc on every changed public symbol.
  2. The package README when the public API, installation, or the quick start changed.
  3. The guide that teaches the changed behavior, and the package hub if its entry points changed.
  4. An example when the usage pattern changed or the feature is new.
  5. The ADR when the change alters the decision it records. Amend it by the rules in the ADR section above (a Current Decision, not a rewrite of history); a decision on a new subject is a new ADR.

Where each one lives:

MaterialRepositoryLocation
JSDocconnectumIn the source of packages/<name>/src
Package READMEconnectumpackages/<name>/README.md
Guides, package hubs, migration guides, ADRsdocs (this repository)en/guide, en/packages, en/migration, en/contributing/adr
ExamplesexamplesThe examples repository
API referencedocs, generateden/api, produced by TypeDoc from the JSDoc; never edited by hand

Regenerate the API reference with pnpm docs:api in the framework repository after you change JSDoc; the TypeDoc run treats every warning as an error, so a broken {@link} fails it. pnpm docs:check executes the documentation's code examples as a consumer of the packed packages, which catches an example that no longer matches the code. It packs the dist of every package as it is and does not build, so run pnpm build first after any source edit; otherwise it checks the examples against stale output. Both commands are listed in CLI Commands.

Canonical ownership ​

Target release ​

The site documents its declared release line, including features implemented for that release. Describe their behavior directly. Do not label them Preview, upcoming or unpublished because the npm latest tag points to an older release. Verify examples against the target framework source and build. Keep genuine migration boundaries and runtime requirements; do not invent missing features.

When information could appear in several places, these locations win:

InformationCanonical ownerOther pages may contain
Function signatures, option fields, exported types, defaultsGenerated API referenceA task-essential subset plus a direct API link
Node.js/Bun support and known runtime limitationsRuntime requirements and coverageA one-line prerequisite and canonical link
Request/response versus events trade-offsMechanism examples and failure behaviorA contextual recommendation and link
Broker comparisonEvent AdaptersAdapter-specific setup only
Package installation and orientationPackage hubA command required by the current task
Required upgrade actionsMigrationA release-note link to the migration
Architectural rationaleADRCurrent behavior and an ADR link

If two pages contain the same complete table or explanation, keep the better canonical version and replace the other with task context plus a link.

Learn / Configure / API reference pattern ​

End module and task pages with routes that match the reader's next intent:

md
## Learn / Configure / API reference

- **Learn:** [How authentication fits the request lifecycle](/en/guide/auth)
- **Configure:** [Configure JWT authentication](/en/guide/auth/jwt)
- **API reference:** [`JwtAuthInterceptorOptions`](/en/api/@connectum/auth/interfaces/JwtAuthInterceptorOptions)

A guide may omit one route if it is genuinely irrelevant. A package hub should normally include all three. Link to the exact TypeDoc symbol when the text names one; link to the package API index only when several symbols are equally relevant.

Page and navigation conventions ​

  • Add title, description, and docType frontmatter to hand-written pages.
  • Use one H1. Keep headings descriptive and preserve established anchors during rewrites; use explicit {#legacy-anchor} headings or an anchored compatibility disclosure when material moves deeper.
  • Use root-relative internal links beginning with /en/, without .md.
  • Put every user-facing page in a logical sidebar group, unless it is a documented compatibility page intentionally excluded from navigation.
  • Use task language in navigation. Package dependency layers belong in architecture content, not as the primary package taxonomy.
  • Use ::: tip, ::: info, ::: warning, and ::: danger for meaningful callouts. Do not use a callout as decoration.
  • Generated files under en/api/** are never edited manually.

Runtime variants ​

Use ::: runtime only when execution differs between Node.js and Bun. Runtime is independent from the tool used to install dependencies.

md
::: runtime
== node
```bash
node --test tests/
```
== bun
```bash
bun test tests/
```
:::

Rules:

  • A grouped block contains both == node and == bun with equivalent outcomes.
  • Do not put headings inside variant blocks; duplicate headings create unstable outline anchors.
  • Use a normal block when the commands are identical.
  • A single-runtime block such as ::: runtime bun is a short, always-visible compatibility note.
  • Verify Bun commands before publishing them.
  • Contributor pages do not use consumer runtime variants.

Package-manager variants ​

Use ::: pm for installation or script commands that differ among npm, pnpm, and bun. Each group must contain all three tools and perform the same operation.

md
::: pm
== npm
```bash
npm install @connectum/core
```
== pnpm
```bash
pnpm add @connectum/core
```
== bun
```bash
bun add @connectum/core
```
:::

Hoist commands that do not vary. Do not nest package-manager blocks inside code groups. Build-time validation checks completeness, the command tool, and semantic parity between tabs.

Source accuracy ​

Diagrams and process flows ​

Use Mermaid for process flows, state machines, sequences, and architecture diagrams, except for the authored SVG Guide overviews described above and the composition plates below. Do not represent a diagram as aligned text, Unicode arrows, or ASCII boxes inside a plain code fence. Mermaid diagrams inherit light/dark colors, remain readable at narrow widths, and provide a keyboard-accessible fullscreen view.

Use a fenced text block only for literal command output or a file tree. Use a generated image only when the subject cannot be expressed clearly in Mermaid; include useful alt text, preserve the editable source, and verify both themes.

Isometric composition style ​

The composition figure on Server is the visual reference for all isometric figures. Get started uses the same plates with responsive HTML explanations. Keep the subject's layout and meaning; reuse the geometry and skin from scripts/isometric-plates.mjs.

  • Project every vertex with project(x, y, z, origin): [ox + x - y, oy + (x + y) / 2 - z]. This is a 2:1 dimetric projection. Do not draw a shallower diamond, skew the SVG with CSS, or place corners by hand.
  • Use the shared plateModel: a 184 × 184 footprint, radius 12 and thickness 20. Rounded corners project to elliptical arcs with radii r * sqrt(2) and r / sqrt(2). Scale uniformly; do not thicken the side faces independently.
  • Generate faces with partGeometry() and renderPlateFaces(). Paint the opaque silhouette, top, left and right faces, front rim, then the outline. The outline is 1.2 units with rounded joins; the rim is 0.8 units at 0.55 opacity.
  • Include plateStyles and the connectum-isometric class. The module owns both theme palettes. Neutral light faces use paper on top, 7% ink on the left and 15% ink on the right. Dark faces use the module's opaque dark surfaces. Keep the left face lighter than the right. No page-local face colors, translucent solids, gradients, shadows or glow.
  • Give one plate at most data-focal. It uses the shared blue top, side faces and border. Other plates stay neutral. About accents Connectum; Server accents Your services. Color does not replace a name or explanation.
  • Keep one horizontal name outside each plate. Use the site's sans-serif font for names and mono only for code or technical sublabels. Server uses a right label column with 0.8-unit leaders and 2-unit dots; About keeps its semantic HTML headings and prose alongside each decorative SVG, below it on phones. Do not repeat the name on the top face or rotate text into the projection.
  • In an exploded composition, keep the common vertical axis and the shared 60-unit model gap. Responsive HTML rows use their content height instead: preserve About's compact 4px row gap, 16px on phones, and tightly cropped viewBoxes. Do not increase whitespace to compensate for a different prism.

The checked-in HTML files are generated assets consumed by the Vue components. Regenerate both after editing the shared renderer:

bash
node scripts/server-composition.mjs
node scripts/technology-stack.mjs
pnpm guide:test

Review the production pages in both themes and on desktop and mobile. Run scripts/check-technology-stack-browser.mjs against the existing preview with PLAYWRIGHT_MODULE pointing to an installed Playwright module. It compares computed face colors, outlines and rims with Server, checks responsive bounds and text contrast, and exercises no-JS and print views. Server keeps local keyboard-scrollable overflow; About's decorative plates scale with independent HTML text. Preserve all labels and captions without JavaScript. A meaningful SVG needs an accessible title and description; a plate fully explained by adjacent HTML stays aria-hidden="true" and unfocusable.

About has one optional decorative scroll effect. Its SVG plates lift by at most 24, 18 and 12px on desktop, 14, 10 and 6px on phones. Each spends that travel over one plate height as its untransformed top crosses 96px + plate height to 96px in the viewport. This short local range keeps the motion on screen; document length and viewport height do not dilute it. Only the whole decorative SVG translates vertically; its geometry, labels, row heights and gaps stay fixed. The limits and scroll mapping live in stackParallax.ts; useStackParallax.ts schedules one frame per batch of passive scroll events, using untransformed HTML wrappers as its reference. There is no constant frame loop, rotation, zoom or inertia. Work pauses outside the viewport and on hidden pages; unmount removes listeners, observers and pending frames. The effect works without CSS scroll-timeline support, including in Firefox. Do not add it to Server or other diagrams.

Reduced motion, print, no-JS and standalone HTML retain the complete static figure. A short note explains reduced motion or an explicit static link. Use ?motion=static or <html data-motion="static"> for stable captures. Run scripts/check-technology-stack-parallax-browser.mjs --browser chrome and --browser firefox against the existing preview. Test short wheel gestures while the plate remains wholly visible, including its motion relative to its label and neighboring plates. Adding content below must not change the effect. Do not use a full-page or offscreen end position as proof of visible parallax. Test reverse scroll and lifecycle cleanup. Text must remain stationary in document coordinates, moving plates must not touch labels, and a stationary page must produce no autonomous motion.

The shared diagram theme ​

Every diagram is painted by one theme, configured centrally. Write the diagram; do not write its appearance. Typography, node surfaces and borders, subgraph framing, edge routing, arrowheads, edge labels, and the sequence and state primitives all arrive from the shared configuration, in both light and dark mode and in the fullscreen view.

Edges run on the horizontal and vertical axes and turn at rounded corners; converging edges may share a common trunk before separating into their own approaches. This is a property of the shared layout, not a per-diagram choice, and it is why generated diagrams read like the project-authored technical SVGs. A new hand-drawn connector follows the same construction: a quadratic curve whose control point is the corner itself, starting and ending 7.07 units away from it along each segment, reduced to half the segment when a leg is shorter than that.

Never put a literal color in a diagram. A fill:#4a90d9 or stroke:red becomes an inline attribute on the rendered node, which outranks the theme -- the node then keeps its light-mode color when the reader switches to dark. A per-diagram %%{init: ...}%% theme directive is rejected for the same reason. Build validation fails on both.

When a node genuinely needs to stand apart, use one of the five shared variants:

VariantUse for
accentthe subject of the page, or the foundation everything else builds on
positivea success destination or a healthy terminal state
warninga degraded, deferred, or rejected-but-expected path
criticala failure path or an unrecoverable state
muteda de-emphasised element: private, deprecated, or out of scope

Apply one with class or :::, and never let color be the only carrier of the meaning:

A reader who cannot distinguish the colors must still get the same answer from the node text, the edge labels, or the subgraph titles. If the distinction is already carried by structure -- a subgraph named Layer 0: Foundation, for instance -- leave the nodes unstyled rather than repeating it in color.

Styling is not layout ​

The shared theme controls how a diagram looks, never where anything sits. Crossing edges, a label crammed against an arrowhead, a route that implies the wrong order, or a node colliding with an unrelated edge are all defects in the diagram source. Fix them by reordering nodes, reversing an edge, changing the direction, splitting the diagram, or shortening a label. Do not add page-local CSS, and do not move anything after render.

Give arrows room to be seen. A connection needs a visible line segment and an arrowhead that touches neither node; the shared spacing provides this, so a collapsed arrow means the diagram is packing too much into one rank. Prefer TD for anything deeper than about five stages -- a long LR chain scales down to unreadable inside the documentation column, even though the fullscreen view can recover it.

Width is what decides how large diagram text ends up: the documentation column is fixed, so a wide diagram is scaled down and its labels shrink with it. A diagram that has grown wide enough to be unreadable inline is a source problem -- split it, or turn it along the other axis -- not something to fix in configuration.

Documentation contract failures are user-facing defects.

  1. Verify every named symbol, option, field, default, and export against current package source and metadata. Do not document removed APIs.
  2. Check code blocks, imports, .env examples, and diagrams as carefully as prose. Follow each runnable sequence from its stated working directory with its stated dependencies, generated files, and environment. For conditional behavior, verify the condition and any explicit option that overrides the default. Compare the actual response, log, exported value, or exit status with the promised result; successful parsing or a matching symbol name alone is not verification.
  3. The license is Apache-2.0.
  4. Published packages support Node.js >=22.13.0. Consumer projects that execute TypeScript source directly follow the higher development/runtime prerequisite stated by the current Quickstart and Runtime Compatibility page.
  5. The default interceptor order and enabled defaults must agree with current source and ADR-024.
  6. Consumer examples use the generated import extension configured by their buf.gen.yaml; current TypeScript-direct examples use .ts.
  7. Never infer a claim from a test fixture when production source provides the contract.

Redirect and retirement rules ​

The site is currently a static GitHub Pages deployment. A moved route therefore keeps a compatibility page unless the hosting layer gains real HTTP redirects. Before changing a URL:

  1. Record the old route, target, inbound links, and anchors in the migration matrix.
  2. Update internal links to the canonical target.
  3. Keep a compatibility page with a canonical URL and noindex, follow.
  4. Exclude the compatibility page from primary navigation, local search, and LLM navigation outputs.
  5. Preserve fragments where the destination still has an equivalent section.

Do not describe a client-side compatibility page as a permanent HTTP redirect.

Review checklist ​

Reader and structure ​

Accuracy and duplication ​

Variants and accessibility ​

Delivery ​

Documented version and release checklist ​

.vitepress/data/site.json is the single maintained source for the documented Connectum release line. The documentation maintainer updates it in the release documentation change; components must not hard-code a second version string. Runtime floors and environment-specific support belong in the canonical Runtime Compatibility matrix rather than shared site metadata.

For every release line:

  1. Update the documented release line when the portal begins targeting that line.
  2. Regenerate TypeDoc from the targeted framework source; do not hand-edit output.
  3. Add focused migration instructions for required user action.
  4. Review Quickstart, Runtime Compatibility, package hubs, and representative interface links against the released source.
  5. Run route/link/module/variant checks and the production build.
  6. Verify search, sitemap, LLM outputs, and representative user journeys.
  7. Review desktop/mobile light/dark screenshots before deployment.