A Bevy ECS card game project built from the Codex Project Template.
| Task | Command |
|---|---|
| Install dependencies once | scripts/main/InstallDependencies.ps1 |
| Run tests | scripts/other/RunTests.ps1 |
| Run desktop | scripts/other/RunAppDesktop.ps1 |
| Run desktop hot reload | scripts/main/RunAppDesktopHotReload.ps1 |
| Check desktop | scripts/other/RunAppDesktop.ps1 -CheckOnly |
| Run web | scripts/other/RunAppWeb.ps1 |
| Check web | scripts/other/RunAppWeb.ps1 -CheckOnly |
| Export web | scripts/other/RunAppWeb.ps1 -Release -NoOpen -ExportOnly |
| Export release web | scripts/other/ExportWebRelease.ps1 |
| Stop app | scripts/other/StopApp.ps1 |
https://samuelasherrivello.github.io/samurai-card-game/latest/
The static web build is exported and hosted when a GitHub Release is published. Versioned releases live under /releases/<version>/, and /latest/ points at the newest release.
| Key | Behavior |
|---|---|
W / A / D |
DebugHUD hold indicators for directional input state. |
R |
Reloads the active AppScene child view without restarting the app. |
S |
Debug shortcut that cycles to the next scene: GameScene, DeckScene, DebugScene, then wraps back to GameScene. |
T |
In GameScene, cycles the active world; in DeckScene or DebugScene, cycles global CardUI presentation settings. |
F |
Toggles fullscreen: Bevy fullscreen on desktop, browser Fullscreen API on web. |
I |
Toggles the Bevy inspector window. |
H |
Toggles persisted desktop hot-reload auto-restart behavior. |
Escape |
Invisible key: requests the same app close flow as the desktop title-bar close button. |
| Screen | Composition | Current Behavior |
|---|---|---|
GameScreen |
AppScene plus GameScene |
Active gameplay view. |
DeckScreen |
AppScene plus DeckScene |
Shows reusable top navigation, deck selection, Deck 01, and the selected deck editor. |
DebugScreen |
AppScene plus DebugScene |
Debug settings/card presentation view. |
DeckScreen currently owns one deck named Deck 01 with 12 cards. All library cards start in the deck, so the Library starts empty; the Shop tab is visible as an empty state for future work. Card modals support Back, Move To Library, and Move To Deck 01; Transfer Out remains visible but disabled until that feature is specified.
Reusable DeckScreen UI concepts include TopNavigationViewBundle for page navigation and DeckViewBundle for deck tiles rendered from the existing card back asset plus the deck name.
| Requirement | Purpose |
|---|---|
| Windows package manager | InstallDependencies.ps1 can install rustup through winget when Rust is not already installed. If winget is unavailable, install rustup manually from https://rustup.rs/. |
| Rust toolchain | InstallDependencies.ps1 installs and verifies the stable Rust toolchain. |
| Rust target | InstallDependencies.ps1 installs and verifies x86_64-pc-windows-msvc. |
| Cargo | InstallDependencies.ps1 verifies cargo is available after rustup setup. If it is not found, restart the terminal and rerun the script. |
| Dioxus CLI | InstallDependencies.ps1 verifies or installs Dioxus CLI 0.7.x for desktop hot reload. Pass -SkipHotReloadTools to skip this optional setup. |
| MSVC linker | Desktop builds may require link.exe. Install Build Tools for Visual Studio from https://visualstudio.microsoft.com/visual-cpp-build-tools/ with the Desktop development with C++ workload. |
| Fast linker | rust-lld is optional. When available, the scripts use it for faster desktop linking; otherwise they fall back to the default Windows linker. |
| Setting | Behavior |
|---|---|
| Desktop target | scripts/other/RunAppDesktop.ps1 uses the host target with a dedicated target/run-app-desktop cache so other Cargo tasks do not invalidate warm runs. |
| First checkout | scripts/main/InstallDependencies.ps1 warms the same desktop cache once, so later RunAppDesktop.ps1 calls only rebuild changed code. |
| Default run | scripts/other/RunAppDesktop.ps1 compiles only changed artifacts, then opens the cached desktop executable. |
| Headless compile helper | scripts/other/CompileApp.ps1 centralizes Cargo build, check, and test setup for the main run scripts. |
| Fast validation | scripts/other/RunAppDesktop.ps1 -CheckOnly runs cargo check -p samurai-card-game --features asset-hot-reload,fast-dev without launching the app. |
| Fast dev feature | Non-release desktop runs enable fast-dev, which turns on Bevy dynamic linking for faster edit-run cycles after the first build. |
| Asset hot reload | Desktop run scripts enable asset-hot-reload, which turns on Bevy file watching for changed runtime assets including bitmap textures. |
| Desktop hot reload | scripts/main/RunAppDesktopHotReload.ps1 uses Dioxus CLI hot patching with target/run-app-desktop-hot-reload, enables asset file watching, and keeps output in the terminal. |
| Web target | scripts/other/RunAppWeb.ps1 builds wasm32-unknown-unknown into target/run-app-web, runs wasm-bindgen, serves the generated page on localhost, and opens the browser. |
| Explicit target | Pass -TargetTriple x86_64-pc-windows-msvc only when a separate target cache is required. |
| Path | Purpose |
|---|---|
.github |
GitHub Actions and repository automation, including release and web export workflows. |
deploy.vps.env |
Public, non-secret VPS deployment defaults used by ReleaseWebBuildToVps. |
bevy/crates/game |
Main Bevy game crate and executable for card-specific runtime behavior. |
bevy/crates/template-crate |
Proper reference skeleton for Bevy crate folders, representative files, assets, and Rust coding standards. |
bevy/crates/game/src/runtime/components |
Card-specific ECS data attached to entities. |
bevy/crates/game/src/runtime/resources |
Card-specific ECS resources and inspection state. |
bevy/crates/game/src/runtime/systems |
Card-specific setup, pointer mapping, smoothing, and DebugHUD composition. |
bevy/crates/game/src/runtime/plugins |
Game plugin composition and card POC tests. |
bevy/crates/game/assets/themes/theme_japan/cards |
Theme-owned Japan card textures, card back, and safe-area presentation asset. |
bevy/crates/game/assets/themes/theme_japan/cards/card_kage_ren |
Generated Kage Ren card textures. |
bevy/crates/game/assets/themes/theme_japan/cards/card_lord_daichi |
Generated Lord Daichi card textures. |
bevy/crates/game/assets/themes/theme_japan/cards/card_sister_hotaru |
Generated Sister Hotaru card textures. |
bevy/crates/game/assets/themes/theme_japan/cards/card_yokai_placeholder |
Generated temporary Yokai placeholder card textures. |
bevy/crates/game/assets/themes/theme_japan/locations |
Theme-owned Japan tactical location textures. |
bevy/crates/game/assets/themes/theme_japan/worlds |
Theme-owned Japan world background textures. |
bevy/crates/game/assets/themes/theme_japan/worlds/world_bamboo_forest |
Generated Bamboo Forest world background. |
bevy/crates/game/assets/themes/theme_japan/worlds/world_coastal_harbor |
Generated Coastal Harbor world background. |
bevy/crates/game/assets/shaders |
Shared shader assets that remain outside theme-owned folders. |
bevy/crates/shared |
Reusable system-level Rust logic for shared runtime behavior. |
bevy/crates/shared/src/window.rs |
Project-approved desktop window defaults: 1024x768. |
data/local_storage |
Local persisted runtime state for window placement and DebugHUD input toggles. |
.codex |
Repo-local Codex guidance, skills, memory, and rules. |
.specify |
Specify workflow configuration and constitution. |
specs |
Active project specs. |
scripts |
Repeatable local commands. |
documentation/images |
README-visible supporting images. |
| Area | Choice |
|---|---|
| Language | Rust 2024 |
| Engine | Bevy 0.18.1 |
| Runtime dependencies | bevy-inspector-egui, bevy-persistent, serde, serde_json; optional bevy_hotpatching_experiments for desktop code hot reload |
| Architecture | Shared runtime crate plus game-specific ECS components, resources, systems, plugins, generated theme assets, and local persisted runtime state |
| Workspace | Cargo workspace rooted at this repository |
Keep gameplay changes small and spec-driven. Reusable system-level behavior belongs in bevy/crates/shared; card-specific geometry, card models, pointer mapping, smoothing, DebugHUD composition, inspector UI, and view reload behavior belongs in bevy/crates/game. Use bevy/crates/template-crate as the proper reference for Bevy crate folders, representative files, assets, and Rust coding standards.
| Concept | Purpose |
|---|---|
AppScene |
Always-present app-level scene that owns persistent overlays such as DebugHUD. |
GameScene |
Gameplay sub-screen view loaded on top of AppScene. |
DeckScene |
Focused Deck sub-screen view loaded on top of AppScene. |
DebugScene |
Debug settings sub-screen scene duplicated from DeckScene. |
CardModel |
Card data model containing identity, display text, presentation paths, and tuning data. |
CardView |
Rendered card presentation created from one CardModel. |
CardViewBundle |
Bevy bundle for the root visual entity of a rendered card view. |
| Related tech | Link |
|---|---|
| GitHub Actions | GitHub Actions docs |
| GitHub Pages | Custom GitHub Pages workflows |
Keep .github/workflows/export-web-build-to-github-pages.yml as the only GitHub Pages deployment workflow. Do not create a branch-based Pages action; it can fight with this custom export workflow.
Choose one setup option:
| Option | Instructions |
|---|---|
| Enable Pages manually | In GitHub, open Settings > Pages and set Source to GitHub Actions. Do not select a branch source. |
Add PAGES_ADMIN_TOKEN |
Add a repository secret named PAGES_ADMIN_TOKEN with Pages write permission so the workflow can enable or repair Pages setup without creating another action. |
The GitHub Actions display names are:
| Workflow | Purpose |
|---|---|
PerformRelease |
Manually increments VERSION.txt, updates Cargo package versions, commits, tags, and creates a GitHub Release. |
ReleaseWebBuildToGithubPages |
Builds the release web app and publishes /releases/<version>/ plus /latest/ to GitHub Pages. |
ReleaseWebBuildToVps |
Builds the release web app and publishes it to the configured VPS app directory. |
Use GitHub Releases as the publishing boundary. Normal commits do not publish the project. To publish, run the PerformRelease workflow manually.
VERSION.txt is the release source of truth. It stores the public project version without the tag prefix, such as 0.01. Release tags add v, such as v0.01.
The release workflow uses this version style:
VERSION.txt |
Git tag | Cargo package version |
|---|---|---|
0.01 |
v0.01 |
0.1.0 |
0.02 |
v0.02 |
0.2.0 |
0.03 |
v0.03 |
0.3.0 |
Each published release builds the public Bevy web target for GitHub Pages.
If the Pages workflow is run manually, leave the release version input blank to use the current VERSION.txt. Enter a value like v0.01 only when redeploying a specific release folder.
The reusable release web export script is scripts/other/ExportWebRelease.ps1. It calls the standard web build, writes 404.html, and validates the expected web bundle and card type assets before deployment workflows upload the result.
| URL | Purpose |
|---|---|
/latest/ |
Newest published release. |
/releases/v0.01/ |
Specific immutable release folder. |
The Pages workflow stores release folders on the pages-releases branch, then deploys them through GitHub Pages Actions. Keep the repository Pages source set to GitHub Actions, not a branch.
The VPS workflow uses deploy.vps.env for public, reusable deployment settings and GitHub repository secrets for private SSH access. The default remote app path is /srv/apps/samurai-card-game, with release folders under /srv/apps/samurai-card-game/releases and a current symlink pointing at the active release.
Public deployment settings:
| Setting | Purpose |
|---|---|
APP_NAME |
Short app name used for release archive names. |
WEB_RELEASE_SCRIPT |
Repo script that builds and validates the release web bundle. |
DEPLOY_STATIC_PATHS |
Comma-separated `local/source |
REMOTE_APP_DIR |
VPS app root containing releases and the active symlink. |
REMOTE_RELEASES_DIR |
Folder under REMOTE_APP_DIR for timestamped release directories. |
REMOTE_CURRENT_LINK |
Symlink under REMOTE_APP_DIR that points to the active release. |
REMOTE_SERVICE_NAME |
Optional systemd service to restart after deploy. Leave blank for static-file deployments. |
DEPLOY_KEEP_RELEASES |
Number of previous VPS release folders to keep. |
PUBLIC_WEB_ROOT |
Optional Nginx-served public folder for browser access. |
PUBLIC_APP_PATH |
Optional public URL path below PUBLIC_WEB_ROOT. |
PUBLIC_HEALTHCHECK_PATH |
Public path checked after deploy, relative to PUBLIC_APP_PATH. |
To make VPS deployments immediately browser-visible, install the shared static app router once on the VPS:
sudo bash scripts/vps/InstallStaticWebRouter.sh <deploy-user>This installs Nginx, serves /srv/www publicly on HTTP port 80, and lets each project expose its active release through a symlink like /srv/www/samurai-card-game -> /srv/apps/samurai-card-game/current. The public URL for this repo is http://<vps-host>/samurai-card-game/.
Port 80 is public web traffic. Do not place private admin tools, API credentials, wallet files, server notes, or other secrets under /srv/www or deployed app bundles.
For this static Bevy game, DEPLOY_STATIC_PATHS=target/run-app-web/site|/ means the exported web bundle is the only folder packaged for deployment, and it is served at /samurai-card-game/. Additional browser-visible folders can be mapped with comma-separated entries, such as target/docs|/docs/. Do not map server binaries or private files into DEPLOY_STATIC_PATHS.
The VPS deploy publishes three browser URL shapes for public static builds:
| URL | Purpose |
|---|---|
/samurai-card-game/ |
Newest deployed release. |
/samurai-card-game/latest/ |
Alias for the newest deployed release. |
/samurai-card-game/v0.02/ |
Versioned release path using the resolved release tag. |
Required GitHub repository secrets:
| Secret | Purpose | Public-safe example |
|---|---|---|
VPS_HOST |
VPS hostname or IP address. | example.com |
VPS_USER |
Limited deploy user on the VPS. | deploy |
VPS_SSH_PORT |
SSH port for the VPS. | 22 |
VPS_SSH_PRIVATE_KEY |
Private deploy key for the limited VPS deploy user. | Do not print or commit this value. |
VPS_KNOWN_HOSTS |
Pinned SSH host key entry for the VPS. | Generate from the trusted VPS host key. |
The VPS workflow validates these five secrets and runs a pinned-host-key SSH preflight before installing Rust tooling or building the web bundle. Missing secrets, an invalid port, malformed SSH key material, host key mismatch, connection timeout, or public-key login failure should fail near the start of the job.
The deploy user should only have write access to the configured app directory. If REMOTE_SERVICE_NAME is set, allow that user to restart only that one service with sudo systemctl restart <service>.
Add the secrets in GitHub under Settings > Secrets and variables > Actions > Repository secrets. Use New repository secret once for each name above. Do not put secret values in deploy.vps.env, commit history, issues, pull requests, screenshots, or README text.
Use a dedicated SSH key for this repository deployment. Store the private key content in VPS_SSH_PRIVATE_KEY, and install only the matching public key in the deploy user's authorized_keys file on the VPS. The deploy user should not be a personal admin user.
Create VPS_KNOWN_HOSTS from a trusted terminal after verifying the server identity out of band:
ssh-keyscan -p <ssh-port> <vps-host>Copy the resulting host key line into the VPS_KNOWN_HOSTS repository secret. Do not replace this with automatic host-key trust in the workflow; the pinned host key helps prevent deploying to an impersonated server.
Public configuration belongs in deploy.vps.env; private access belongs in GitHub repository secrets:
| Location | Put this there | Do not put this there |
|---|---|---|
deploy.vps.env |
App name, build output path, remote app folder, release retention count. | SSH private keys, passwords, tokens, cookies, private host notes. |
| GitHub repository secrets | SSH private key, SSH host, SSH user, SSH port, pinned known-hosts entry. | Build paths or app defaults that other users should customize in the repo. |
Created by Samuel Asher Rivello.
Provided as-is under MIT License.