# home

A static portfolio of my open-source projects, published with GitHub Pages.

- **Public page** — [`index.html`](index.html): projects grouped into **Mature
  projects**, **Work in progress**, **Libraries & tools**, **Prototyping...**,
  **Demos**, **Documentation & learning** and **Unclassified**, with
  subject headings in the WIP and Prototyping groups and a collapsed **project
  index**. The other groups use one grid without subdivisions. Only explicitly
  selected projects are listed. Featured cards stay within their status group.
- **Beta releases** — [`releases.html`](releases.html): a tester-friendly page
  listing public `*-releases` repositories with links to their GitHub downloads
  and release notes.
- **Admin page** — [`admin.html`](admin.html): my complete repository inventory
  (including private, archived and forked repos). Reachable on the same site but
  **passphrase-protected**: the data ships only as AES-GCM ciphertext and is
  decrypted in the browser. No local server needed. Once unlocked, you can paste
  a GitHub token to perform **reversible** actions — change a repo's
  visibility (public/private) or archive/unarchive it. Deletion is not offered.

## How it works

Plain HTML/CSS/JS, no build step. The public page reads
[`data/repositories.json`](data/repositories.json); the admin page reads
[`data/repositories.admin.enc.json`](data/repositories.admin.enc.json) and
unlocks it with WebCrypto (PBKDF2-SHA256 → AES-GCM).

Each project links to:

- the **GitHub repository**,
- the **live site** (GitHub Pages) when the repo publishes one,
- the **homepage** when a different URL is configured.

The beta releases page automatically lists public repositories whose names end
in `-releases`, using the public repository data file. Each entry links to the
repository's GitHub Releases page, where testers can download available builds
and read version notes.

## Data

Both data files are **generated** in a private admin repository, never edited by
hand here:

- `data/repositories.json` — public, non-archived repos only (no private names).
- `data/repositories.admin.enc.json` — the encrypted master inventory.

See [`docs/TAXONOMY.md`](docs/TAXONOMY.md) for the section and tag taxonomy.

## Configure the portfolio

Edit [`config/portfolio.json`](config/portfolio.json), either locally or with
GitHub's file editor. This is hand-maintained content, separate from the
generated inventory. Find a repository by its exact, case-sensitive name:

```json
"Scopetta": {
  "status": "mature",
  "visible": true,
  "summary": "Play Italian Scopa in your browser. Includes the rules and scoring.",
  "curated": true,
  "featured": true,
  "tags": ["card-game", "scopa", "browser-game"],
  "liveUrl": "https://diegoami.github.io/Scopetta/",
  "downloadUrl": "https://github.com/diegoami/Scopetta/releases/latest"
}
```

Valid statuses:

- `mature` — established and ready to use; maintenance continues.
- `wip` — usable but not ready yet.
- `tools` — a reusable library or practical utility.
- `prototyping` — we are not there yet.
- `demo` — an abandoned proof of concept.
- `documentation` — study guides, exercises and reference material.
- `unclassified` — status not yet chosen (the default).

`liveUrl` sets the **Open app** link; without it, the generated Pages URL or
homepage is used. `downloadUrl` adds a **Downloads** link. Both must be absolute
HTTP(S) URLs.
Use `liveLabel` to override the primary link text, for example
`"Read example chronicle"` instead of `"Open app"`.

`extraLinks` adds labelled links to a card and its index entry, for example:

```json
"extraLinks": [
  { "label": "My chess games", "url": "https://diegoami.github.io/chessgamescollection/" }
]
```

Each link needs a nonempty `label` and an absolute HTTP(S) `url`.

`summary` is the public text shown on the card and in the full index, and is
searchable. It is plain text, not HTML or Markdown. `curated: true` gives the
project a card; `false` keeps it in the full index only. `featured: true` adds a
badge and puts the card first within its subject group. It needs
`curated: true` to appear as a card.

`tags` is an optional array of nonempty strings. It replaces the generated tags
and controls the card badges, tag filter and search. Omit it to keep the generated
tags, or use `[]` to show no tags. Prefer descriptive tags such as `card-game`,
`geography`, `subtitles` or `developer-tools`; language has its own filter too.

`visible: true` includes a project on the public page. `false` hides it completely,
including from search, counts, filters and the project index. Omitted `visible`
defaults to **false**, so new inventory entries stay hidden until you select them.
Legacy and other unselected projects remain in the configuration for later editing.
This controls the page presentation; the generated public JSON is still readable.

Every field in a repository's settings is optional. Omit `summary`, `curated` or
`featured` to use the generated inventory's value. Omit `status` to use Unclassified.

To include a **public** project missing from the generated inventory, add an
entry with an explicit `repositoryUrl`, a `summary`, and a `status`. For example:

```json
"goal2": {
  "repositoryUrl": "https://github.com/diegoami/goal2",
  "status": "wip",
  "visible": true,
  "summary": "A faithful rebuild of Goal (1993), alongside a World Cup bot.",
  "language": "Python",
  "section": "games",
  "curated": true
}
```

`language` and `section` optionally override the generated language and subject
ID (subject IDs come from `data/repositories.json`, such as `games` or `devtools`).
Two subjects are hand-maintained in `assets/portfolio.mjs` and set with
`section` in this file: `learning` (**Learning**) and `angband` (**Angband**).
Work in progress and Prototyping... show their subjects as subheadings; the
other groups are one grid, so a project needs no `section` outside them. In a
group with subheadings, a project without one — `"section": ""` — is listed as
a plain card above them.
Supplemental projects default to curated cards, no highlighting, no tags and the
Other subject. They merge with the generated entry once the inventory includes
them. To describe a project without a public repository, use `standalone: true`
instead of `repositoryUrl`; its name and description appear without a source
link. Use a public-facing name as the entry key and include only public copy.
Unknown names without `repositoryUrl` or `standalone: true` are ignored. `repositoryUrl` also
overrides the repository link for existing entries. These settings control the
portfolio only; they do not change repository visibility on GitHub.

Do not put private repository names or private notes in this public file.

Validate edits with `node --test tests/portfolio.test.mjs`, then use the local
preview below. Commit changes and merge them to `main` to publish through the
existing GitHub Pages deployment. The encrypted admin page still manages GitHub
visibility and archiving; portfolio content is configured in this file.

When changing JavaScript or adding configuration fields, update the `v` query
in both the `index.html` app script URL and the `assets/app.js` portfolio import
to a new matching release value. GitHub Pages caches scripts for ten minutes;
these URLs prevent a cached validator from rejecting freshly loaded settings.

## Local preview

```bash
python -m http.server 8000
# open http://localhost:8000/       (public)
# open http://localhost:8000/releases.html (beta releases)
# open http://localhost:8000/admin.html  (admin, needs passphrase)
```

(A local server is only needed for `fetch()` to work on your machine; the
deployed site needs none.)

## Deploy

Serve the repository root from GitHub Pages (Settings → Pages → branch `main`,
`/root`). `.nojekyll` is present so files are served as-is.

The portfolio is published at [diegoami.github.io/home](https://diegoami.github.io/home/).

## Illustrated project destinations

The first four illustrated destinations live under `guides/`: Cerea Vice and
Oravitsa player guides, Goal2's screen design, and Imperial Conquest 2's
versioned v0.6.2 manual. Cards use explicit action labels so a design or manual
is not presented as a playable application. The other project links are unchanged.

Edit `guides/<project>/guide.md` and the shared `guides/manifest.json`, then run
`node tools/render-project-guides.mjs` (Node/npm required). It uses the pinned
build-only `marked@18.0.14` renderer. Commit the generated HTML and the curated
illustrations with their source references. Pages continues to serve static
files with no server or runtime dependency. Check image loading, contents links
and narrow-screen layout when updating a guide; keep design/version labels honest.
