This document is based strictly on the provided project plan and expands it into:
- Complete user flow (end‑to‑end)
- Gap / missing steps analysis (functional + technical)
- Completed technical implementation doc, adjusted for Netlify static export + 100% client‑side execution
Entry
- User opens app URL
- App shell loads instantly (static assets)
Initialization
-
App bootstraps (
main.ts) -
Pinia store initializes
-
initDataset()is called-
Fetch
/data/version.json -
Compare with
localStorage.data_version -
If mismatch or missing:
- Fetch
/data/lessons.lz.json - Decompress in browser
- Store full dataset in IndexedDB
- Fetch
-
Result
- Dataset available offline
- User state initialized (empty SRS, settings default)
Home Screen
-
Shows:
- Welcome message
- Total lessons
- Review due count (0 initially)
- CTA: “Start Learning”
-
User navigates to Lessons List (
/lessons) -
App:
- Loads lesson metadata only (id, title, tags)
- Does NOT load lesson content yet
-
User selects a lesson
-
User opens
/lesson/:id -
App:
- Pulls lesson data from IndexedDB
- Renders vocabulary / grammar / examples
-
User:
- Reads content
- Optionally marks items as favorite
- Optionally adds notes
-
User taps Add to Review (implicit or automatic)
Result
- Lesson cards are added to SRS queue
- Initial SRS state created per card
-
User opens
/review -
App queries SRS store:
- Filters cards where
due <= now
- Filters cards where
-
Review loop:
- Show prompt (JP → EN or EN → JP)
- User answers
- User self‑grades (0–5)
scheduleCard()updates interval, ease, due
-
Card saved to IndexedDB
-
Loop continues until queue empty
Exit State
- Review complete
- Home screen updates review count
-
App loads
-
Dataset version matches
-
No network fetch needed
-
Home screen shows:
- Due reviews
- Continue lesson CTA
Export
-
User opens
/settings -
Clicks Export
-
App:
- Serializes user data
- Downloads JSON or Base64 file
Import
- User uploads file
- App validates schema + version
- Merge or overwrite confirmation
- Save to IndexedDB
Missing:
- Where
initDataset()is called - App‑level loading / blocking UI
Required:
- Global
AppInitializerlogic - Loading + error fallback states
Missing:
- Lesson JSON schema
- Card schema
- SRS state schema
Risk:
- Import/export breakage
- Version migration impossible
You have:
scheduleCard()
Missing:
- Function to build due queue
- Sorting logic (due asc, priority)
Missing:
- How lesson content becomes flashcards
- Card ID strategy (stable IDs)
Dataset versioning exists, but:
- User progress migration not defined
- Breaking dataset changes will corrupt state
- No empty state handling
- No error recovery UI (fetch fail, corrupt DB)
- No first‑time onboarding hints
- No progress indicators per lesson
- No Netlify config
- No SPA fallback (
_redirects) - No build output config
main.ts
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
await useLessonStore().load();
await useUserStore().load();
app.use(router);
app.mount('#app');Add global loading state before mount.
Lesson {
id: string
title: string
vocab: Card[]
grammar: Card[]
}
Card {
id: string // stable hash
front: string
back: string
type: 'vocab' | 'grammar'
}
SRSCard extends Card {
interval: number
ease: number
due: number
}function getDueCards(cards) {
return cards
.filter(c => c.due <= Date.now())
.sort((a, b) => a.due - b.due);
}function initCard(card) {
return {
...card,
interval: 1,
ease: 2.5,
due: Date.now()
};
}Call when first encountered.
db.createObjectStore('dataset');
db.createObjectStore('srs');
db.createObjectStore('notes');
db.createObjectStore('settings');function validateImport(data) {
return data.version && data.srs && data.settings;
}Add version compatibility checks.
vite.config.ts
export default defineConfig({
base: '/',
build: { outDir: 'dist' }
});public/_redirects
/* /index.html 200
- Dataset stored in IndexedDB
- App shell cached via PWA
- No server calls after first load
- All logic runs in browser
- Solid local‑first architecture
- Correct dataset versioning approach
- Netlify‑compatible static design
- App bootstrap orchestration
- Schema definitions
- Lesson → card mapping logic
- SRS queue builder
- Migration + import validation