{"slug": "monster-maker-it-s-like-daily-doodle-but-with-100-percent-more-monsters", "title": "Monster Maker! It's like Daily Doodle but with 100 percent more Monsters", "summary": "A developer built Monster Maker, a free no-signup drawing prompt generator for monsters, by forking the engine behind their existing Daily Doodle site with the help of Claude. The project involved reworking the sentence builder for monster-specific grammar, writing Firebase security rules, adding a share feature, and having an AI agent record its own tutorial video.", "body_md": "[Disco Doodle](https://discodoodle.com) is my hobby site — free, no-signup drawing prompt generators, a division of my little umbrella brand [Plaid Labs](https://theplaidscientist.github.io/). Daily Doodle was the original: pick a few categories (animal, occupation, prop, style...), hit spin, get a silly little drawing idea. Sometimes you just need to get past that blank page. More on that [here.](https://dev.to/plaidscientist/i-vibe-coded-my-first-app-ever-a-daily-drawing-prompt-spinner-beginner-advanced-modes-sound-ble-temp-slug-6383031?preview=b762184a3071d0eebdebf6979c59cd0162fdad6d253c77bf0d990c290352d49974bd8142d01f63d6fccb724114d9dc1099f66fe84aa2e1decbbf909a)\n\nA while back I asked Claude to build a second generator, Monster Maker, as a straight-up fork of Daily Doodle's engine but with monster-flavored categories: eyeballs, horns, skin texture, arm style, eyestalks, patterns, a \"silly / scary / sleepy\" vibe dial. Same beginner/advanced modes, same spin animation, same everything under the hood — just a new skin and a new set of categories.\n\nThat part went fast. What I actually want to write about is everything that happened *after* \"it works\" — the design back-and-forth, a Firebase security rules rabbit hole, building a share feature that doesn't feel like an ad, and then talking an AI agent into recording its own tutorial video of the thing it just built.\n\nMonsters are different than drawing animals or people. I relate to drawing them because they can't look, \"wrong\". No one can say your proportions are off, or you forgot to add a nose, or hey that arm is longer than the other...because it's a monster. They only enter our world at nighttime while we're sleeping. Via a network of magical doors... oh wait.\n\nSmall but real gotcha worth mentioning: I was working in a fresh Cowork session, and it had no memory of Daily Doodle's code — it lives on my machine / in the repo, not in the AI's head. So the very first thing that happened wasn't code, it was a clarifying question: *do you have the file, can I reach your computer, or should I build from scratch?*\n\nI pasted the whole `daily-doodle.html` file in. From there the fork was genuinely mechanical — same CSS custom properties, same category-card component, same slot-machine spin animation, just new data:\n\n``` js\nconst categories = {\n  eyeballs:    { label: \"Eyeballs\",     icon: \"👀\", color: \"card-teal\",   items: [\"No Eyes\",\"One Eye\",\"Two Eyes\",\"Three Eyes\",\"Five Eyes\",\"A Dozen Eyes\"] },\n  horns:       { label: \"Horns\",        icon: \"😈\", color: \"card-blue\",   items: [\"No Horns\",\"One Horn\",\"Two Horns\",\"Three Horns\",\"Four Horns\",\"A Crown of Horns\"] },\n  skinTexture: { label: \"Skin Texture\", icon: \"🖐️\", color: \"card-purple\", items: [\"Hairy\",\"Slimy\",\"Scaly\",\"Bumpy\",\"Fuzzy\",\"Leathery\"] },\n  // ...armStyle, eyestalks, pattern, vibe\n};\nconst CORE_KEYS = ['eyeballs', 'horns', 'skinTexture']; // beginner mode\n```\n\nThe sentence builder was the one piece that actually needed new logic, since \"Your monster has Two Eyes and Four Horns, with Hairy skin, wiggly eyestalks...\" doesn't follow the same grammar as Daily Doodle's \"a [style] drawing of a [job] [animal] wearing [outfit].\" Small thing, but it's the difference between a reskin and something that reads like it was actually written for monsters.\n\nThis is the part I'll happily admit: I could not settle on a background, and the AI just... kept building whatever I said next. Light blue polka dots. Then \"big scalloped scales, olive green and khaki\" (which, credit where due, it built as actual CSS `radial-gradient` math and got right on basically the first try — no image assets, just gradients tiled in an offset grid). Then \"actually just olive green with giant polka dots.\" Then \"remove the polka dots.\" We landed on flat olive green.\n\nI really just didn't want it to look ugly, but wanted it to be fun when you changed from Daily Doodle to Monster Maker. A few of the tries were exactly what I asked for, and what I asked for was wrong and hideous!\n\nThe one genuinely useful thing that came out of that back-and-forth: once the background got dark, the plain gray subtitle/instruction text became almost unreadable against it. Rather than just darkening the text globally, the fix was giving those bits of text the same rounded \"pill\" treatment the app already used for buttons and badges — so it reads as an intentional design choice instead of a patch:\n\n```\n.subtitle {\n  display: table; margin: 8px auto 0;\n  background: rgba(255,255,255,0.8);\n  padding: 2px 14px; border-radius: 999px;\n}\n```\n\nSmall detail, but it's the kind of thing that's easy to miss when you're iterating fast — worth actually looking at your own contrast, not just trusting that \"it compiles.\"\n\nBoth generators share one Firebase Realtime Database for their visitor counters — `/counters/dailyDoodle` and `/counters/monsterMaker`, two independent keys in the same JSON tree. That part's simple. What wasn't obvious to me was *why* the counter worked for one and not the other, and whether I needed a whole second Firebase project.\n\nI ended up screenshotting my actual Firebase console rules tab a couple of times and just asking \"does this help?\" The short version of what I learned: Realtime Database rules can be scoped to a specific path or left wide open at the root, and my original rules were the *default test-mode* rules — open, but with a hard expiry date baked in (`\"now < <timestamp>\"`). That's the kind of thing that quietly breaks a hobby project months later with zero warning. We replaced it with a permanent rule scoped just to `/counters`:\n\n```\n{\n  \"rules\": {\n    \"counters\": {\n      \".read\": true,\n      \".write\": true\n    }\n  }\n}\n```\n\nOpen where it needs to be, closed everywhere else, no expiry ticking down in the background.\n\nThe ask was: after you spin, let people save an image — the result sentence, a counter badge, something you'd actually want to post next to a photo of your drawing — without it screaming \"please post my app.\" That \"not overly promotional\" constraint mattered more than it sounds like it should.\n\nThe whole thing is a `<canvas>` element, never attached to the page, rendered on demand and downloaded as a PNG:\n\n```\nasync function buildShareImageBlob() {\n  // measure the sentence first on a scratch canvas, so the final\n  // canvas can size itself to the text instead of leaving dead space\n  const lines = wrapCanvasText(measureCtx, sentenceText, cardWidth - cardPadX * 2);\n  const cardHeight = cardPadY * 2 + lines.length * lineHeight;\n  const H = Math.max(680, cardY + cardHeight + 160);\n  // ...draw wordmark, badge, card, and a small watermark bottom-right\n  return new Promise(resolve => canvas.toBlob(resolve, 'image/png'));\n}\n```\n\nThat \"measure first, then size the canvas\" step mattered a lot in practice — a short beginner-mode sentence and a long seven-category advanced-mode sentence are wildly different lengths, and a fixed-size card either wastes half the image on empty space or clips the text. Sizing the canvas to the content fixed both at once.\n\nThe watermark is one small line of text in a corner, not a banner. That was the actual design decision — the whole point is that someone wants to post this next to their own art, and a self-promotional overlay works against that.\n\nThis is a screenshot from the test of the daily doodle verison. I probably misplaced the Monster Maker one.\n\nThis is the bit I'd actually recommend trying yourself. Once the app worked, I asked for a vertical walkthrough video — and rather than screen-recording a live demo, the approach was to script an actual headless-browser session that performs the demo itself: type into the input, click spin, click share, all timed out, with a synthetic cursor and text captions injected directly into the page so they show up *in* the recording.\n\n``` js\nasync function tapEl(page, selector) {\n  const handle = await page.$(selector);\n  await handle.scrollIntoViewIfNeeded();\n  const box = await handle.boundingBox();\n  await moveCursorTo(page, box.x + box.width / 2, box.y + box.height / 2);\n  await handle.click();\n}\n```\n\nThe cursor and captions are just DOM elements injected via `page.evaluate()` before the \"recording\" starts — a styled `<div>` that animates to each click target, and a caption pill that updates at each beat (\"Add your own ideas to any category,\" \"Tap Spin for an instant idea!\"). Since they're real elements on the real page, Playwright's built-in video recorder captures them for free.\n\nTwo bugs worth knowing about if you try this:\n\n`size` you give it.`recordVideo.size` is bigger than your CSS viewport, it pastes the unscaled frame into the corner of the bigger canvas instead of stretching it — you get a video that's mostly gray dead space. Fix: record at your real viewport size and let `ffmpeg` do a proper upscale afterward.`html { min-height: 100%; background: ...; }`) injected just for the recording session solved it without touching the real site's CSS.\n\n```\nffmpeg -i raw.webm -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 \\\n  -vf \"scale=1080:1920:flags=lanczos,fade=t=in:st=0:d=0.4\" \\\n  -c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p \\\n  -c:a aac -shortest -movflags +faststart walkthrough.mp4\n```\n\n(The silent audio track is deliberate — some platforms handle video-with-no-audio-stream oddly, so `anullsrc` gives it one for free.)\n\nI asked for a voiceover next, and this is the honest part: there's no ElevenLabs- or OpenAI-quality voice available in that sandbox. What *was* available: `espeak-ng` (classic robotic TTS, works instantly, zero setup) and Piper, a free offline neural TTS that's a meaningful step up in naturalness — installable in about thirty seconds, no API key, no network dependency at runtime.\n\nI still haven't posted this video. I'm not sure why. Anyone else get super self-conscious before posting to social media? Me neither!\n\nWhat I did get out of the AI: a clean, timed caption script broken into beats that match the video almost to the second, ready to paste into whatever TTS tool I wanted:\n\n```\n0:00–0:03 — \"Welcome to Monster Maker.\"\n0:03–0:06 — \"Add your own ideas to any category.\"\n0:10–0:15 — \"Tap Spin for an instant monster!\"\n0:18–0:20 — \"...or share it as an image!\"\n```\n\nThat felt like the right division of labor, honestly — the AI is great at the mechanical parts (timing, syncing captions to on-screen actions, getting the technical plumbing right) and much less useful the moment \"which voice sounds right for my brand\" becomes the actual question.\n\nYou should absolutely ask to get a video generated on how to use your product. It may not be great for marketing or even an explainer video. You do get to see how someone will use your idea before hitting publish. Who knows, it may give you some insight on things to tweak or change. Ways to really make your idea even shinier.\n\nIf you want to see the actual result, both generators are live and free at [discodoodle.com](https://discodoodle.com/monster-maker.html) — no signup, just pick your categories and hit spin.\n\nWhile you're there, make a Monster and doodle it up on a post-it. Share Your [Art](https://discodoodle.com/gallery.html) in our [Doodle Gallery.](https://discodoodle.com/gallery.html) We could always use more submissions!", "url": "https://wpnews.pro/news/monster-maker-it-s-like-daily-doodle-but-with-100-percent-more-monsters", "canonical_source": "https://dev.to/plaidscientist/monster-maker-its-like-daily-doodle-but-with-100-percent-more-monsters-e7g", "published_at": "2026-09-23 14:09:00+00:00", "updated_at": "2026-09-23 14:29:13.926812+00:00", "lang": "en", "topics": ["generative-ai", "ai-tools", "ai-agents"], "entities": ["Monster Maker", "Daily Doodle", "Plaid Labs", "Claude", "Firebase"], "alternates": {"html": "https://wpnews.pro/news/monster-maker-it-s-like-daily-doodle-but-with-100-percent-more-monsters", "markdown": "https://wpnews.pro/news/monster-maker-it-s-like-daily-doodle-but-with-100-percent-more-monsters.md", "text": "https://wpnews.pro/news/monster-maker-it-s-like-daily-doodle-but-with-100-percent-more-monsters.txt", "jsonld": "https://wpnews.pro/news/monster-maker-it-s-like-daily-doodle-but-with-100-percent-more-monsters.jsonld"}}