{"id":51699082,"url":"https://github.com/edycutjong/redacted-game","last_synced_at":"2026-07-16T08:33:47.019Z","repository":{"id":371335121,"uuid":"1300532640","full_name":"edycutjong/redacted-game","owner":"edycutjong","description":"🕵️ Asymmetric-information detective game — each player holds different censored evidence; zero AI, handcrafted linted cases (Devvit)","archived":false,"fork":false,"pushed_at":"2026-07-15T07:31:52.000Z","size":732,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-16T08:33:42.807Z","etag":null,"topics":["deduction-game","detective-game","devvit","games-with-a-hook","hackathon","puzzle-game","react","reddit","reddit-games","typescript"],"latest_commit_sha":null,"homepage":"https://edycutjong.github.io/redacted-game/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edycutjong.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-14T13:36:03.000Z","updated_at":"2026-07-15T07:31:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/edycutjong/redacted-game","commit_stats":null,"previous_names":["edycutjong/redacted-game"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/edycutjong/redacted-game","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fredacted-game","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fredacted-game/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fredacted-game/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fredacted-game/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edycutjong","download_url":"https://codeload.github.com/edycutjong/redacted-game/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fredacted-game/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35537751,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-16T02:00:06.687Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["deduction-game","detective-game","devvit","games-with-a-hook","hackathon","puzzle-game","react","reddit","reddit-games","typescript"],"created_at":"2026-07-16T08:33:43.461Z","updated_at":"2026-07-16T08:33:47.011Z","avatar_url":"https://github.com/edycutjong.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/icon.svg\" alt=\"REDACTED\" width=\"144\" height=\"144\" /\u003e\n  \u003ch1\u003eREDACTED\u003c/h1\u003e\n  \u003cp\u003e\u003cem\u003enot trivia — closed-world deduction; zero AI, handcrafted linted cases\u003c/em\u003e\u003c/p\u003e\n  \u003cimg src=\"docs/readme-hero.svg\" alt=\"REDACTED — a daily mystery no single reader can solve alone\" width=\"100%\" /\u003e\n\n  \u003cbr/\u003e\u003cbr/\u003e\n\n  [![Play on Reddit](https://img.shields.io/badge/Play_on-Reddit-FACC15?style=for-the-badge\u0026labelColor=0B0A07)](https://www.reddit.com/r/the_redacted_game_dev/)\n  [![Watch Demo](https://img.shields.io/badge/Watch-Demo-F43F5E?style=for-the-badge\u0026labelColor=0B0A07)](https://www.youtube.com/watch?v=nWXwBE4XXTs)\n  [![Devpost](https://img.shields.io/badge/View_on-Devpost-003E54?style=for-the-badge\u0026labelColor=0B0A07)](https://devpost.com/software/redacted-0jze1y)\n  [![Landing Page](https://img.shields.io/badge/Landing-Page-FACC15?style=for-the-badge\u0026labelColor=0B0A07)](https://edycutjong.github.io/redacted-game/)\n  [![Pitch Deck](https://img.shields.io/badge/Pitch-Deck-F43F5E?style=for-the-badge\u0026labelColor=0B0A07)](https://edycutjong.github.io/redacted-game/pitch/)\n  [![Games with a Hook](https://img.shields.io/badge/Reddit-Games_with_a_Hook-8B5CF6?style=for-the-badge\u0026labelColor=0B0A07)](https://redditgameswithahook.devpost.com)\n\n  \u003cbr/\u003e\n\n  ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat\u0026logo=typescript\u0026logoColor=white)\n  ![React 19](https://img.shields.io/badge/React_19-0B0A07?style=flat\u0026logo=react\u0026logoColor=61DAFB)\n  ![Devvit 0.13](https://img.shields.io/badge/Devvit_0.13-FF4500?style=flat\u0026logo=reddit\u0026logoColor=white)\n  ![Vitest](https://img.shields.io/badge/Vitest-269_passing-6E9F18?style=flat\u0026logo=vitest\u0026logoColor=white)\n  ![Coverage](https://img.shields.io/badge/coverage-100%25-6E9F18?style=flat\u0026logo=vitest\u0026logoColor=white)\n  [![CI](https://github.com/edycutjong/redacted-game/actions/workflows/ci.yml/badge.svg)](https://github.com/edycutjong/redacted-game/actions/workflows/ci.yml)\n\u003c/div\u003e\n\nA daily noir detective case lives inside a Reddit post. Every player's dossier is\n**censored differently**: a deterministic deal hands each viewer a few unredacted\nlines out of ~40 clue shards that the crowd doesn't have yet. Nobody can solve the\ncase alone — the comment thread becomes the evidence board where the subreddit\ncollectively un-redacts the truth, flags contradictions, and votes an accusation\nbefore the verdict ceremony. A judge who opens the post isn't evaluating a game;\nwithin 30 seconds they're personally holding a line 400 strangers need.\n\nIt is **not trivia** (closed-world deduction over fictional evidence — no outside\nknowledge helps) and **not collaborative storytelling** (one authored ground\ntruth, a win/lose verdict). There is **zero runtime AI**: all 3 launch cases are\nhandcrafted and pass an offline solvability linter. In an anti-AI-slop hackathon,\nthat is the whole point, stated out loud.\n\n## 🎮 How to play\n\n1. **RECEIVE** — open the case folder (`CASE #17 · DAY 3 · 61% UNREDACTED`). One\n   black bar is *yours*: tap it and the redaction peels off to reveal your line\n   (\"the pawn ticket was dated the 14th — two days AFTER the fire\").\n2. **READ THE BOARD** — evidence cards other players filed; contradiction pairs\n   glow red where both sides are on the board (the red string is *computed*, not\n   moderated).\n3. **FILE** — one tap posts your line as a typeset evidence-card comment, under\n   your username if you consent (asUser `SUBMIT_COMMENT`) or via the app account\n   otherwise. The case meter ticks up; the ACCUSE bars shift.\n4. **ACCUSE / RETURN** — stake season points on one suspect (locked in a single\n   transaction, one accusation per case). At the scheduled hour the verdict\n   ceremony crowns the earliest correct accusers and cites the cards that cracked\n   it; a new case drops at 00:00.\n\n**The population-elasticity valve:** after case-hour 12 a scheduler drips the\nsingle highest-information unfiled shard onto the public board every hour, so even\na 30-member sub closes every case and a judge arriving mid-case always lands in a\nlive investigation. A solo **Cold Case Archive** replays closed cases against the\nrecorded solve timeline — no liveness dependency for judges.\n\n**The witnessable \"I am needed\" beat (seeded Case #17).** The demo seed leaves the\ncrowd-favorite watchman *standing* at exactly **61%** — the crowd has already\ncleared the widow and the rival, and the whole board is stuck arguing about him.\nFiling your reserved pivot shard (the pawn ticket) ticks the meter **61 → 63%**,\n**strikes the watchman**, and lights the second red string — in one tap. That beat\nis deterministic (`core/demoSeed.ts`), proven at build time (lint **LD**), and\nlocked by tests, so a lone cold judge witnesses their own impact.\n\n## 🏗️ Architecture (verified Devvit surface only)\n\n```\nsrc/client/     React, DOM/CSS only — paper folder, typewriter type, redaction-peel\nsrc/server/     Hono over the Devvit runtime\n  core/         PURE engine: hash, dealer, deduction, drip, verdict, meter,\n                contradictions, filters, cardMarker, time, demoSeed  (no platform imports)\n  store.ts      the ONLY Redis-touching layer (hashes + zsets + watch/multi/exec)\n  serialize.ts  the I2 boundary — builds client responses, never touches truth\n  routes/       thin adapters: /api/*, /internal/{cron,triggers,menu}/*\ntools/case-compiler/   offline YAML → sealed bundle + solvability linter\ncases/*.yaml    the authored cases (compiled to cases/compiled/*.bundle.json)\n```\n\n```mermaid\nflowchart TD\n  subgraph Authoring [offline]\n    Y[cases/*.yaml] --\u003e CC[case compiler + linter] --\u003e B[sealed bundles]\n  end\n  B --\u003e|devvit upload assets| R\n  subgraph Client [React webview]\n    D[Dossier + peel] --\u003e|/api/my-shards| S\n    E[Evidence board] --\u003e|/api/board| S\n    F[File card] --\u003e|/api/file| S\n    G[Accuse] --\u003e|/api/accuse| S\n    H[Verdict + Archive] --\u003e|/api/verdict, /api/archive| S\n    E \u003c--\u003e|realtime tiles| RT[realtime]\n  end\n  subgraph Server [Devvit Node]\n    S[Hono] --\u003e R[(Redis)]\n    C1[cron case-drop 00:00] --\u003e R\n    C2[cron drip hourly] --\u003e R\n    C3[cron verdict 21:00] --\u003e RED[Reddit API]\n    T1[onComment] --\u003e R\n    T2[onPostCreate] --\u003e R\n    M[menu: Seed/Bonus/Approve/Hide] --\u003e R\n    S --\u003e|asUser SUBMIT_COMMENT| RED\n  end\n```\n\nFull Redis schema (`case:{id}:public` vs **`case:{id}:truth`**, `shards`/`board`/`card`\nhashes, `pivot`/`board`/`accuse`/`rank:season`/`rep:cited` zsets) and endpoint tables are in\n[`ARCHITECTURE.md`](ARCHITECTURE.md). **No plain redis lists/sets, empty\nfetch allowlist, no runtime AI** — enforced by design.\n\n### Four invariants\n\n| # | Invariant | Where it lives |\n|---|-----------|----------------|\n| I1 | Deal is pure + deterministic — same viewer always sees the same lines | `core/dealer.ts` + first-write-wins persistence in `store.dealFor` |\n| I2 | No endpoint returns undealt shard text or any truth field | truth split at **compile time**; `serialize.ts` is the only response builder |\n| I3 | Pivot pool drains before duplication — every fresh viewer (every judge) gets a board-absent shard while pivots remain | `pivot:{id}` zset drained head-first in `store.dealFor` |\n| I4 | One accusation per (user, case), stake locked | `store.accuse` under `watch/multi/exec` |\n\n## 🗂️ Case format\n\nA case is one YAML file (schema: `tools/case-compiler/types.ts`, guide:\n[`cases/README.md`](cases/README.md)). In brief:\n\n- `suspects` (≥3), `docs` (≥2) whose `lines` are either `text:` or a `shard:` ref,\n  `shards` (≥20) each `{id, doc, text, supports:[factIds]}`,\n- `facts` (≥4) — atomic truths, each established by ANY one of its supporting\n  shards being on the board,\n- `eliminations` — per non-culprit suspect, ≥2 paths (a path is a conjunction of\n  factIds; any complete path strikes the suspect),\n- `contradictions` (≥2) annotated shard pairs, `pivots` (≥1) reserved for\n  first-seen accounts, and a `truth` block (`culprit`, `motive`, `summary`,\n  `reveal[]`). The culprit has **no** elimination entry — they can never be struck.\n\nThe compiler splits the sealed bundle into a **public half** (`src/shared`) and a\n**server-only truth half** (`src/server/cases/types.ts`) so truth cannot be\nserialized to a client by construction.\n\n## 🧩 Solvability linter (the moat)\n\n`npm run lint:cases` runs three levels over every case (`tools/case-compiler/lint.ts`):\n\n- **L1 solvability** — the culprit is uneliminable; every other suspect is\n  eliminable by ≥2 **shard-disjoint** combinations; and a seeded **Monte-Carlo of\n  1,000 random 60% deals all reach the truth** (all non-culprits struck). The MC\n  uses the *same* deduction engine as the runtime, so gameplay and lint can never\n  diverge.\n- **L2 drama** — ≥2 annotated contradiction pairs; no orphan shards (every shard\n  participates in some elimination path).\n- **L3 safety** — profanity / link / real-user-resemblance (`u/`, `r/`) filter over\n  all case text; sealed bundle ≤ 200KB.\n- **LD demo** — when a case names a demo `reserve:` suspect, *prove the magic\n  moment*: on the planned ~61% seed the reserved crowd-favorite is still standing,\n  and filing a reserved pivot shard strikes them. The \"I am needed\" beat is a\n  build guarantee, not a hope — same deduction engine as L1.\n\nCurrent status (`npm run lint:cases`):\n\n```\n✓ case-017 \"The Larchmont Fire\" — 49 shards, 4 suspects, MC 1000/1000, bundle 16.3KB\n✓ case-018 \"The Halloway Vault\" — 40 shards, 4 suspects, MC 1000/1000, bundle 13.3KB\n✓ case-019 \"The Gilt Cage\"      — 40 shards, 4 suspects, MC 1000/1000, bundle 13.7KB\n```\n\n## ✅ Tests\n\n**269 vitest tests across 17 files** (`npm test`), all green, against the pure\ncores + an in-memory Redis stub that implements the real `RedisClient` surface\n(including `watch/multi/exec` optimistic concurrency) and Hono routes with\n`@devvit/web/server` mocked out end-to-end:\n\n| file | n | covers |\n|---|---|---|\n| store.test.ts | 37 | deal determinism (I1), pivot drain (I3), accusation escrow under contention (I4), seed determinism, **reserve-aware seed + witnessable strike**, file/drip/verdict idempotency, degenerate/partial-data edge cases |\n| routes/api.test.ts | 37 | all `/api/*` endpoints end-to-end (case/my-shards/file/board/accuse/verdict/archive), consent-gated comment fallback, litContradiction + elimination deltas, best-effort realtime |\n| routes/internal.test.ts | 32 | scheduler crons (drop/drip/verdict), the onComment trigger reconciliation, mod-menu actions, idempotency + best-effort Reddit side-effects |\n| linter.test.ts | 28 | Monte-Carlo per case, disjointness, L2/L3, **LD demo magic-moment** proof, negative mutations |\n| drip.test.ts | 28 | information-gain ordering, hour-12 gate, **10/100/1000-player closure sims** |\n| deduction.test.ts | 15 | fact/path/elimination/truth-reached per authored case |\n| hash.test.ts | 14 | fnv1a / mulberry32 / pickK determinism, bar width id-derived |\n| verdict.test.ts | 13 | idempotent resolve, podium payouts, citation rules, public-record earns no citation |\n| filters-marker.test.ts | 12 | L3 filters, note sanitizer, comment-marker round-trip |\n| serialize.test.ts | 11 | **I2 — truth never serialized**, censored bars carry no text |\n| dealer.test.ts | 10 | deterministic deal + pivot reservation |\n| meter-time.test.ts | 8 | meter clamping, case-day / verdict clock |\n| contradictions.test.ts | 6 | lit / newly-lit deltas |\n| postComment.test.ts | 6 | consent-gated comment posting + app-account fallback chain |\n| shared.test.ts | 5 | realtime channel naming, rank tiers, redis key schema |\n| viewer.test.ts | 4 | logged-out → loid → anon fallback chain |\n| demoSeed.test.ts | 3 | synthetic-bundle branches the 3 authored cases never happen to hit |\n\n`npm run type-check` (`tsc --noEmit`) is clean; `npm run build` emits\n`dist/client/{splash,game}.html` + `dist/server/index.cjs`.\n\n### Coverage\n\n`npm run test:coverage` enforces a **100% statements/branches/functions/lines**\ngate (vitest.config.ts), scoped to the pure/mockable business logic —\n`src/shared/**`, `src/server/core/**`, `src/server/cases/**`,\n`src/server/routes/**`, and the single Redis-touching `store.ts` +\n`serialize.ts` + `keys.ts` + `viewer.ts` + `postComment.ts` + `redisLike.ts`.\nExcluded on purpose: `src/client/**` (React/DOM rendering — needs a real\nbrowser) and `src/server/index.ts` (process bootstrap — calls\n`createServer(...).listen(...)` at import time). 15 lines carry a narrow\n`/* v8 ignore */` with a one-line rationale, all for data-integrity guards\nthat are unreachable given the compiler's own validation (e.g. every\nelimination-path fact id is checked against the case's fact set at compile\ntime) or a fixed, non-empty generated registry — never a shortcut around a\nreal test.\n\n## ⚙️ Engineering harness\n\n| Layer | Tool | Where |\n|---|---|---|\n| Type safety | `tsc --noEmit` (strict) | CI · `npm run type-check` |\n| Lint | ESLint 9 + typescript-eslint (flat config) | CI · `npm run lint` |\n| Unit tests + coverage | Vitest — 269 tests / 17 files, 100% on the pure/mockable core (real-surface Redis stub) | CI · `npm run test:coverage` |\n| Content quality | Solvability + demo linter (MC 1000/1000) | CI · `npm run lint:cases` |\n| Build | Vite → `dist/client` + `dist/server` | CI · `npm run build` |\n| SAST | CodeQL (`javascript-typescript`) | `.github/workflows/codeql.yml` |\n| Supply chain | Dependabot (npm + actions, weekly) | `.github/dependabot.yml` |\n\n`.github/workflows/ci.yml` runs the five real gates on **Node 20**:\n`npm ci → lint → type-check → test:coverage → lint:cases → build`.\n\n**Deliberately N/A — Lighthouse CI and Playwright-against-localhost.** This is a\nDevvit Web app: the client is bundled into `dist/client/*.html` and served by the\nReddit runtime inside a webview, so there is no localhost server to point a\nheadless browser or Lighthouse at. Interactive verification is `devvit playtest`\n(human-run — see the First-playtest checklist below).\n\n## ⚠️ Honest limitation: off-platform sharing\n\nDeterministic per-viewer censorship means a determined group **can** screenshot\ntheir shards into a Discord and pool them off-platform. We do **not** claim to\nprevent this, and it isn't a leak of the ground truth (the truth section never\nleaves the server — I2): a screenshot only reveals shards those accounts were\nalready dealt. In practice that behaviour *is* the game — the evidence board just\nformalizes and rewards (citation economy) the un-redaction the crowd would do\nanyway. The design leans into sharing rather than pretending to stop it.\n\n## 📋 First playtest checklist (do this in order)\n\nYou (the human) run these — an agent cannot run `devvit playtest`.\n\n1. **Create the test subreddit from your aged main account on day one.** New\n   hackathon subreddits are being **auto-banned (\"Rule #2\")** by Reddit safety\n   automation, *including a re-ban immediately after you install a Devvit app*.\n   Front-load the round-trip: create r/the_redacted_game_dev, add a normal pinned post\n   *before* installing anything, and keep the unban-request forum thread handy —\n   staff unban manually when you post `username + subreddit`. Expect a second\n   ban at first app install.\n2. `npm run login` (`devvit login`), then `npm run dev` (`devvit playtest\n   r/the_redacted_game_dev`).\n3. **Probe the onComment payload before trusting the parser.** The\n   `onCommentCreate` trigger exists (docs-cache `triggers.md`) but the exact\n   `CommentV2` field shape is only confirmed at runtime. The handler\n   (`src/server/routes/internal.ts`) is a **defensive adapter** that reads every\n   field optionally and no-ops on anything unrecognised — file one card, watch the\n   logged payload, confirm `comment.body` / `comment.author`, then tighten.\n4. From the mod menu run **REDACTED: Seed Demo Case** → restores Case #17 at ~61%\n   with the pivot pool full and the first contradiction lit (idempotent). Open the\n   post, peel your shard, file it, watch the meter tick and a suspect bar shift.\n5. Verify the three crons (`/internal/cron/{drop,drip,verdict}`) — all idempotent —\n   and, if you want extra live cases during judging, **REDACTED: Launch Bonus Case**.\n6. `npm run check:submission` to re-run the readiness gate before you record video.\n\n## 📮 Submission checklist\n\nRun `npm run check:submission` before submitting. The demo-post URL stays a\nplaceholder (and the gate stays red) until the post is live.\n\n\u003e **The remaining `[ ]` items need no app approval — do them now.** The Reddit\n\u003e review only unlocks the *public* App Directory listing + icon; judging happens on\n\u003e your (public) test sub, which is entirely in your control.\n\n- App listing: https://developers.reddit.com/apps/the-redacted-game\n- Devpost project: https://devpost.com/software/redacted-0jze1y\n- Demo video: https://www.youtube.com/watch?v=nWXwBE4XXTs\n- Demo post: https://www.reddit.com/r/the_redacted_game_dev/s/f04ylDXAJr\n- [x] `npm run lint` clean\n- [x] `npm run type-check` clean\n- [x] `npm test` green (269/269), `npm run test:coverage` at 100%\n- [x] `npm run build` succeeds\n- [x] Published to the App Directory (`devvit publish`, in review)\n- [x] 60-second demo video recorded \u0026 published (link above)\n- [x] Public repo + Devpost project page linked\n- [x] `r/the_redacted_game_dev` set to **Public**, demo post seeded (`Seed Demo Case`) and verified against `DEMO.md`\n- [ ] Demo-post URL filled above + Devpost form submitted\n\n## 💻 Commands\n\n```\nnpm run lint           # eslint .\nnpm run type-check     # tsc --noEmit\nnpm test               # vitest run  (269 tests)\nnpm run test:coverage  # vitest run --coverage  (100% on shared/core/routes/store)\nnpm run lint:cases     # solvability linter over cases/*.yaml\nnpm run compile:cases  # emit cases/compiled/*.bundle.json + src/server/cases/registry.ts\nnpm run build          # vite build → dist/client + dist/server\nnpm run dev            # devvit playtest  (you run this)\nnpm run check:submission\n```\n\n## 🔖 Versioning\n\nAutomatic semantic versioning via [semantic-release](https://semantic-release.gitbook.io/):\nevery push to `main` parses [Conventional Commits](https://www.conventionalcommits.org/)\n(`fix:` → patch, `feat:` → minor, `BREAKING CHANGE:` → major) and, when warranted,\nbumps `package.json`, updates `CHANGELOG.md`, tags the commit, and publishes a\nGitHub Release with generated notes (`.github/workflows/release.yml`). No manual\nversion bumps, no npm registry publish (private app).\n\n## 📄 License\n\n[MIT](LICENSE) © 2026 Edy Cu. Built for Reddit's *Games with a Hook* hackathon.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedycutjong%2Fredacted-game","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedycutjong%2Fredacted-game","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedycutjong%2Fredacted-game/lists"}