Skip to content

Frontend Architecture

The KanjiIQ frontend is a Flutter Web application served by Nginx. It supports offline study, automatic locale detection, and 51 UI languages.

Build Pipeline

graph LR
    S[Flutter Source] --> GL[flutter gen-l10n<br/>Generate 51 ARB files]
    GL --> B[flutter build web<br/>--release]
    B --> N[Nginx Alpine<br/>Static Serve]

The frontend is built as a multi-stage Docker image:

  1. Build stage (Ubuntu 22.04): Installs Flutter SDK, generates localizations, builds release web assets
  2. Production stage (Nginx Alpine): Serves static files with gzip, caching, and SPA routing

Key Technologies

Technology Version Purpose
Flutter Latest stable UI framework
Provider ^6.1.1 State management
GoRouter ^13.0.0 Declarative routing
sqflite ^2.3.2 Local SQLite for offline cache
connectivity_plus ^5.0.2 Network state detection
SharedPreferences ^2.2.2 Persistent key-value storage
flutter_animate ^4.5.0 UI animations

Application Structure

frontend/lib/
├── main.dart                    # App entry point, Provider setup
├── models/                      # Data models (Kanji, Vocabulary)
├── providers/                   # State management
│   └── study_provider.dart      # Flashcard session state
├── repositories/                # Data access layer
│   ├── kanji_repository.dart    # Cache-first kanji fetching
│   └── vocabulary_repository.dart
├── screens/                     # UI screens
│   ├── home_screen.dart         # Language & level selection
│   ├── study_screen.dart        # Flashcard presentation
│   └── results_screen.dart      # Session summary
├── services/                    # Business logic
│   ├── api_service.dart         # REST API client
│   ├── database_helper.dart     # Local SQLite operations
│   ├── locale_detector.dart     # Device locale detection
│   ├── locale_preferences.dart  # Language preference management
│   ├── connectivity_service.dart # Online/offline detection
│   └── sync_service.dart        # Background data synchronization
└── l10n/                        # Localization
    ├── app_en.arb               # English (template)
    ├── app_ja.arb               # Japanese
    └── ... (51 ARB files)

Offline-First Architecture

KanjiIQ works without an internet connection using a cache-first data strategy:

graph TD
    A[User requests data] --> B{Local cache<br/>available?}
    B -->|Yes| C[Return cached data]
    B -->|No| D{Online?}
    D -->|Yes| E[Fetch from API]
    D -->|No| F[Show offline message]
    E --> G[Store in SQLite]
    G --> C
    C --> H[Background sync<br/>when online]
  • SQLite stores kanji and vocabulary locally for offline access
  • ConnectivityService monitors network state changes
  • SyncService runs background synchronization when connectivity returns
  • SharedPreferences caches locale configuration for 7 days

Nginx Configuration

The Nginx server (nginx.frontend.conf) handles:

  • SPA routing: All routes fall through to index.html for Flutter's client-side routing
  • API proxying: /api/ requests are proxied to localhost:8080 (the backend container in the same pod)
  • Gzip compression: Enabled for text, CSS, JS, JSON, and SVG
  • Cache control: 1-year cache for versioned static assets, no-cache for index.html
  • Security headers: X-Frame-Options, X-Content-Type-Options, Referrer-Policy
  • Health check: /health endpoint for Kubernetes probes