react_frontend¶
Builds a Node.js frontend (React/Vite or anything with an npm run
build-style step) from a private GitHub repository and serves the static
output via nginx, with a single-page-app fallback to index.html for
client-side routing. Self-contained: unlike fastapi_backend, it does not
need pairing with backend_website — it templates and serves its own
HTTPS vhost directly.
What it does¶
Everything runs as root (the play's default become user) so that
redeploys stay idempotent even though the last step hands ownership to
www-data — see the comment at the top of tasks/main.yml for why.
- Ensures
/home/<username>/projects/<react_frontend_server_name>exists (the site root). - Resolves which ref to deploy — same rule as
fastapi_backend:react_frontend_use_release_tag: true(production convention) deploysreact_frontend_release_tagif pinned, else the repo's latest GitHub release tag (fails if none exists);false(default, staging convention) deploysreact_frontend_git_branch. - Clones/pulls
react_frontend_repoover HTTPS using a GitHub token embedded in the URL (no_log: true, token never logged) at the ref resolved above. - Installs
nvmto/opt/nvmif not already present — shared across everyreact_frontendinvocation on the host, so multiple apps don't each install their own copy. - Installs the requested Node version via
nvm install. - If
react_frontend_build_envis non-empty, writes it as a.envfile at the app's working directory (the repo root, orreact_frontend_repo_subdirwithin it) before building (for build-time variables baked into the bundle, e.g. Vite'sVITE_*). - Runs
<react_frontend_package_manager> installthenreact_frontend_build_commandfrom that same working directory. - Symlinks
<site_root>/dist -> <working_dir>/<react_frontend_build_dir>whenever that doesn't already resolve to<site_root>/diston its own (i.e. always whenreact_frontend_repo_subdiris set, or when the build output isn't literally nameddist) — the nginx template always serves<site_root>/dist. - Recursively chowns the site root to
www-dataso nginx can read it — this is the last task withtags: deploy, done every deploy run. - Templates the HTTPS vhost and reloads nginx.
Variables¶
| Variable | Required | Default | Description |
|---|---|---|---|
react_frontend_repo |
yes | — | GitHub repo, org/name form (private, HTTPS). |
react_frontend_repo_subdir |
no | '' (repo root is the app) |
Path within the cloned repo where this app actually lives — set this when react_frontend_repo is a monorepo (e.g. apps/tamiyo_scroll). The build (npm install/build command, build_env file) runs from <site_root>/<repo_subdir> instead of the repo root; the dist symlink served by nginx is adjusted to match. The full repo is still cloned to <site_root> either way. |
react_frontend_server_name |
yes | — | Public domain; also used for the site root path. Certificate must already exist (run register_ssl first). |
react_frontend_app_name |
no | react_frontend_server_name |
Currently informational only (no systemd unit — this role has no long-running process). |
react_frontend_use_release_tag |
no | false |
true deploys a GitHub release tag instead of a branch — the production convention. |
react_frontend_release_tag |
no | unset (auto-resolve latest) | Pins a specific tag instead of "whatever's latest" — how you roll back. Only used when react_frontend_use_release_tag: true. |
react_frontend_git_branch |
no | main |
Branch/ref to check out. Only used when react_frontend_use_release_tag: false. |
react_frontend_node_version |
no | 22 |
Node version passed to nvm install/nvm use. |
react_frontend_package_manager |
no | npm |
Must support <pm> install (e.g. yarn, pnpm). |
react_frontend_build_command |
no | npm run build |
Full build command, run from the repo root. |
react_frontend_build_dir |
no | dist |
Where the build output lands relative to the repo root. Symlinked to dist if different. |
react_frontend_build_env |
no | {} |
Dict written to a .env file before building (build-time vars, not runtime secrets — there's no running process to pass Environment= to). |
react_frontend_github_token |
no | the play's github_token |
Overrides the GitHub PAT used to clone this specific app, for when it lives in a different org/repo than the shared token covers. |
Requirements¶
- A GitHub Personal Access Token (repo read scope) available as the
play-level
github_tokenvar (vaulted — see the root README) or passed per-invocation viareact_frontend_github_token. Ifreact_frontend_use_release_tag: true, that token also needs read access to the repo's Releases (the samereposcope covers this). - If
react_frontend_use_release_tag: true, the repo needs at least one GitHub Release published — the role fails with a clear message otherwise. register_sslmust have run forreact_frontend_server_namefirst.- The build must produce a client-side-routed SPA (or a plain static
site) — the nginx
try_files $uri /index.html;fallback assumes any unmatched path should render the app shell, not 404.
Example¶
- role: register_ssl
tags: [frontend, certs]
register_ssl_server_name: my-app.barrins-codex.org
- role: react_frontend
tags: [frontend]
react_frontend_repo: my-org/my-app
react_frontend_server_name: my-app.barrins-codex.org