We’ve all seen it: the "AI-powered" app that promises the world but feels like it’s held together by duct tape and hope. When I set out to build Ancre, a French learning application, my goal wasn't just to slap an AI "magic wand" onto a flashcard app. I wanted to build a precise tool that solved a real problem without sacrificing data integrity.
Here is how I architected the AI autofill feature, the technical decisions behind it, and what I actually learned when things inevitably broke.
1. Why This Feature? The Problem with Flashcards
If you’ve ever tried to learn a language, you know the absolute worst part is data entry. Creating flashcards manually is tedious. You have to look up the word, find a good context sentence, translate that sentence, and format it perfectly. It’s a massive friction point that kills momentum.
I built the AI Auto-fill feature to act as an intelligent assistant. You type in a French word, click a button, and the AI instantly generates the English translation, a natural-sounding French example sentence, and its English equivalent. It solves the "blank page" problem, letting the user focus on actually studying the language rather than doing data entry.
2. Technical Decisions: Under the Hood
The Provider and Model
I chose Google Generative AI (Gemini) for this feature. When it comes to natural language processing and translation, Gemini is exceptionally fast and incredibly nuanced with context, which is vital for generating natural-sounding French sentences, not just robotic direct translations.
The Prompt Structure
LLMs are notoriously eager to please. If I typed a keyboard smash like "asdfg", a naive prompt would try to invent a French word for it. To fix this, I structured my prompt not just as a translator, but as a strict validator. I enforced a JSON-only response and added a rule: If the input is not a real French word, return a NOT_FRENCH flag. This allowed me to handle errors gracefully in the UI instead of saving garbage data.
Text Streaming?
I explicitly chose not to stream the AI response. While streaming looks cool for chatbots, it’s a terrible UX for form inputs. Watching a JSON object slowly populate characters into input fields looks glitchy and can cause React state nightmares. Instead, I opted for a single, fast API payload. The user sees a clean "shimmer" loading state, and then the entire form populates perfectly at once.
3. The Integration Reality Check
My actual build process was a humbling reminder that "making an API call" is only 10% of the work. The real work is integrating it cleanly into the application lifecycle.
Initially, my approach was too trusting. The code worked perfectly on my local machine, but the integration hit two major snags:
- React State Ghosting: Because the form fields were tied to the component's state, searching for a new word wouldn't always clear the old word's data. I had to fundamentally restructure how I handled the React lifecycle, ensuring the state completely reset the moment the "Auto-fill" button was clicked to prevent stale data.
-
The Deployment "Palava": Moving from local development (using Vite) to production (on Vercel) broke the API entirely. I had to learn how to manage environment variables the hard way. I navigated 404 routing errors for my Single Page Application, wrestled with Vite crashing because an alias was accidentally scanning my
vercel.jsonconfig file, and realized that Vite’s default dev server doesn’t know how to run serverless backend functions natively. I had to switch to using the Vercel CLI locally to finally get the frontend and backend talking.
4. What I’d Do Differently
Hindsight is key. If I were to rebuild Ancre today, the biggest change I’d make has nothing to do with the AI itself, but rather where the data lives.
Right now, Ancre relies heavily on the browser's localStorage. While that made it incredibly fast to prototype, it's fragile. The UI is polished, but treating the browser as a database feels like a ticking time bomb for data loss.
If I were to scale this app, my immediate next step would be to build a proper data layer. I would replace localStorage with a robust relational database like PostgreSQL, managed through an ORM, and build out a secure backend API to handle user accounts and cross-device syncing.
The frontend is just the interface. This project proved that the architecture, the data validation, and the infrastructure pipelines are what actually make software resilient.
Check out the live app here: https://ancre-fr.vercel.app/
Top comments (0)