Files
software-mansion__argent/packages/docs/scripts/encode-video.sh
Kacper Kapuściak 36aa14a5fc docs: add Argent documentation (#814)
Adds the Argent documentation site, published to
[docs.swmansion.com/argent](https://docs.swmansion.com/argent): a
branded Docusaurus project under `packages/docs/`, the full first set of
pages, and the CI that checks and deploys it.

<img width="1512" height="945" alt="Screenshot 2026-08-21 at 13 05 04"
src="https://github.com/user-attachments/assets/4607e143-4359-49a8-93a2-aaa3af4c9534"
/>

## Site

A standalone Docusaurus 3.9 project, built on the shared Software
Mansion docs theme
([`@swmansion/t-rex-ui`](https://www.npmjs.com/package/@swmansion/t-rex-ui))
and restyled for Argent:

- **Palette** from [argent.swmansion.com](https://argent.swmansion.com):
dark `#0D0F26`, blue `#99DAFF`, lavender `#E4E1FF`, light `#FEFEFE`,
mist `#F1F1F1`. The `--swm-*` token names stay, since the shared theme
resolves against them.
- **Typography**: DM Sans and DM Mono, matching the landing page.
- **Sidebar** with lucide icons on every page entry
(`sidebar_custom_props.icon` in the front matter, registered in
`src/theme/SidebarIcon`), the logo kept on the page background and the
panel inset from the edge.
- **Video component** for embedded screen recordings, with
`scripts/encode-video.sh` producing a web-sized MP4 and a poster frame
for each clip in `static/video/`.
- **Copy page button** and a few theme fixes: inline code badges in
tables, paginator hover.
- **No landing page.** That stays at argent.swmansion.com. The root
route redirects to Getting started.

## Content

Three sections in `docs/`:

- **Fundamentals**: getting started, installation, supported platforms.
- **Features**: interacting with apps, flows, network, screen recording,
lens, visual regression, profiling, debugging. Conceptual overviews with
recordings, each linking to the tools reference.
- **Reference**: tools, CLI, configuration, flow YAML, editors,
telemetry.

Prose follows Simplified Technical English. The conventions (style,
front matter, icons, checks) are written down in
`packages/docs/CLAUDE.md`, and a root `CLAUDE.md` adds a checklist so
that code changes to tools, CLI, configuration or flows update the
matching docs page in the same pull request.

## CI and deploy

- `Docs build` runs `format:check`, `lint`, `typecheck` and `build` on
every pull request that touches `packages/docs/`. The build has
`onBrokenLinks: "throw"`, so it catches links left dangling by a moved
page.
- `Docs publish` deploys `packages/docs/build` through the GitHub
Actions Pages source on every push to `main` that touches the docs. The
repository Pages source needs to be set to **GitHub Actions** for the
first run.

## Notes for review

- The site is excluded from the root `packages/*` workspaces
(`!packages/docs`) and keeps its own `package.json` and
`package-lock.json`, so its dependency tree stays out of the toolkit's
lockfile. Root Prettier, ESLint and knip ignore it; it formats and lints
itself with the repo `.prettierrc` and its own `eslint.config.mjs`.
`check-workspace-versions.mjs` skips it so its `0.0.0` version is not
read as drift.
- `webpack` is pinned to `5.105.4` and `@docusaurus/plugin-content-docs`
/ `theme-common` to `3.9.2` via `overrides`. Newer webpack fails
Docusaurus 3.9's ProgressPlugin option validation, and a hoisted
`plugin-content-docs@3.10.2` produced a duplicate React context that
crashed SSR.
- **Search is not wired up yet.** The shared theme always mounts a
DocSearch bar, so an `algolia` block has to be present. It reads
`ALGOLIA_APP_ID` / `ALGOLIA_API_KEY` / `ALGOLIA_INDEX_NAME` from the
environment and the bar stays hidden until Argent has its own DocSearch
application. Follow-up PR.

## Testing

- `npm run format:check`, `npm run lint`, `npm run typecheck` and `npm
run build` pass in `packages/docs/`.
- Root `prettier --check`, `eslint` and `npm run knip` pass.
- Walked the served production build in the browser in light and dark
themes while iterating: root redirect, docs pages, sidebar icons,
videos, TOC, footer.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 16:03:35 +02:00

85 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Normalizes screen recordings for the docs site.
#
# ./scripts/encode-video.sh ~/Desktop/tap-flow.mov
# ./scripts/encode-video.sh -h 720 recordings/*.mov
# ./scripts/encode-video.sh -p 6 recordings/wizard.mov
#
# Each input produces static/video/<name>.mp4 plus a <name>.jpg poster frame.
# Reference them from MDX as <Video src="/video/<name>.mp4" portrait />.
#
# Encoding notes:
# -an docs clips are silent, and muted video autoplays everywhere
# -movflags +faststart playback starts before the whole file has downloaded
# -pix_fmt yuv420p required for Safari and iOS
# -crf 28 visually lossless enough for flat UI, roughly 30x smaller
# than the same clip as a GIF
set -euo pipefail
HEIGHT=900
CRF=28
POSTER_AT="" # seconds into the clip; defaults to a quarter of the duration
OUT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/static/video"
usage() {
echo "usage: $(basename "$0") [-h HEIGHT] [-c CRF] [-p POSTER_SECONDS] [-o OUT_DIR] input [input...]" >&2
exit 1
}
while getopts ":h:c:p:o:" opt; do
case "$opt" in
h) HEIGHT="$OPTARG" ;;
c) CRF="$OPTARG" ;;
p) POSTER_AT="$OPTARG" ;;
o) OUT_DIR="$OPTARG" ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
[ "$#" -gt 0 ] || usage
if ! command -v ffmpeg >/dev/null 2>&1; then
echo "ffmpeg is not installed (brew install ffmpeg)" >&2
exit 1
fi
mkdir -p "$OUT_DIR"
for input in "$@"; do
if [ ! -f "$input" ]; then
echo "skipping $input: not a file" >&2
continue
fi
name="$(basename "${input%.*}")"
# Lowercase, spaces and underscores to hyphens, so URLs stay tidy.
slug="$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' _' '--')"
video="$OUT_DIR/$slug.mp4"
poster="$OUT_DIR/$slug.jpg"
# scale=-2 keeps the aspect ratio and rounds the width to an even number,
# which H.264 requires.
ffmpeg -y -loglevel error -i "$input" \
-vf "scale=-2:$HEIGHT" \
-c:v libx264 -crf "$CRF" -preset slow \
-pix_fmt yuv420p -movflags +faststart -an \
"$video"
# The first frame of a demo is usually an empty terminal or a splash screen,
# so the poster comes from a quarter of the way in unless -p says otherwise.
poster_at="$POSTER_AT"
if [ -z "$poster_at" ]; then
duration="$(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 "$video")"
poster_at="$(LC_NUMERIC=C awk -v d="$duration" 'BEGIN { printf "%.2f", d / 4 }')"
fi
ffmpeg -y -loglevel error -ss "$poster_at" -i "$video" -frames:v 1 -q:v 4 "$poster"
size="$(du -h "$video" | cut -f1 | tr -d ' ')"
echo "$video ($size)"
done