Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 5 additions & 4 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ Dark is the default theme. A light theme is available through the navigation the

## App Store Descriptions and Navigation

- The `/apps/` app store's descriptions are generated from the first sentence of each app's `README.md` in `badger/home` (same logic as `badger/badgerfactory` PR #19).
- The `/apps/` app store reads `public/app-catalog.json` from this website, never GitHub's API in the browser. App descriptions are generated from the first sentence of each app's `README.md` in `badger/home`.
- When adding an installable app to the store, give its README a plain-text first sentence. Keys are the exact `badger/home/badge/apps/` folder names and must match `^[a-z0-9][a-z0-9_-]*$`.
- The `Update app descriptions` workflow runs nightly (and on demand), reads `badger/home` `main`, and runs `npm run sync:app-descriptions` and opens a PR. You can also run it on a website branch.
- `src/data/app-descriptions.json` is generated; do not edit it by hand or maintain a second description list.
- The `Deploy` workflow checks out public `badger/home/main` and runs `npm run sync:app-catalog -- .catalog-source` before building. App changes reaching `badger/home/main` trigger it through the companion GitHub App workflow; no releases, generated-data commits, or data-update PRs are needed.
- `public/app-catalog.json` and `src/data/app-descriptions.json` are generated together; do not edit them by hand or maintain a separate description source. For local updates run `npm run sync:app-catalog -- /path/to/home`.
- Do not depend on `badger/badgerfactory` for descriptions; the sync reads only public `badger/home` content.
- Preserve existing description wording, including exclamation marks; app descriptions are an exception to the punctuation rule for labels and instructions.
- Keep app downloads in `badger/home`; builds and browser code must not need private-repository access.
- Keep app downloads in `badger/home`, pinned to the catalog's source commit; builds and browser code must not need private-repository access.
- Keep the cross-repository App private key in badger/home's main-only `catalog-sync` environment secret, never in code, logs, browser files, or build artifacts. The App is installed only on this website repository with Actions write permission; source changes still require PRs.
- The store and description coverage exclude `menu`, `startup`, and `quest` through the shared catalog helper.
- Local app content descriptions still serve `/browse-apps/` and individual app pages.
- The global **Apps** tab opens the app store and USB/disk tools at `/apps`.
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
push:
pull_request:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -26,6 +29,8 @@ jobs:
run: npm ci
- name: Check app description updates
run: npm run test:app-descriptions
- name: Check app catalog updates
run: npm run test:app-catalog
- name: Check editor projects
run: npm run test:editor
- name: Verify Doom runtime and shareware assets
Expand Down
37 changes: 30 additions & 7 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,54 @@ on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
pages: read
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- name: Read public app source
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
repository: badger/home
ref: main
path: .catalog-source
persist-credentials: false
sparse-checkout-cone-mode: false
sparse-checkout: |
/badge/apps/*/README.md
/badge/apps/*/readme.md
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
cache: npm
- name: Install dependencies
run: npm ci
- name: Configure Pages
id: pages
uses: actions/configure-pages@v5
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
- name: Verify Doom runtime and shareware assets
run: npm run verify:doom-assets -- --require
- name: Generate app catalog and descriptions
run: npm run sync:app-catalog -- .catalog-source
- name: Check app metadata
run: npm run test:app-descriptions && npm run test:app-catalog
- name: Build and verify site URLs
run: |
npm run build
Expand All @@ -40,17 +60,20 @@ jobs:
SITE_URL: ${{ github.repository == 'badger/badger.github.io' && 'https://badger.github.io' || steps.pages.outputs.origin }}
BASE_PATH: ${{ steps.pages.outputs.base_path }}
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
with:
path: dist

deploy:
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
42 changes: 0 additions & 42 deletions .github/workflows/update-app-descriptions.yml

This file was deleted.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
dist/
# generated types
.astro/
# public app source used by deployment
.catalog-source/

# dependencies
node_modules/
Expand Down
94 changes: 64 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,36 +69,70 @@ npm run preview # Preview the production build
npm run astro # Run Astro CLI commands
```

## App store descriptions

The `/apps/` app store uses descriptions generated from the first sentence of
each app's `README.md` in `badger/home`. App downloads also come from
`badger/home`; descriptions on `/browse-apps/` and individual app
pages still come from local app content.
The store excludes the `menu` and `startup` system apps and the `quest` app.

To update descriptions:

1. Edit the app's `README.md` in `badger/home` so its first paragraph starts with
one plain-text sentence.
2. After the change merges to `main`, the nightly `Update app descriptions`
workflow reads `badger/home` and opens a pull request here. To run it by hand, use `workflow_dispatch` or run
`npm run sync:app-descriptions` on a website working branch.
3. Run `npm run test:app-descriptions` and `npm run build`, then submit the saved
website changes through a pull request.

The update command requires Node.js 22.6.0 or newer. It reads the file tree and
READMEs from the public `badger/home` repository (`APPS_REF` selects a branch or
commit, default `main`). Apps without a usable README keep their saved
description. Folders that do not match the lowercase key rule
(`^[a-z0-9][a-z0-9_-]*$`, such as `Copilot`) get no description. Invalid or
incomplete updates fail with a clear error and leave the last good copy
unchanged.

Do not edit `src/data/app-descriptions.json` by hand. It is the generated website
copy used by normal builds and deployment. A newly added store app remains
installable and is listed without a description until the descriptions are
updated.
## App store catalog and descriptions

The `/apps/` app store reads `/app-catalog.json` from this website, not GitHub's
REST API. Reload reads the currently published catalog; it does not start a
workflow. App downloads still come from public `badger/home`, using the exact
commit recorded in the catalog so file lists and downloaded code match.

Each deployment reads the latest `badger/home/main` file tree and app READMEs,
then generates the catalog and `src/data/app-descriptions.json` in its build
workspace. The latter also supplies descriptions in the Developer Simulator.
Descriptions use the first sentence of each app's README. Descriptions on
`/browse-apps/` and individual app pages still come from local app content.
The store excludes `menu`, `startup`, and `quest`.

After the companion workflow is configured in `badger/home`, a push to its
`main` branch that changes `badge/apps/**` starts this site's `Deploy` workflow.
This includes fixes to existing apps, new or removed files, and README changes.
It does not require a release or tag. Catalog refreshes publish build output
without data commits or data-update PRs. Website source changes still use PRs.
Until that setup is complete, an authorized maintainer can run `Deploy` manually
on `main`. A failed generation or build does not replace the published site.

### Cross-repository setup

Use a dedicated organization-owned GitHub App installed only on
`badger/badger.github.io`, with repository **Actions: read and write** permission.
The companion workflow creates a short-lived installation token only to start
`deploy.yml` on `main`; it does not check out or execute badge-app code.

An administrator must configure a `catalog-sync` environment in `badger/home`,
restricted to the `main` branch, and protect workflow changes through review.
Add the App's non-secret Client ID as the environment variable
`CATALOG_APP_CLIENT_ID` and its private key as the environment secret
`CATALOG_APP_PRIVATE_KEY`. Do not add content-write or administration permissions,
install the App across all repositories, or put the key in code, logs, artifacts,
or browser files. Restrict the website's Pages environment to deployments from
`main` too. Follow the organization's approval requirements.

The private key remains sensitive even though each installation token is
temporary. Keep it protected and replace it if exposed. To stop automatic
updates, disable the companion workflow or revoke the App's access.

### Local catalog updates

Normal local builds use the saved catalog and do not need the GitHub App.
To refresh it, use a checkout of public `badger/home`:

```bash
npm run sync:app-catalog -- /path/to/home
npm run test:app-descriptions
npm run test:app-catalog
npm run build
```

The generator reads committed files at that checkout's `HEAD`, not uncommitted
edits. Only the Git file tree and app READMEs are needed; a sparse checkout is
sufficient. It does not download or execute app code. Apps without a usable
README keep their saved description. Existing folders outside the lowercase
description-key rule (`^[a-z0-9][a-z0-9_-]*$`, such as `Copilot`) remain
installable without a generated description.

Do not edit `public/app-catalog.json` or `src/data/app-descriptions.json` by hand.
Both are generated from the same public source commit. Invalid or incomplete
updates fail before replacing the generated files.

## 📁 Project Structure

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"preview": "astro preview",
"sync:app-descriptions": "node --experimental-strip-types scripts/sync-app-descriptions.mjs",
"test:app-descriptions": "node --experimental-strip-types --test scripts/sync-app-descriptions.test.mjs",
"sync:app-catalog": "node --experimental-strip-types scripts/sync-app-catalog.mjs",
"test:app-catalog": "node --experimental-strip-types --test scripts/sync-app-catalog.test.mjs",
"astro": "astro",
"sync:editor-apps": "node --experimental-strip-types scripts/sync-editor-apps.mjs",
"sync:editor-examples": "node scripts/sync-editor-examples.mjs",
Expand Down
Loading
Loading