An AI-powered interactive storytelling app for kids that creates personalized adventures using GPT-4o-mini and DALL-E 2. Children follow the Hero's Journey through 12 magical story beats with beautiful watercolor illustrations, making choices that shape their unique adventure.
๐ Live Demo - Try it now!
- ๐ค AI-Powered Stories: Uses GPT-4o-mini to generate unique, age-appropriate stories
- ๐จ Watercolor Illustrations: DALL-E 2 creates dreamy, hand-painted style images for each story beat
- ๐ Hero's Journey Structure: 12-step narrative framework for engaging storytelling
- ๐ฎ Interactive Choices: Kids make decisions that shape the story's direction with animated transitions
- ๐ Celebration Screen: Special ending with congratulations message and restart option
- ๐ค Character Wizard: Full character customization with:
- Hair color (brown, black, blonde, red, blue, pink)
- Hair style (short, long, curly, braids, ponytail)
- Outfit style (adventurer, princess, superhero, wizard, explorer)
- Favorite color influence on outfit
- ๐ฐ 5 Story Themes: Enchanted Forest, Space Adventure, Underwater Kingdom, Dinosaur Land, Fairy Tale Castle
- ๐ Trilingual Support: English, Thai (เธ เธฒเธฉเธฒเนเธเธข), and Singlish (Singapore English)
- ๐ PDF Export: Download completed stories as beautifully formatted PDF books
- ๐ Text-to-Speech: Listen to story narration (SpeakButton component)
- ๐ฑ Responsive Design: Works beautifully on mobile, tablet, and desktop
- ๐พ Progress Persistence: LocalStorage saves story history
- ๐ Shareable Links: Preload name, gender, language, theme via URL parameters
- โ๏ธ Configurable: Toggle image generation on/off to manage costs
- ๐งช Test Coverage: Vitest + React Testing Library for component testing
- Node.js 20+
- OpenAI API key with access to GPT-4o-mini and DALL-E 2
- Clone the repository:
git clone https://github.com/yourusername/story-ai.git
cd story-ai- Install dependencies:
pnpm install- Create a
.envfile in the root directory:
OPENAI_API_KEY=sk-your-api-key-here
ENABLE_IMAGE_GENERATION=true # Set to false to disable image generation- Run the development server:
pnpm run dev- Open http://localhost:3000 in your browser
- Framework: Next.js 16.1.1 (App Router)
- UI Library: React 19.2.3
- Language: TypeScript 5.x
- Styling: Tailwind CSS 4.x
- AI Models:
- GPT-4o-mini for story generation
- DALL-E 2 for image generation
- Validation: Zod for runtime type checking
- Testing: Vitest + React Testing Library
- PDF Generation: jsPDF
- Font: Geist Sans & Geist Mono
story-ai/
โโโ app/
โ โโโ components/
โ โ โโโ common/ # Reusable UI components
โ โ โ โโโ Button.tsx
โ โ โ โโโ Card.tsx
โ โ โ โโโ Input.tsx
โ โ โ โโโ LoadingSpinner.tsx
โ โ โ โโโ SpeakButton.tsx # Text-to-speech button
โ โ โโโ story/ # Story-specific components
โ โ โโโ CharacterWizard.tsx # Character customization UI
โ โ โโโ ChoiceButtons.tsx
โ โ โโโ ExportPdfButton.tsx # PDF export functionality
โ โ โโโ StartScreen.tsx # Name, gender, language, theme selection
โ โ โโโ StoryCarousel.tsx # Image carousel for story review
โ โ โโโ StoryImage.tsx
โ โ โโโ StoryScreen.tsx
โ โ โโโ StoryText.tsx
โ โ โโโ TransitionScreen.tsx # Animated choice transitions
โ โโโ hooks/
โ โ โโโ useStoryGame.ts
โ โ โโโ useLocalStorage.ts
โ โโโ api/
โ โ โโโ story/
โ โ โโโ route.ts # Story generation API endpoint
โ โโโ layout.tsx
โ โโโ page.tsx
โ โโโ globals.css
โโโ ai/
โ โโโ llm/
โ โ โโโ index.ts # LLM client
โ โ โโโ systemPrompt.ts # Hero's Journey prompt with character support
โ โโโ generateImage/
โ โ โโโ index.ts # DALL-E 2 client
โ โโโ story.ts # Story orchestration
โ โโโ story.test.ts # Story logic tests
โ โโโ types.ts # AI message types
โ โโโ ai.ts # OpenAI client
โโโ lib/
โ โโโ i18n/ # Internationalization system
โ โโโ index.ts # t() translation function
โ โโโ types.ts # TranslationKey type definitions
โ โโโ locales/ # Translation files (en, th, singlish)
โ โโโ prompts/ # AI prompt translations per language
โโโ services/
โ โโโ storyClient.ts # Story API client
โ โโโ ttsClient.ts # Text-to-speech API client
โโโ docs/
โ โโโ internal/ # Internal documentation and task tracking
โโโ types.ts # Core types (StoryBeat, CharacterCustomization, etc.)
โโโ vitest.config.ts # Vitest configuration
โโโ vitest.setup.ts # Test setup
โโโ vitest.smoke.test.ts # Smoke tests
- Character Setup: Child enters name, selects gender, language, theme, and customizes character
- LLM Call: GPT-4o-mini generates story text + choices + transitions + image prompt
- Image Generation: DALL-E 2 creates watercolor illustration with consistent character design
- Transition Animation: Selected choice triggers animated transition screen
- User Choice: Child selects from 3 story choices
- Repeat: Steps 2-5 for 12 beats (Hero's Journey)
- Celebration: Special ending screen with PDF export option
- Ordinary World (The Dream)
- Call to Adventure
- Refusal of the Call
- Meeting the Mentor
- Crossing the Threshold
- Tests, Allies, Enemies
- Approach to the Inmost Cave
- The Ordeal
- Reward (Seizing the Sword)
- The Road Back
- Resurrection
- Return with the Elixir (ending - no choices)
| Theme | English Setting | Thai Setting |
|---|---|---|
| ๐ฒ Enchanted Forest | Magical forest with talking animals, fairies | เธเนเธฒเธงเธดเนเธจเธฉเธเธตเนเธกเธตเธชเธฑเธเธงเนเธเธนเธเนเธเน เธเธฒเธเธเนเธฒเนเธเธเธต |
| ๐ Space Adventure | Outer space with planets, aliens, rockets | เธญเธงเธเธฒเธจเธเธงเนเธฒเธเนเธซเธเน เธกเธตเธเธฒเธงเนเธเธฃเธฒเธฐเธซเนเธซเธฅเธฒเธเธชเธต |
| ๐ Underwater Kingdom | Ocean with mermaids, dolphins, treasures | เนเธเนเธเนเธญเธเธกเธซเธฒเธชเธกเธธเธเธฃ เธกเธตเธเธฒเธเนเธเธทเธญเธ เธเธฐเธเธฒเธฃเธฑเธ |
| ๐ฆ Dinosaur Land | Prehistoric world with gentle dinosaurs | เนเธฅเธเธขเธธเธเธเนเธญเธเธเธฃเธฐเธงเธฑเธเธดเธจเธฒเธชเธเธฃเน เธกเธตเนเธเนเธเนเธชเธฒเธฃเน |
| ๐ฐ Fairy Tale Castle | Magical kingdom with castles, dragons | เธญเธฒเธเธฒเธเธฑเธเธฃเธกเธซเธฑเธจเธเธฃเธฃเธขเน เธกเธตเธเธฃเธฒเธชเธฒเธ เธกเธฑเธเธเธฃ |
Note: Singlish stories use predominantly English with subtle Singapore English expressions ("lah", "leh", "shiok", etc.).
# Required
OPENAI_API_KEY=sk-...
# Optional (defaults shown)
ENABLE_IMAGE_GENERATION=true # Set to false to disable images and reduce costWith Images Enabled (default):
- LLM: ~$0.03 per story (12 beats)
- Images: ~$0.24 per story (12 images ร $0.02)
- Total: ~$0.27 per story
With Images Disabled:
- LLM: ~$0.03 per story
- Images: $0.00
- Total: ~$0.03 per story (89% savings)
To disable images during development:
ENABLE_IMAGE_GENERATION=false pnpm run devPreload the start screen with custom settings using URL query parameters:
https://your-app.com/?name=Alex&gender=girl&language=singlish&theme=space_adventure
| Parameter | Values | Default |
|---|---|---|
name |
Any string (max 50 chars, HTML sanitized) | Empty |
gender |
boy, girl |
boy |
language |
en, th, singlish |
en |
theme |
enchanted_forest, space_adventure, underwater_kingdom, dinosaur_land, fairy_tale_castle |
enchanted_forest |
All parameters are optional. Invalid values are silently ignored and fall back to defaults.
pnpm run dev # Start development server
pnpm run build # Production build
pnpm run start # Start production server
pnpm run lint # Run ESLint
pnpm run test # Run Vitest in watch mode
pnpm run test:run # Run tests once
pnpm run test:coverage # Run tests with coverage reportThe project uses Vitest with React Testing Library for component testing.
# Run all tests
pnpm run test
# Run tests once (CI mode)
pnpm run test:run
# Run with coverage
pnpm run test:coverageTest Files:
ai/story.test.ts- Story orchestration logic testsapp/components/story/StoryScreen.test.tsx- StoryScreen component testsapp/components/story/StoryCarousel.test.tsx- StoryCarousel component testsapp/components/story/ExportPdfButton.test.tsx- PDF export testsvitest.smoke.test.ts- Smoke tests
The app includes performance metrics in the console:
[PERF] Starting LLM call...
[PERF] LLM completed in 2500ms
[PERF] Starting image generation...
[PERF] Image generation completed in 15000ms
[PERF] Total runStory duration: 17500ms (LLM: 2500ms, Image: 15000ms)
Generate next story beat based on history.
Request:
{
"name": "Alice",
"gender": "girl",
"language": "en",
"theme": "enchanted_forest",
"character": {
"hairColor": "blonde",
"hairStyle": "braids",
"outfitStyle": "princess",
"favoriteColor": "pink"
},
"history": [
{
"storyText": "Alice found herself in a magical garden...",
"choices": ["Explore the forest", "Follow the river", "Climb the mountain"],
"choicesWithTransition": [
{ "text": "Explore the forest", "transition": ["She walked into the woods...", "The trees sparkled..."] }
],
"imagePrompt": "A young girl with braided blonde hair...",
"imageUrl": "https://...",
"selected": "Explore the forest"
}
]
}Response:
{
"storyText": "Alice ventured into the enchanted forest...",
"choices": ["Talk to the owl", "Pick the glowing flower", "Cross the bridge"],
"choicesWithTransition": [
{ "text": "Talk to the owl", "transition": ["She approached the wise owl...", "Its eyes sparkled..."] }
],
"imagePrompt": "A young girl with braided blonde hair wearing a pink princess dress talking to a wise owl...",
"imageUrl": "https://..."
}- Push to GitHub
- Import to Vercel
- Add environment variables:
OPENAI_API_KEYENABLE_IMAGE_GENERATION
- Deploy
Build the production bundle:
pnpm run build
pnpm run startContributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.
- OpenAI for GPT-4o-mini and DALL-E 2
- Vercel for Next.js framework
- Joseph Campbell for the Hero's Journey framework
Pariyawit J - @yourtwitter
Project Link: https://github.com/yourusername/story-ai
Built with โค๏ธ using Next.js, React, and OpenAI