{"id":28067577,"url":"https://github.com/arkham-build/arkham.build","last_synced_at":"2025-06-23T21:35:26.295Z","repository":{"id":244462845,"uuid":"815249822","full_name":"arkham-build/arkham.build","owner":"arkham-build","description":"Deck builder for Arkham Horror: The Card Game™","archived":false,"fork":false,"pushed_at":"2025-06-19T07:49:17.000Z","size":95915,"stargazers_count":35,"open_issues_count":10,"forks_count":18,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-19T08:40:53.740Z","etag":null,"topics":["arkham-horror","arkham-horror-lcg","deck-building"],"latest_commit_sha":null,"homepage":"https://arkham.build","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arkham-build.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-06-14T17:19:39.000Z","updated_at":"2025-06-19T07:49:21.000Z","dependencies_parsed_at":"2024-06-29T10:21:28.924Z","dependency_job_id":"769e3544-c69b-4d2a-ab3c-8afad92e7b5e","html_url":"https://github.com/arkham-build/arkham.build","commit_stats":null,"previous_names":["fspoettel/arkham.build","arkham-build/arkham.build"],"tags_count":107,"template":false,"template_full_name":null,"purl":"pkg:github/arkham-build/arkham.build","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkham-build%2Farkham.build","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkham-build%2Farkham.build/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkham-build%2Farkham.build/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkham-build%2Farkham.build/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arkham-build","download_url":"https://codeload.github.com/arkham-build/arkham.build/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arkham-build%2Farkham.build/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261559767,"owners_count":23177267,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arkham-horror","arkham-horror-lcg","deck-building"],"created_at":"2025-05-12T16:03:20.376Z","updated_at":"2025-06-23T21:35:26.280Z","avatar_url":"https://github.com/arkham-build.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# arkham.build\n\n\u003e [arkham.build](https://arkham.build) is a web-based deckbuilder for Arkham Horror: The Card Game™.\n\n## Metadata additions\n\narkham.build extends the _arkhamdb deck schema_ with a few fields for additional functionality.\n\n- `meta.extra_deck`: Parallel Jim's spirit deck. Format: comma-separated list of ids `\"id1,id2,id3\"`.\n- `meta.attachments_{code}`: cards that are attached to a specific setup deck, for example _Joe Diamond_ or _Stick to the Plan_. Format: comma-separated list of ids `\"id1,id2,id2,id3\"`.\n- `meta.card_pool`: packs that can be used for this deck. Used for limited pool deckbuilding such as #campaign-playalong. Format: `\"\u003cpack_code\u003e,\u003cpack_code\u003e\"`. For arkham.build, new format pack codes take precedence over old format. Single cards can be added to the pool by adding the `card:` prefix. Example: `card:02022` to add _Shortcut_.\n- `meta.card_pool_extension_{code}`: Some cards can extend the card pool with choices. This tracks their selection state. Format: `\"card:\u003ccode\u003e,card:\u003ccode\u003e\"`. \n- `meta.sealed_deck`: card ids that are pickable for this deck. Used for sealed deckbuilding. Format: comma-separated list of `id` / `quantity` pairs in the format `\"id:2,id:1,...\"`.\n- `meta.sealed_deck_name`: name of the sealed deck definition used. format: string.\n- `meta.transform_into`: code of the investigator that this deck's investigator has transformed into. I.e. `04244` for _Body of a Yithian_.\n- `meta.banner_url`: URL to an image to be displayed as banner for the deck. Preferably aspect ratio `4:1`.\n- `meta.intro_md`: Short deck introduction that uses the same markdown format that `description_md` uses.\n- `meta.annotation_{code}`: Annotation for a specific card that uses the same markdown format that `description_md` uses. Annotations are not limited to cards in deck, but can also target cards in the side deck (upgrades, alternatives) or _any_ card (reasoning for exclusion).\n\n### Additional metadata keys (AMK)\n\nArkhamDB imposes a strict limit on the amount of data that can be stored in the `meta` field of a deck. In order to work around this, we extract some of our custom metadata from `deck.meta` and store it in our own database before a deck is saved to ArkhamDB. The information is replaced with a token that can be used to retrieve it, the so called `amk`  (**a**dditional **m**etadata **k**ey). When a deck is fetched from ArkhamDB, our API consumes the entry and writes the actual metadata back to the `deck.meta`. The process is transparent to the API consumer.\n\nThe following fields are currently handled in this fashion:\n\n- `meta.annotation_{code}`\n- `meta.intro_md`\n- `meta.sealed_deck`\n- `meta.sealed_deck_name`\n\nThere is a public endpoint to resolve an `amk` via `GET https://api.arkham.build/v1/public/additional_metadata/:amk`.\n\n## File formats\n\n### Sealed decks\n\nThe sealed deck feature expects a csv file in the format:\n\n```csv\ncode,quantity\n01039,2\n01090,2\n06197,2\n07032,2\n```\n\nIn this example, the sealed deck contains two copies of _Deduction_, _Perception_, _Practice Makes Perfect_ and _Promise of Power_, so users would only be able to add these cards to their deck in the deck builder.\n\n## Development\n\n1. Create an `.env` file from `.env.example`.\n2. `npm install`\n3. `npm run dev`\n\n## Translations\n\nThe app and its data are fully translatable and PRs with new translations are _welcome_.\n\nTranslations for the user-interface are handled with [react-i18next](https://react.i18next.com/) and live in the `./src/locales/` folder as JSON files.\n\nTranslations for cards and metadata are sourced from the [arkhamdb-json-data](https://github.com/Kamalisk/arkhamdb-json-data) and the [arkham-cards-data](https://github.com/zzorba/arkham-cards-data) and assembled by our API.\n\n### Creating translations\n\n1. Create a copy of `en.json` in the `./src/locales` folder and rename it to your locale's ISO-639 code.\n2. Add your locale to the `LOCALES` array in `./src/utils/constants`.\n3. Run `npm run i18n:pull` to pull in some translations (traits, deck options) from ArkhamCards automatically.\n4. _(if your locale has translated card data)_ Create an issue to get the card data added to the card data backend.\n5. Translate and open a PR.\n\n### Updating translations\n\n1. Run `npm run i18n:sync` to sync newly added translation keys to your locale.\n2. (optional) If there are new _traits_ or _uses_ attributes that have been translated in ArkhamCards, run `npm run i18n:pull` to sync translations from ArkhamCards.\n3. Update the translation file and open a PR.\n\n## Architecture\n\narkham.build is a SPA app that, by default, stores data locally in an IndexedDB database. The SPA has several backend components that it uses to enrich functionality.\n\n### api.arkham.build\n\nThe API source code is tracked in a private git repo. It has a few functions:\n\n1. a cache for metadata  such as cards and sets.\n2. a cached proxy for public ArkhamDB endpoints.\n3. a [token-mediating backend](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps#name-token-mediating-backend) for authenticated ArkhamDB endpoints.\n4. a CRUD API for public _shares_.\n5. a generator for opengraph previews.\n\n### Recommendation API\n\nThe recommendation API is a seperate [project](https://github.com/TartanLlama/arkham-rec-provider/).\n\n### Cloudflare Pages functions\n\nWe leverage a few Cloudflare Pages functions for rewriting the HTML we serve to _some_ clients. Currently, this is used to inject OpenGraph tags for social media bots.\n\n## Icons\n\nArkham-related SVG icons are sourced from ArkhamCards's [icomoon project](https://github.com/zzorba/ArkhamCards/blob/master/assets/icomoon/project.json) and loaded as webfonts.\n\nIn order to update icon fonts, the workflow is:\n1. Load the icomoon project you want to update.\n2. Add the icons you want. Select everything and generate a font.\n3. Convert the font to `.woff2`.\n4. Replace the font, icomoon project in the assets directory.\n5. Update the CSS file from the generated icomoon css. If you are updating the `icon` icon set, beware that there are some manual overrides in the file (visible in the git diff).\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch2\u003eTemplate readme\u003c/h2\u003e\u003c/summary\u003e\n\n# vite-react-ts-template\n\n\u003e extended version of [vite](https://vitejs.dev/)'s official `react-ts` template.\n\nadditional features:\n\n- [biome](https://biomejs.dev/) for linting and code formatting.\n- [lefthook](https://github.com/evilmartians/lefthook) for pre-commit checks.\n- [vitest](https://vitest.dev/) for unit testing.\n- [playwright](https://playwright.dev/) for end-to-end testing.\n- [github actions](https://github.com/features/actions) for continuous integration.\n- [browserslist](https://github.com/browserslist/browserslist) + [autoprefixer](https://github.com/postcss/autoprefixer).\n\n## Install\n\n```sh\n# install dependencies.\nnpm i\n```\n\n## Develop\n\n```sh\nnpm run dev\n```\n\n## Build\n\n```sh\nnpm run build\n```\n\n## Test\n\n```sh\nnpm test\n\n# run vitest in watch mode.\nnpm run test:watch\n\n# collect coverage.\nnpm run test:coverage\n```\n\n## Lint\n\n```sh\nnpm run lint\n```\n\n## Format\n\n```sh\nnpm run fmt\n```\n\nPrettier will be run automatically on commit via [lint-staged](https://github.com/okonet/lint-staged).\n\n## Preview\n\nServes the content of `./dist` over a local http server.\n\n```sh\nnpm run preview\n```\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farkham-build%2Farkham.build","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farkham-build%2Farkham.build","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farkham-build%2Farkham.build/lists"}