-
-
Your Characters gallery — every saved character with its real portrait, one click to reuse.
-
Editable story plan — the parent reviews and approves every page before any art is generated.
-
A real page-turning Book Reader — cover, one page at a time, Prev/Next, not a scroll of images.
-
Real Gemini-generated cover — "Mira and the Glowing Forest," narration burned right into the art.
Inspiration
Every parent has told their kid a bedtime story where they're the hero. AI comic/story generators exist for this now -- but they're one-shot: describe a theme, get a comic, forget it ever happened. They don't remember the character next session. They can't tell "he lost his first tooth today" apart from "make him an astronaut." They never check whether the character still looks the same on page 4 as on page 1. And if a parent says "make page 4 funnier," most of them quietly regenerate the whole book, hoping you won't notice the other five pages changed too.
We wanted to build something a parent would actually keep using -- not a generator you visit once, but a companion that remembers a family's ongoing "Story Universe": the characters, the places, the lessons that landed, the real moments that inspired a story in the first place.
What it does
DadHero is an agent that turns a child's real life -- a worry, a milestone, or a memory -- into a personalized illustrated storybook where a family member is the hero. A parent describes an idea, or something that actually happened ("she's nervous about starting school," "he lost his first tooth today"), and the agent:
- Maps that into a story objective (never states the lesson out loud -- shows it happening in the plot instead).
- Locks a consistent character from a text description, a photo of an adult family member, or the child's own drawing -- never a photo of the child, enforced in the tool layer itself, not a prompt.
- Plans the whole book as a real, recorded, parent-editable checkpoint before any art is generated.
- Draws a cover first, then every page chained off it for visual consistency, narration burned directly into the artwork like a real printed comic panel.
- Independently verifies each page against the character's reference image, and audits the whole story for continuity, before presenting it.
- Remembers the character, the goal, and whether it actually helped -- across sessions, so a later report ("she walked in by herself today!") gets matched back to the exact story that targeted it.
And critically: when a parent asks for a change -- "make page 4 funnier and add Grandpa" -- the agent figures out which page(s) are actually affected and regenerates only those, re-running just that page's safety and consistency checks. We didn't just build this and hope; we verified it live, by checking the actual image files' modification times before and after the request. The untouched pages never changed. Only the flagged one did.
Beyond the core loop, DadHero is built to feel like a parent's own studio, not a form you fill out once:
- Your Characters -- every character ever made, with its real generated portrait, one click to reuse it in a new book.
- Read Book → -- a real page-turning book reader (cover, one page at a time, Prev/Next), not a scroll of images.
- Make tonight's story -- a dedicated "What happened today?" box that turns something real into tonight's bedtime story in one click.
- 9 real art styles (watercolor, comic book, claymation, pixel art, paper-cutout, and more) that apply to every page -- including a child's own sketch, drawn right in the browser and turned into finished art in the chosen style.
How we built it
The core is a single Strands Agents Agent
(Bedrock primary, Anthropic/Gemini fallback for the text model) driving
15 purpose-built @tool functions -- the agent decides which to call
and in what order, not a single giant prompt reciting a script:
save_character/save_character_from_photo/get_saved_characterlock a Character Bible once, reused verbatim across every page.create_story_planrecords the page-by-page outline as a real checkpoint before any image API cost is spent -- shown to the parent as an editable plan they approve (or edit) before generation starts.generate_page_imagedraws the cover and every page with Gemini ("Nano Banana"), chaining each image off the cover for consistency, with narration rendered directly into the artwork.check_visual_consistencyis a second, independent Gemini vision call judging each new page against the reference portrait -- regenerating just that page if it drifted.check_story_factandaudit_story_continuitycatch contradictions (a red backpack on page 1, blue on page 4) both as they happen and in a final cross-page pass.check_page_safetyscreens every page's narration text before it's shown.record_family_memory/record_progress/record_finished_storybuild the persistent Story Universe a later conversation reads back.
The UI is Streamlit, with a live "Workshop" panel translating each raw tool call into plain language as it happens ("Recording a real family memory," "Illustrating page 4," "Checking visual consistency") instead of showing raw JSON.
For the studio features, the Story Library keeps each book as a
structured list of pages -- built directly from generate_page_image's
own tool calls (real page slugs and image paths), not scraped from the
reply text. That's also what makes revision provably surgical: if a
page's slug already belongs to an existing story, it's a revision, and
only that page's image is replaced in place; every other page (and the
reader's current position) is untouched.
Beyond the hackathon surface, we also built and live-verified a
multi-tenant version of the same agent behind a real REST API: FastAPI,
Supabase Postgres with row-level security, JWT auth, and a React
frontend -- the exact same dadhero/ tools, unchanged.
Challenges we ran into
- Cross-turn state, not just cross-message. The plan-approval pause
(parent reviews the plan, THEN generation happens) splits related tool
calls across separate agent turns. Our first attempt at backfilling a
character's portrait after generation searched "this turn's" tool
calls and silently never fired, because the character was selected in
an earlier turn. Worse, once we searched the full conversation trace
instead, we found Strands' own
SlidingWindowConversationManager(window size 40) had already trimmed that earlier turn's tool calls out ofagent.messagesby the time a multi-page book finished generating -- so even the full trace couldn't recover it. The fix was to stop trying to re-derive state from history at all, and persist the few facts we actually need (the active character, the approved plan's title) directly in session state at the moment they're known. - A subtle Strands serialization behavior. A tool's plain-dict return
gets JSON-serialized into the
ToolResultautomatically -- unless the dict already has both astatusand acontentkey, in which case Strands passes it through unchanged.create_story_plan's return has both (for a friendly Workshop message), which meant our first attempt at reading itstitle/page_countback out of the tool result silently failed. We had to read those fields from the tool call's input instead, which is always reliable.json {"status": "success", "content": [{"text": "..."}], "title": "...", "page_count": 6} - A dependency that broke without warning.
streamlit-drawable-canvas(the in-browser sketch canvas) turned out to fail on import against the current Streamlit release -- a real, reproduced exception raised inside the package's own code, not something we assumed. Since neither package was version-pinned, a routine reinstall could have taken the entire app down at import time, not just the drawing feature. We wrapped the import defensively so the app degrades to "upload a photo instead" rather than crashing outright. - Sourcing real reference material honestly. For the comic-book art style, we wanted actual vintage comic panel/caption conventions as a visual reference, not just a text description. Rather than scrape images of uncertain provenance, we individually verified three specific Golden Age comic pages on Wikimedia Commons, each with its own stated public-domain rationale, before using them.
Accomplishments that we're proud of
- The revision boundary is provable, not just claimed: we checked file modification times before and after a "change page 4" request and confirmed the other pages' files genuinely never touched disk.
- A real, non-negotiable child-safety rule -- a photo of a child is never used for that child's own likeness -- enforced where a tool itself refuses the wrong relationship, not just requested politely in a system prompt.
- The same agent and tools run, live-verified end to end, behind both a local Streamlit demo and a real multi-tenant Supabase-backed REST API with row-level security tested between two actual users.
- 40 passing tests covering everything that doesn't need a live model call, kept green through every change in this build.
What we learned
That "agentic" is worth proving, not asserting -- the moment that actually convinced us this was more than a fancy wrapper was watching a single page regenerate while five others stayed byte-for-byte untouched. And that a lot of what makes something feel like a real product instead of a hackathon demo isn't a new AI capability at all -- it's a Characters gallery, a book you can reopen, a "what happened today" box that respects that the parent already said yes by clicking it.
What's next
PDF/image-bundle export for a finished book, a long-form 13-16 page default for older kids, deploying the already-verified Supabase backend
- React frontend as a real hosted product, and extending the vintage comic-reference conditioning to more of the nine art styles as more verified public-domain source material is curated for each.
Built With
- agents
- amazon
- anthropic
- bedrock
- claude
- fastapi
- gemini
- pillow
- postgresql
- pytest
- python
- react
- rest
- strands
- streamlit
- supabase
- typescript
- vite
Log in or sign up for Devpost to join the conversation.