Primary: Best Use of User Contributions (UGC).
Every competitor is a user drawing: stroke capture, morph close, marching squares, simplify, Matter.Bodies.fromVertices (poly-decomp, convex hull fallback). Nightly brackets, champion defense, and auto result comments turn UGC into the full social loop.
Secondary: Hook + Phaser.
Champion re-seed, grudge/spar, and morning bracket browsing are the return reasons. Live client Matter re-sim of the same seeded fight is the spectacle layer on top of server authority.
What it is (player loop in 10 seconds)
- Expand → paper canvas, draw a champion (stroke limits enforced).
- Submit: server traces ink → collider verts + stats (mass, reach, stamina, crit).
- Same-session spar vs champion (or mini-spar) so payoff is instant.
- Fighter enters tonight's roster.
- Nightly job runs the bracket; morning: watch rounds, POST RESULT, grudge a rival.
Why we built it
UGC wins when user content is not decoration. Here the drawing is the physics body and the competitive unit. Server-side headless Matter makes outcomes authoritative for comments and brackets. Seed fighters keep empty nights playable for judges without faking a human roster as "real players."
How it works (architecture)
| Layer | Role |
|---|---|
| Devvit webview | splash.html ink feed card; game.html Phaser + draw overlay |
| Client Phaser 4.2 | Home, Draw, Bracket, Replay/Grudge; optional live Matter re-sim |
| Hono API | Draw submit, init/roster, bracket fetch, grudge, share comment |
| Redis | Fighters, pending queue, bracket trees, champion, leaderboard, moderation flags |
| Scheduler | 0 3 * * * nightly-bracket: seed, sim matches, store replays, update champion |
| Shared | trace.ts, fightSim.ts (same Matter core client/server), replay codec |
| Mod tools | Review pending drawings form; "Run nightly bracket now" menu for demos |
Fight authority: server simulateFight packs frames and results. Client LiveMatterFight re-runs with the same seed and verts for spectacle; lerp fallback if live init fails.
Virality / hook (why return tomorrow + why share)
Return: Did my scrawl win the night? Champion badge auto-re-enters seed #1. Grudge match against a named rival's latest fighter.
Share: POST /api/share posts result lines to the feed. Fight poster CTAs. Friend challenge + crest on splash for "draw something better than this."
Reddit-native features
- UGC fighters identified with real Reddit usernames.
- Nightly tournament results as comment surface (margin-flavored copy).
- Moderator review queue for pending drawings.
- Crest renown chip + friend challenge row (invite by username energy).
- Grudge API targets another user's fighter by username.
- Async multiplayer: draw today, fight tonight, spectate tomorrow.
Not karma-as-theme: ink, sumo ring, champion throne. Reddit is authorship and trash-talk venue.
Demo post / subreddit
| Field | Value |
|---|---|
| Subreddit | r/scrawl_fight_dev |
| App owner | u/proffesor1729 |
| Devvit package | scrawl-fight |
| Product name | Scroll Fighter |
| Demo post | (mod menu: "Create a new post" → paste URL here after publish) |
| Demo tip | Use "Run nightly bracket now" after a few draws so judges see a full tree |
Tech stack
- Client: Phaser 4.2, Matter.js, Vite 8, TypeScript, DOM draw surface
- Server: Hono, Devvit 0.13.6, headless Matter + poly-decomp, Redis
- Shared: trace pipeline, fight sim, constants contract
- Tests:
npm run test:brawl - Platform: Node >= 22.2; Redis + Reddit permissions
What judges / users should do first (60s path)
- Open the demo post → expand.
- Draw a bold blob with a few detail strokes → BRAWL!
- Watch submit celebration / spar vs champion.
- Open Bracket (or run nightly now if empty) → tap a match.
- Watch live Matter or packed replay.
- POST RESULT / share once; optional grudge by username.
Proof of production
- Package name
scrawl-fightwith real cron, forms, and Redis fighter storage. - Tracing and stats derived from submitted strokes/masks, not preset avatars.
- Bracket outcomes from headless Matter; shared
fightSimused for determinism. ensureSeedFightersfills thin rosters with AI shapes so nights resolve; human draws still enter the same pipeline.- Share hits
POST /api/share→ Reddit comment when post context exists. - Brawl tests cover sim/codec without placeholder outcomes.
Built With
- devvit
- hono
- matter.js
- phaser-4.2
- reddit-karma
- reddit-usernames-for-ugc
Log in or sign up for Devpost to join the conversation.