Skip to content
Go back

Haechi v0.2 — Authentication, Server Database, and Offline Sync

Published:  at  09:00 AM
This post was automatically translated from Korean using AI (source updated 2026-04-01). Read the original →

Haechi is an app for studying Korean grammar with the FSRS-5 spaced repetition algorithm. Browse grammar pages, create flashcard sets, and review with scientifically-driven scheduling. It has gone through three major releases over the past few weeks.

v0.1.0 — Visual Integration

The first challenge was making the app look like it was made by the same person as the blog. Previously it was hastily styled with 450 lines of vanilla CSS.

Dark-first design. Dark mode is set as the default. It saves to localStorage, respects system preferences, and doesn’t flash the wrong theme on load. Light mode is available via toggle.

Dual typography system. Geist Mono for UI chrome (navigation, labels, buttons, stats), and Pretendard Variable for Korean content. Two identities coexisting within one system.

Dual accent colors. Blue (#7eb8f0) for grammar browsing mode, purple (#c4a7e7) for review sessions. Automatically switches via CSS variable scoping on the review page.

Dashboard homepage. A stats grid showing cards due for review, estimated time remaining, session count, and next review time — all in real time. Shows an onboarding message for new users, and an “all done” state when there’s nothing left to review.

Tailwind CSS 4. Replaced 450 lines of vanilla CSS with the same design token system as the blog. Built a translucent surface system using rgba() backgrounds and borders via the @tailwindcss/vite plugin.

After the visual integration, actually using the app revealed what was missing.

960px wide layout. Expanded the homepage and review pages to 960px, while the grammar detail page keeps a 768px reading column. Progress bar and counter span full width; cards are centered at 480px.

Grammar search and filters. Search by Korean title or English definition. Level filters for beginner/intermediate/advanced (shown when there are 5 or more grammar items). Learning status badges are visible directly from the homepage.

Consistent dashboard. Whether you’re a new user, actively studying, or in the “all done” state, you always see the same four-stat grid and review button.

v0.2.0 — Authentication and Server Database

The biggest change. The limitations of browser local storage alone were clear. Study on your phone, switch to your laptop — no data. Review on the subway, go offline — reviews could be lost.

Authentication

Email/password authentication with better-auth. 30-day sessions, middleware-based auth guards. Every page except public routes (login, signup, API health check) requires authentication.

The login/signup pages follow the existing dark editorial design. An auth gate was added to the Study button so unauthenticated users see an inline signup prompt instead of being redirected.

Server-Side Data Persistence

AstroDB (Turso/libSQL) for the server-side database. Schema: User, Session, Account (better-auth managed tables) + Card, ReviewLog, ReviewStats (app data).

Five API endpoints:

DataProvider Abstraction

This was the most important architectural decision. Three implementations:

The appropriate provider is returned based on whether a session cookie is present. All components (ReviewSession, StudyButton, DashboardStats, ExportImport) operate through the DataProvider, so direct Dexie imports are gone.

Offline-First Sync

Not losing data while reviewing on the subway was a core requirement.

SyncingDataProvider automatically attempts to sync on app initialization, when online/offline events fire, and when page visibility changes. Last-write-wins strategy with UUID deduplication. Toast notifications provide sync status feedback.

The review log stores state_before/state_after FSRS state snapshots. Currently last-write-wins, but the foundation is in place to refine conflict resolution strategies in the future.

Other Changes

Test Infrastructure

For E2E testing, a script was written to spin up a temporary Turso database, run the tests, and clean up afterward. A single command automates the entire flow: create DB → start server → run Playwright tests → delete DB.

Currently 42 unit tests (Dexie operations, FSRS scheduling) and 33 E2E tests (auth flows, grammar pages, review sessions, export/import) are passing.

Why It Was Built This Way

Haechi is intentionally minimal. It sits at the opposite end of the spectrum from Duolingo. No gamification, no decoration. The interface is built from typography and depth alone.

There’s a reason for this approach. Late at night when studying, flashy animations and notifications are a distraction. What’s needed is a calm, focused, trustworthy tool. One where the data is yours, it works offline, and you can pick up where you left off across devices.

Choosing FSRS-5 comes from the same mindset. It’s scientifically more accurate than Anki’s SM-2 and tracks a learner’s memory state with greater precision. When the algorithm decides when to review, you just sit down and study.

The next step is expanding the grammar content. There are currently only two grammar entries (~아/어서, ~으면서). The infrastructure is ready — now it’s time to fill in the content.


Share this post on:

Previous Post
Lower Body (PPL W6D3)
Next Post
Pull Day (PPL W6D2)