← All posts
PROJECT Language Learning · AI · Web Development

Teaching AI to write me a new story every day

How I built Daily Story—fresh reading practice in eight languages, calibrated to your level—and what it taught me about prompt engineering.

stack Node.js · Express · Claude AI status live
dailystory.page
Daily Story interface preview

Building Language Immersion Without a Plane Ticket

Language immersion doesn't require a plane ticket. Daily Story delivers fresh, AI-generated stories in eight languages across four skill levels—beginner to advanced. Each story comes with comprehension quizzes to reinforce what you've learned and track your progress.

Whether you're brushing up on Spanish before a trip or diving deep into Japanese grammar, Daily Story gives you something new to read every single day, perfectly calibrated to challenge you without overwhelming you.

dailystory.page
Daily Story main interface
dailystory.page
Japanese story example
dailystory.page
Comprehension quiz questions

The Problem with Finding Content at Your Level

One of the best ways to learn a language is to immerse yourself in it through reading. The problem? Finding content that matches your exact skill level is difficult. Too easy and you're not learning; too hard and you're frustrated.

I found myself constantly asking ChatGPT to generate short stories at my skill level for language practice. It worked, but it was tedious to do manually every day. I realized this could be automated into a daily habit-building tool that others could benefit from too.

Teaching AI to Curate, Not Just Generate

Building Daily Story taught me that working with AI is less about the code and more about the conversation. The technical infrastructure was straightforward, but getting consistent, quality output required a completely different skill set.

The real challenge wasn't the architecture—it was prompt engineering.

After a few days of testing, I noticed the AI kept generating eerily similar stories. Without memory of what it had created before, the model naturally gravitated toward the same narrative patterns. The solution? A curated library of about 100 themes per skill level that the app randomly selects from before each generation.

themes.jsJavaScript
// Daily theme selection prevents repetitive stories
const themes = {
  a1: [
    "introducing yourself and saying hello",
    "saying where you are from",
    "ordering coffee or tea"
  ],
  a2: [
    "planning a weekend trip with friends",
    "discussing your favorite restaurant",
    "discussing why you like your job"
  ],
  b1: [
    "talking about changing careers or jobs",
    "explaining how you balance work and personal life",
    "discussing a time you had a disagreement with someone"
  ],
  b2: [
    "debating the ethics of human enhancement technologies",
    "analyzing the role of traditional media versus independent journalism",
    "evaluating the long-term consequences of the gig economy"
  ]
};

This wasn't just about variety for variety's sake. A theme like "navigating cultural misunderstandings" works beautifully for intermediate learners but falls flat for beginners who need simpler vocabulary. Each proficiency level needed its own theme collection, carefully chosen to match both linguistic complexity and conceptual accessibility.

Another major shift came from rethinking the story format itself. Initially, all stories were fables—traditional tales with morals and lessons. But fables proved too challenging for absolute beginners and too simplistic for upper-intermediate readers. More importantly, fables rely heavily on past tense narration, which doesn't reflect the language learners actually use in real conversations. I pivoted to a conversation format between two or more people. This made stories immediately more relevant across all skill levels, focusing on the present-tense dialogue and natural speech patterns that learners encounter in daily life.

Seeing the Progression

dailystory.page
English A1 beginner story

A1 Beginner: Simple vocabulary and present tense, designed for beginners starting their language journey.

Key Features

Language learning apps often promise too much. Daily Story focuses on doing three things really well:

Fresh Content Daily

Every day brings a new story perfectly calibrated to your current proficiency—challenging enough to push your skills forward, accessible enough to keep you engaged.

Active Comprehension

Three targeted questions after each story transform passive reading into active learning, helping you retain vocabulary and internalize grammar patterns.

8 Languages, 4 Levels

Find your perfect match across four proficiency tiers (A1, A2, B1, B2) in English, Spanish, French, German, Italian, Portuguese, Chinese, and Japanese.

Architecture Designed for Cost Efficiency

The architecture is intentionally straightforward. Built with Node.js and Express, the app runs on a simple cron schedule that handles AI content generation efficiently and cost-effectively.

The app runs on two cron schedules. At midnight, it submits a batch request to the Claude API for 32 different stories—8 languages at 4 skill levels each. Batch requests process at half price but can take up to 24 hours. At 6 PM, the app retrieves any completed stories and caches them, ensuring they're ready with no delay when midnight rolls around. If stories aren't ready by 6 PM, they're picked up during the next midnight cycle when submitting the following day's request.

By retrieving stories at 6 PM, they're ready the moment users need them at midnight—eliminating any lag while still taking advantage of half-price batch processing.

Cron Job Runs

Daily story generation check

Runs at 12 AM and 6 PM daily

Check Today's Stories

Already generated?

Batch in progress?

Cron Job Outcomes

Stories Ready

Save to filesystem

/stories folder

Batch Requested

Submit batch request

32 stories total

Batch Pending

Return status

"Batches in progress"

Fig. 1 — Cron job decides whether to save stories, submit a batch, or report an in-progress batch

Running on Google Cloud Run means I only pay for active compute time. No database overhead, no complex state management—just reliable, daily language practice delivered through a clean API.

console.cloud.google.com
Cloud Scheduler cron jobs

Automated cron jobs scheduled for midnight (batch submission) and 6 PM (story retrieval)

Tech Stack

Node.js Express Claude AI

Lessons in Prompt Engineering

This project transformed how I think about working with AI. I expected the hard part to be building the infrastructure—cron jobs, API integration, deployment. But the real challenge was prompting the large language model to consistently generate stories that felt authentic and educational across eight different languages.

I spent days iterating on prompts, discovering that small changes in phrasing could mean the difference between a compelling story and something that read like a textbook exercise. Quality matters more than quantity—each story needs to be genuinely engaging and leave learners feeling measurably better at their target language.

The trickiest part? Getting consistent JSON responses across all languages. The LLM would sometimes fail to properly escape characters or add characters that would break the JSON parsing—especially problematic when working with eight different languages, each with unique character sets and punctuation. After countless malformed responses, I discovered structured output tools specifically designed for this purpose. Using these tools ensures the LLM generates properly formatted JSON every single time, regardless of language. What started as my biggest pain point became a solved problem once I learned the right approach.

Try Daily Story

Start improving your language skills today.

Let's talk.

Open to new roles, projects, or a chat about code and flying.