Web Device does not have one context-free, eternal component catalog. A component is resolved from layered sources, and the exact contract belongs to the manifest.json and renderer implementation in the target runtime/theme/site.
This page is a resolution and authoring guide with concrete layout-component examples (source + real layout proof routes). The full one-component-per-page catalog from the reference matrix lives under theme components and site components (and siblings). Do not treat this page as a link-only hub; do not treat the catalog hubs as a substitute for this how-to.
Sample contract (layout path)
This page is a layout-component sample path, not a Markdown-directive live page. Layout components render only when a layout.aup (or named layout) mounts them into a page shell. The tables and fences below are copyable author source; the real render surface is a site page that already mounts the component, not a second fake HTML mock inside this document.
| Field | Value |
|---|---|
| Purpose | Resolve and author theme/site layout components with explicit empty states |
| Boundaries | Not Markdown directives; not AUP document primitives; no invented props beyond manifest |
| Author entry | layout.aup / named layouts/*.aup · component … component=… |
| Surface | layout (and narrow); site pages that use the component |
| Public status | released for components this site actually mounts |
| Fallback / failure | Empty items → emptyText line (or nothing if emptyText=""); empty breadcrumb props → no nav |
| Verification | Manifest paths · live site routes listed below · arc --version = 2.0.0-beta.32 |
Resolution layers
For the current runtime, the resolver assembles a component from:
- the runtime surface;
themes/default/components;- an optional active theme overlay;
- the site’s
.web/components.
Same-named files from a later layer override earlier files. This lets a site override a provided component narrowly, but it also means a component name mentioned in an older article is not automatically a portable contract for every theme/version.
Keep three component surfaces separate
| Surface | What proves its contract | Current documentation path |
|---|---|---|
| Markdown in a content item | Content-reader syntax and its rendered document result | Web Device Content Markdown |
| AUP primitive on a target | That target's renderer, capability boundary, and acceptance | Keep its target-specific evidence separate from this Web layout reference |
.web or theme component | Its resolved manifest, renderer, layout section, and page result | This page and Use and override components |
Do not promote an example from one surface into a contract for another. A Markdown card is not a .web component API, and a primitive accepted by an AUP parser is not automatically a layout section.
content-card (theme + site override)
Resolution: default theme themes/default/components/content-card/ · this site may override via blocklets/arcblock/.web/components/content-card/.
Manifest props (author-facing): title, description, eyebrow, items, basePath, variant, readMoreHref, emptyText, headingLevel, itemHeadingLevel.
items entries commonly carry title / slug / excerpt / category (or meta.*). No slug means the card is not a destination link (unlinked chrome, not a dead /#/ anchor).
Author source (layout fragment)
component reading slot=featured-reading component=content-card \
variant=fleet \
title="Featured" \
description="Hand-picked entries" \
basePath="/$locale/" \
emptyText="No content has been published yet." \
items=[{title: "Example", category: "Guide", excerpt: "Short blurb", slug: "articles/example"}]Empty list with an explicit message:
component reading slot=featured-reading component=content-card \
title="Featured" \
emptyText="No content has been published yet." \
items=[]When another surface owns the list chrome (for example search results), pass emptyText="" so this component renders nothing for the empty state instead of a second empty line.
Real render surface (not this docs body)
| Locale-agnostic proof | Notes |
|---|---|
Site home / product landings that mount content-card | e.g. /en/, product pages under pages/*/layout.aup |
| Empty state | Only visible when items is empty and emptyText is non-empty |
This Markdown page does not live-render content-card; claiming a screenshot mock here would break the live-example contract.
Failure and limits
| Situation | Expected result |
|---|---|
items=[] and default emptyText | One empty-state line (“No content has been published yet.” unless overridden) |
items=[] and emptyText="" | No empty-state node |
Item without slug | Unlinked card chrome |
| Invented prop not in manifest | Not a portable contract — confirm in target manifest.json / render.js |
page-breadcrumb (site component)
Resolution: site-only blocklets/arcblock/.web/components/page-breadcrumb/ (not a default-theme universal catalog entry).
Manifest props: items ([{ label, href }] — href without locale prefix; last item is current), currentLabel (trailing crumb, often $meta.name), collection (today: events for layouts that cannot resolve an i18n block).
Author source (layout fragment)
From this site’s event detail layout (pages/events/[slug]/layout.aup):
component crumb slot=purpose component=page-breadcrumb \
items=[{label: "Events", href: "/events/"}] \
currentLabel=$meta.namecurrentLabel is a top-level prop because $meta.* only resolves at a prop’s own top level. Do not nest $meta.name only inside a map entry if you need the live page title.
Real render surface
| Route pattern | Notes |
|---|---|
/en/events/<slug>/ (and zh) | Breadcrumb back to Events + current title |
Product / glossary detail layouts that mount page-breadcrumb | Same component, different items |
Failure and limits
| Situation | Expected result |
|---|---|
No items, no collection, no currentLabel | Component returns empty HTML (no nav) |
href on the last crumb | Last crumb still renders as current (non-link) |
Named layout i18n for labels when using only collection | Prefer collection or explicit items — named layouts do not resolve layout i18n the way page layouts do |
Review a component before using it
- Locate the component in the target resolution path.
- Read its
manifest.jsonfor declared contract and itsrender.jsfor the actual accepted props/slots. - Use an explicit empty state for optional lists or media.
- Run the site locally and inspect the actual page in each supported locale and viewport.
Do not paste a component’s implementation into a page just because its manifest is inconvenient to read. If the input contract is unclear, confirm it from the target manifest and runtime before using it; do not invent props.
Verification evidence
| Item | Value |
|---|---|
| Baseline | 2026-08-12 · arc --version → 2.0.0-beta.32 |
| Capability row | docs/aup/capability-matrix.md (internal, non-routed) · content-card · page-breadcrumb |
| Manifest / render | .web/components/content-card/{manifest.json,render.js} · .web/components/page-breadcrumb/{manifest.json,render.js} · theme default content-card |
| Unit catalogs | components hub · surfaces hub · e.g. content-card unit · page-breadcrumb unit |
| Layout sources | e.g. pages/events/[slug]/layout.aup, pages/index/layout.aup, product layout.aup files |
| Docs route (this contract text) | /en/docs/web-device/built-in-components/ · /zh/docs/web-device/built-in-components/ |
| Live layout proof | Open an event detail and home (or product) page after arc service start --blocklet blocklets/arcblock --port 4900 |
| Accept | Breadcrumb/list cards appear on those layout pages; empty-state rules match the table; this docs page stays source-only for layout components |
For authoring a site-owned component, see Use and override components. For AUP tree versus Web layout boundaries, see AUP layout boundary.