# How the portal is built

Explore the Astro shell, WU API recipes, React/Vue composition, and the service example with contracts and RPC.

<span id="estructura-del-proyecto"></span>

<span class="section-anchor" id="section-1"></span>

## Project structure

```text
wu-docs/
├── shell/astro.config.mjs       # Astro: configuración del host
├── src/content/docs/           # Manuales del framework y CLI
│   ├── guides/
│   ├── framework/
│   └── cli/
├── src/layouts/                # Composición del documento
├── src/components/             # Controles Lit del portal
├── src/pages/                  # Rutas y generación estática
├── apps/command-lab/           # Microfrontend React
├── apps/runtime-lab/           # Microfrontend Vue
├── apps/systems-lab/           # Ejecutor e infraestructura del servicio
├── apps/api-lab/               # WU recipes with owned instances in the host document
├── apps/backend-lab/           # Implementación del proveedor RPC
├── examples/                   # SSR, IA local y relay MCP
├── packages/lab-ui/            # Controles Lit de los laboratorios
├── scripts/build-apps.mjs      # Empaquetado de los módulos ESM
├── public/microfrontends/      # Salida generada de las apps
├── packages/backend-ui/        # Cliente e interfaz de Servicios y RPC
└── dist/                       # Sitio estático compilado
```

Astro's `srcDir` points from `shell/` to `../src`. This keeps an identifiable shell without hiding documentation content inside a client application.

<span id="desarrollo"></span>

<span class="section-anchor" id="section-2"></span>

## Development

```sh
npm ci
npm run dev
```

The lockfile pins published WU Framework 4.0.0 from npm for both `wu-framework` and the `wu-framework-release` alias. The homepage, labs and downloads use this release. Composition and Services and RPC retain an exact CDN URL and a fallback package of the same version.

`npm run dev` builds laboratories and starts Astro. Markdown, host-component, and style changes flow through the development server. After editing apps or shared UI, run `npm run build:apps` and reload the laboratory.

<span id="build-reproducible"></span>

<span class="section-anchor" id="section-3"></span>

## Reproducible build

```sh
npm run build
npm run preview
```

The first step bundles applications, runners, and Lit components. Astro then generates documents, search, the API explorer, and example pages. The service includes execution artifacts; the normal build does not require Zig. Everything needed to serve the portal is in `dist/`.

The npm scripts build this documentation repository. For a workspace created with WU CLI, follow the conventions and configuration of [wu build](/docs/cli/build/).

<span id="añadir-un-capítulo"></span>

<span class="section-anchor" id="section-4"></span>

## Adding a chapter

Create Markdown under `src/content/docs/` with valid frontmatter:

```yaml
---
title: Título del capítulo
description: Qué aprenderá el lector en esta página.
section: Framework
order: 20
---
```

Use `##` for navigable sections and `###` for subsections. Astro derives the sidebar index and previous/next links from the collection. The route comes from the filename: `framework/ejemplo.md` produces `/docs/framework/ejemplo/`.

The search index includes title, description, and full body. It needs no search service and sends no queries to third parties. The interface searches locally after loading `/search.json`.

<span id="rutas-de-los-ejemplos"></span>

<span class="section-anchor" id="section-5"></span>

## Example routes

| Route | Purpose |
| --- | --- |
| `/labs/` | Eight WU API recipes with observable checks and cleanup |
| `/labs/api/` | Compatible access to the same recipe laboratory |
| `/labs/composition/` | Two WU hosts: React builder and Vue inspector |
| `/labs/backend/` | Services and RPC: client, contract, and provider |

The [Running the examples](/docs/guides/running-examples/) guide provides a reading and practice path. The `/api/` explorer is the signature and contract reference; each example links its relevant chapter.

<span id="composición-y-lifecycle-reales"></span>

<span class="section-anchor" id="section-6"></span>

## Real composition and lifecycle

The shell imports the runtime on the client. Each module exposes `register(wu)` and defines lifecycle. The host initializes configuration with manifests and grants, then mounts the app in a dedicated container.

In [Composition](/labs/composition/), mount/unmount controls call the actual WU lifecycle. The React builder and Vue inspector share `docs.lab.counter`, `docs.lab.lastCommand`, and `docs:lab:*` events during the same visit. Each app receives a scoped facade and releases listeners and its framework root on unmount. Changing documents resets the context; the example has no remote persistence.

The [API laboratory](/labs/) runs each recipe in its own WU instance within the current document. It mounts fixtures directly in Shadow DOM and releases their resources when finished. Composition registrations remain independent. The receipt distinguishes assertions, confirmed cleanup and resources still pending. Only fixed documentation code runs.

[Services and RPC](/labs/backend/) mounts two applications with separate grants. The client consumes a versioned contract and requests a provider response. The [service guide](/docs/guides/browser-backend/) explains identity, versions, cancellation, responses, and provider removal.

`apps/systems-lab/` retains the Worker executor, compiled guests, and test fixtures. The service reuses that WASM/WASI infrastructure to process browser data; no third Systems Lab app mounts in the public UI. This implementation decision does not change the WU contract consumed by the client.

SSR, AI, and MCP examples are included in `examples/`. The build generates a portable ZIP at `/examples/wu-server-recipes.zip`, with an npm manifest and tests. The static portal does not automatically start an MCP relay.

<span id="lectura-y-accesibilidad"></span>

<span class="section-anchor" id="section-7"></span>

## Reading and accessibility

Manual content is delivered as static HTML. Navigation and text work without JavaScript. Search, copy buttons, and the laboratory require JavaScript.

There is a skip-content link, landmarks, active-page state, visible focus, and reduced motion. On narrow screens, the chapter index becomes a scrollable strip and search can take you directly to any chapter.

<span id="política-editorial"></span>

<span class="section-anchor" id="section-8"></span>

## Editorial policy

Each chapter explains purpose, signature, configuration, examples, and limits. Capabilities present in types but absent from public exports are identified. Snippets must use existing APIs and link the complete contract.

Framework and CLI manuals also live alongside their code. When a contract changes, update its reference, examples, and tests, then regenerate the portal. See [versions and distribution](/sources/) before changing runtime version.

<span id="documentación-en-cuatro-idiomas"></span>

<span class="section-anchor" id="section-9"></span>

## Documentation in four languages

English is the portal's primary language. The selector preserves the chapter, filters, and current section when switching to Simplified Chinese, Portuguese, or Spanish. Language links also work without JavaScript; search and laboratories require JavaScript.

| Language | Route prefix |
| --- | --- |
| English | `/` |
| Simplified Chinese | `/zh-cn/` |
| Portuguese | `/pt/` |
| Spanish | `/es/` |

Astro generates every chapter and its Markdown download in all four languages. Each page has its own `lang`, canonical URL, and `hreflang` links; the sitemap connects its versions. The search index contains text and links for the active language.

Manual and API entry translations live in `src/i18n/`. The generator combines those translations with the shared code blocks to produce the `src/content/localized/` collection. Shared templates in `src/views/` use explicit messages for their controls and text. The shell sets the language before loading the React, Vue, and Lit applications; the laboratory runner also receives the language in its URL.

Module paths, assets, and downloadable ZIPs are shared across languages. Commands, app names, channels, permissions, and literal messages in example code retain their values: translate the explanation, but preserve what the reader must copy or verify. That is why all four counter guides download the same executable files.

To update a translation, run `npm run i18n:extract`, fill in the missing keys, and run `npm run i18n:build`. `npm run check:i18n` checks coverage and verifies that translations preserve code, links, tables, and placeholders. `npm run test:i18n` checks routes and interactive flows with a running portal server. The production build fails if a required translation is missing.