Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
8400e0b
docs: update README.md for project to major versioned doc links (#7513)
janechu May 12, 2026
71eff8a
feat: propagate <f-template> host attributes onto rendered host eleme…
janechu May 20, 2026
c7ce25e
chore: update dependencies (#7525)
radium-v May 20, 2026
5a98edc
feat(fast-test-harness): propagate shadow DOM options through templat…
radium-v May 20, 2026
1093a70
feat(examples): add CSS-only design system package (#7524)
janechu May 21, 2026
7ba6a16
feat: add todo-mobx-app example with MobX↔FASTElement bridge (#7523)
janechu May 21, 2026
f3eac2b
feat: add chat app example (#7518)
janechu May 22, 2026
5f34c93
feat(examples): unified todo apps with SSR, MobX, and E2E suite (#7424)
janechu May 22, 2026
b104fa7
fix(docs): update example references in documentation and tests (#7527)
radium-v May 22, 2026
4c89b9a
refactor(test-harness): remove parseDefaultValue and CEM-related logi…
radium-v May 22, 2026
d1bf09a
ci: split CD into GitHub release + Azure publish stages, with crate s…
janechu May 26, 2026
18c98d3
chore: update dependencies in package.json (#7533)
radium-v May 27, 2026
8368dcf
chore: adapt cherry-picked commits for v3 architecture
janechu May 27, 2026
f6ecae1
fix(examples): set useDefineForClassFields=false in csr/todo-app
janechu May 27, 2026
27b3eeb
feat(examples): port SSR examples to v3 declarative + hydration pattern
janechu May 27, 2026
a933fb0
fix(fast-element): make declarativeTemplate() generic over the elemen…
janechu May 27, 2026
2f073f3
fix(fast-test-harness): preserve subdirectory structure in generateSt…
radium-v May 28, 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
6 changes: 5 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ Each package includes a DESIGN.md file, read that to gain a general understandin

### Example projects

- `examples/todo-app/` β€” A simple To-Do app demonstrating FAST usage patterns.
- `examples/design-system/` β€” Shared semantic design tokens (`@microsoft/fast-examples-design-system`) consumed by all example apps.
- `examples/csr/todo-app/` β€” A simple To-Do app demonstrating FAST usage patterns and using the shared `@microsoft/fast-examples-design-system` tokens.
- `examples/csr/todo-mobx-app/` β€” A To-Do app demonstrating how to integrate MobX state with `@microsoft/fast-element` using a single `autorun` per component (no custom bridge code).
- `examples/ssr/chat-app/` β€” A declarative FAST chat demo that pre-renders with `@microsoft/fast-build` and streams canned assistant replies into the transcript. Dark theme.
- `examples/ssr/webui-todo-app/` β€” A To-Do app demonstrating FAST declarative HTML with `@microsoft/webui` prerendering and `@microsoft/fast-element`'s `declarativeTemplate()` + `enableHydration()` for client-side hydration. Light theme.

## Skills

Expand Down
15 changes: 14 additions & 1 deletion .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,17 @@ For more information see the [GitHub CLI documentation](https://cli.github.com/m
All CI workflows that run against pull requests are configured to skip draft PRs:

- **GitHub Actions** (`ci-validate-pr.yml`, `ci-validate-platforms.yml`, `ci-validate-rust.yml`): The `pull_request` trigger includes `ready_for_review` in its event types, and each job has a condition that skips execution when the PR is a draft. When a draft PR is marked as ready for review, the workflows will automatically trigger.
- **Azure Pipelines** (`azure-pipelines-bench.yml`, `azure-pipelines-ci.yml`): The `pr` trigger uses `drafts: false` to prevent pipeline runs on draft PRs.
- **Azure Pipelines** (`azure-pipelines-bench.yml`, `azure-pipelines-ci.yml`): The `pr` trigger uses `drafts: false` to prevent pipeline runs on draft PRs.

## Continuous Deployment

Nightly publishing is split into two coordinated jobs so that npm credentials never leave the Azure environment. GitHub Releases are the source of truth, and `deployed/<tag>` git marker tags track which releases have already been published.

- **`cd-github-releases.yml`** (GitHub Actions) runs nightly via cron (`0 8 * * *` UTC, ~12am PST) and on `workflow_dispatch`. It does **not** bump versions or push source changes to `main` β€” version bumps land on `main` through ordinary human-authored pull requests (for example, by running `npm run bump` locally and opening a PR). The cron is scheduled ~1 hour before the Azure CD pipeline (09:00 UTC) so any GitHub releases this job creates are picked up by that same night's publish run. The workflow has two jobs:
1. **`detect`** β€” checks out `main` with `fetch-depth: 0` and runs [`build/scripts/create-github-releases.mjs --check-only`](../../build/scripts/create-github-releases.mjs). The script walks the workspaces tree (no `npm ci` required), computes `${name}_v${version}` for every non-private workspace, and emits `hasMissingReleases=true` if any of those git tags do not yet exist.
2. **`release`** runs only when missing releases exist. Installs Node, the Rust toolchain (for `cargo package`), and the npm workspace dependencies, builds the repo, then runs the script in default mode. For every missing release the script: packs the npm tarball into `publish_artifacts_npm/`, packs the paired Rust crate (if `crates/<crate-name>/Cargo.toml` exists) into `publish_artifacts_crates/`, and creates the GitHub release with both assets attached via `gh release create --target <sha>`. The `gh` CLI creates the git tag atomically with the release, so "tag exists" and "release exists" are always the same fact β€” a failed release is safely retried on the next workflow run, with no orphan tag stranded behind. The script errors if a paired crate's version does not match the npm package's version β€” but this is purely a safety net: the [`postbump` hook in `beachball.config.js`](../../beachball.config.js) rewrites the crate's `Cargo.toml` (and the matching entry in `Cargo.lock`) automatically whenever `npm run bump` bumps the paired npm package, so the two stay in sync from the same commit.
- **`azure-pipelines-cd.yml`** (Azure Pipelines) runs every night at **1am PST (`0 9 * * *` UTC)** with `always: true` so it still runs on no-op nights (it is checking external GitHub state, not repo commits). It is split into two stages so the heavy publish work is skipped on no-op nights:
1. **`Check`** β€” runs [`build/scripts/download-github-releases.mjs --check-only`](../../build/scripts/download-github-releases.mjs). The script lists every git tag matching the beachball-style `${name}_v${version}` pattern that does **not** also have a `deployed/<tag>` counterpart and emits the comma-separated list via Azure Pipelines `setvariable` output variables (`needsDeployment`, `undeployedTags`). No network calls to npm or crates.io.
2. **`Package`** β€” depends on `Check` and runs only when `needsDeployment == 'true'`. Downloads every undeployed release's assets via `gh release download`, sorts them into `publish_artifacts_npm/` (`.tgz`) and `publish_artifacts_crates/` (`.crate`), hands off to `FAST.Release.PipelineTemplate.yml@fastPipelines` for the actual `npm publish` / `cargo publish`, and on success pushes a `deployed/<tag>` git marker tag for each release that was just published. The next nightly run will see those markers and skip the corresponding releases.

Both scripts are thin Node.js wrappers around `gh`, `npm`, `cargo`, and `git` β€” no extra npm dependencies and no custom GitHub API client. Idempotency is enforced entirely through git tags (`${name}_v${version}` on the GitHub side, `deployed/${name}_v${version}` on the Azure side), so neither side needs to talk to npm.org or crates.io to decide whether work is required.
78 changes: 78 additions & 0 deletions .github/workflows/cd-github-releases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Release packages to GitHub releases

on:
workflow_dispatch:
schedule:
# 12am PST = 08:00 UTC (drifts to ~11pm PDT during US daylight time).
# Runs ~1 hour before the Azure CD pipeline (09:00 UTC) so any new
# GitHub releases this job creates are ready for that night's publish.
- cron: '0 8 * * *'

permissions: { contents: write }

jobs:
# Lightweight detection: walks the workspaces directory tree (no `npm ci`,
# no build, no `gh` API call) and checks whether each `${name}_v${version}`
# tag already exists in git. The downstream `release` job is skipped if
# every current version already has a tag.
detect:
runs-on: ubuntu-latest
outputs:
hasMissingReleases: ${{ steps.check.outputs.hasMissingReleases }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # need all tags for `git rev-parse refs/tags/<tag>`.

- uses: actions/setup-node@v6
with:
node-version: 22

- id: check
name: Detect publishable workspaces without a release tag
run: node build/scripts/create-github-releases.mjs --check-only

release:
needs: detect
if: needs.detect.outputs.hasMissingReleases == 'true'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # need all tags so `git rev-parse` can detect existing releases.

- uses: actions/setup-node@v6
with:
node-version: 22

- name: Cache multiple paths
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-

- name: Install package dependencies
run: npm ci

- name: Install Rust and wasm-pack
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
export PATH="$HOME/.cargo/bin:$PATH"
rustup target add wasm32-unknown-unknown
cargo install wasm-pack
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"

- name: Build workspaces
run: npm run build

- name: Pack and create GitHub releases
run: node build/scripts/create-github-releases.mjs
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
3 changes: 3 additions & 0 deletions .github/workflows/ci-validate-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,8 @@ jobs:
- name: Testing unit tests
run: npx lage test:node test:chromium ${{ github.event_name == 'pull_request' && format('--since origin/{0}', github.event.pull_request.base.ref) || '' }} --allow-no-target-runs --verbose

- name: End-to-end tests for example apps
run: npm run test:e2e

- name: Testing final validation
run: npm run test:validation
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ obj/
test-results/

# Pack directory
publish_artifacts/
publish_artifacts_npm/
publish_artifacts_crates/
publish_artifacts_meta/
publish_artifacts_stage/

# Rust build artifacts
crates/**/target/
Expand Down
77 changes: 77 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,83 @@ Example of how to format `MIGRATION.md`:
- `Bat` has been updated to use the new API [`BatConfig`](link/to/api).
```

### Publishing

Releases are produced from a dedicated **bump pull request** authored by a maintainer (not by CI). Once the bump PR lands on `main`, the [`cd-github-releases.yml`](.github/workflows/cd-github-releases.yml) workflow attaches the freshly-packed tarballs to a GitHub release per package, and the nightly Azure pipeline ([`azure-pipelines-cd.yml`](azure-pipelines-cd.yml)) downloads those assets and publishes them to npm and crates.io. The detailed CD design is documented in [`.github/workflows/README.md`](.github/workflows/README.md).

This section covers the maintainer workflow for opening the bump PR.

#### 1. Prerequisites

Every PR that touches a publishable workspace should include a beachball [change file](#change-files). Bump PRs consume the accumulated change files; if a workspace needs to be bumped but has no change file (e.g. on first release, or because a contributor forgot to add one), generate one yourself with `npm run change` before bumping.

#### 2. Create the bump branch

```bash
git checkout main
git pull origin main
git checkout -b chore/bump-$(date +%Y-%m-%d)
```

#### 3. Run `npm run bump`

```bash
npm run bump
```

This single command:

- Reads every file under `change/`.
- Bumps `package.json` and updates `CHANGELOG.md` / `CHANGELOG.json` for every affected workspace.
- Runs the `postbump` hook in [`beachball.config.js`](beachball.config.js) β€” for any bumped npm package that has a paired Rust crate at `crates/<crate-name>/Cargo.toml` (where `<crate-name>` is the npm name with the leading `@` dropped and `/` replaced with `-`, e.g. `@microsoft/fast-build` β†’ `microsoft-fast-build`), the hook rewrites the crate's `Cargo.toml` and `Cargo.lock` to the new version so they stay in lock-step with the npm package.
- Deletes the consumed change files.

No commit, push, npm publish, or git tag is made by `npm run bump`.

#### 4. Review the result

```bash
git status
git diff
node build/scripts/create-github-releases.mjs --check-only
```

The third command previews exactly which workspaces the post-merge CD will publish, by listing every workspace whose freshly-bumped `${name}_v${version}` tag is not present in the local git tag list. Run `git fetch --tags --prune origin` beforehand if you want the preview to reflect the current state on `origin` rather than your stale local refs β€” though for a fresh bump that hasn't been pushed yet, your local tag list is the source of truth anyway.

A typical bump PR touches:

- `packages/<name>/package.json` (`version` field) for each bumped workspace
- `packages/<name>/CHANGELOG.md` and `CHANGELOG.json` for each bumped workspace
- `crates/<crate-name>/Cargo.toml` and `crates/<crate-name>/Cargo.lock` for any paired Rust crate (handled automatically by the postbump hook)
- Deletions under `change/`

#### 5. Open the PR

```bash
git add -A
git commit -m "chore: release packages"
git push origin chore/bump-$(date +%Y-%m-%d)
gh pr create --fill --base main
```

The bump PR goes through normal review. `npm run checkchange` will pass because the change files have all been consumed; the PR itself does **not** publish anything.

:::note
Do not edit `package.json` or `Cargo.toml` versions by hand. Let `npm run bump` and the postbump hook do it. [`create-github-releases.mjs`](build/scripts/create-github-releases.mjs) refuses to release a workspace whose npm version and paired crate version disagree.
:::

#### 6. After merge

After merge, [`cd-github-releases.yml`](.github/workflows/cd-github-releases.yml) runs on its nightly cron (`0 8 * * *` UTC, ~12am PST) β€” or you can trigger it immediately via `gh workflow run cd-github-releases.yml` if you don't want to wait. Its `detect` job notices the new `${name}_v${version}` tags don't yet exist; the `release` job packs each `.tgz` (and any paired `.crate`) and atomically creates one GitHub release per bumped package. The next nightly run of [`azure-pipelines-cd.yml`](azure-pipelines-cd.yml) (scheduled ~1 hour later at 09:00 UTC) downloads those assets, hands off to `FAST.Release.PipelineTemplate` for the actual `npm publish` / `cargo publish`, and on success pushes `deployed/<tag>` marker tags so the publish is never repeated.

#### Hotfix or single-package bump

The same flow works for a single-package release β€” just keep only the relevant change file(s) before running `npm run bump`, or pass `--package` to beachball directly:

```bash
npx beachball bump --package "@microsoft/fast-build"
```

### Recommended Settings for Visual Studio Code

You can use any code editor you like when working with the FAST monorepo. One of our favorites is [Visual Studio Code](https://code.visualstudio.com/). VS Code has great autocomplete support for TypeScript and JavaScript APIs, as well as a rich ecosystem of plugins.
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ For an in-depth explanation of FAST [see our docs introduction](https://fast.des
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![npm version](https://badge.fury.io/js/%40microsoft%2Ffast-element.svg)](https://badge.fury.io/js/%40microsoft%2Ffast-element)

The `@microsoft/fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework. To get up and running with `@microsoft/fast-element` see [the Getting Started guide](https://fast.design/docs/fast-element/getting-started).
The `@microsoft/fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework. To get up and running with `@microsoft/fast-element` see [the Getting Started guide](https://fast.design/docs/2.x/getting-started/quick-start/).

### `@fluentui/web-components`

Expand All @@ -46,13 +46,13 @@ The source for `@fluentui/web-components` is hosted in [the Fluent UI monorepo](
We hope you're excited by the possibilities that FAST presents. But, you may be wondering where to start. Here are a few statements that describe various members of our community. We recommend that you pick the statement you most identify with and follow the links where they lead. You can always come back and explore another topic at any time.

* "I just want ready-made components!"
* [Check out the FluentUI Web Components.](https://docs.microsoft.com/en-us/fluent-ui/web-components/)
* [Check out the FluentUI Web Components.](https://learn.microsoft.com/en-us/fluent-ui/web-components/)
* "I want to build my own components."
* [Jump to the fast-element docs.](https://fast.design/docs/getting-started/quick-start)
* [Jump to the fast-element docs.](https://fast.design/docs/2.x/getting-started/quick-start/)
* "I need to integrate FAST with another framework or build system."
* [Jump to the integration docs.](https://fast.design/docs/integrations)
* [Jump to the integration docs.](https://fast.design/docs/2.x/integrations/)
* "I want to look at a quick reference."
* [Jump to the Cheat Sheet](https://fast.design/docs/1.x/resources/cheat-sheet)
* [Jump to the Cheat Sheet](https://fast.design/docs/1.x/resources/cheat-sheet) *(only available in 1.x)*

## Roadmap

Expand Down
Loading