How sendajapan/jlpt works
1. Repository shape
This is a two-client system in one repo: a Laravel 13 backend in the root and a native Android app in /android. The backend serves both a browser-based admin panel and a versioned REST API consumed by the mobile client.
2. Core domain
The product is a JLPT vocabulary learning platform. The domain centers on categories, subcategories, vocabulary words, quizzes, user progress, favorites, unlocks, coins, avatars, reads, and profile/authentication flows.
3. Backend application boundary
Laravel splits the server into two major entry points:
- Admin web UI under resources/views/admin and app/Http/Controllers/Admin
- Mobile API under app/Http/Controllers/Api/V1
These are separate surfaces with different auth models and response styles, but they share the same domain models and services.
4. API layer for mobile
The /api/v1/ controllers expose JSON endpoints for auth, categories, subcategories, vocabulary, quiz, favorites, profile, coins, and unlocks. Requests are validated with dedicated app/Http/Requests/Api/* classes, and responses are shaped with app/Http/Resources/* plus DTOs in app/Http/Resources and app/Http/Controllers/Api/V1 dependencies.
5. Business logic layer
Most nontrivial logic is centralized in app/Services. This includes authentication, OTP, social login, avatar management, coin handling, category/subcategory/vocabulary management, favorites, word reads, and unlock logic. Controllers are thin orchestration points; services are the main business boundary.
6. Persistence and data model
Eloquent models in app/Models map to the vocabulary and user tables defined in database/migrations. The schema includes both standard Laravel auth tables and platform-specific tables such as app_users, vocab_categories, vocab_subcategories, vocab_words, avatars, coin_transactions, app_user_otps, app_user_word_reads, and unlock tables. Seeders and backups indicate the database is a first-class operational dependency.
7. Auth split by client
Authentication is intentionally bifurcated:
- Admin web uses Laravel session auth and the built-in auth controllers/views.
- Android/mobile uses Laravel Sanctum token auth.
The API also supports guest login, OTP verification, email verification, password reset, and social login. AuthInterceptor on Android attaches the token to API calls.
8. Async and automation
Audio generation is handled as a background/automation concern rather than inline request work. The backend includes a queue-backed job (GenerateNextVocabAudioJob), console commands for seeding and ticking audio generation, and an AudioAutomationService. This suggests audio assets are processed asynchronously and tracked separately from the main CRUD flows.
9. Admin panel
The admin UI is a traditional server-rendered Laravel app using Blade, Alpine.js, Tailwind CSS v4, and Vite. It manages content operations for categories, subcategories, words, voices, avatars, app users, and audio automation. The admin surface is for content/operator workflows, not the mobile learning experience.
10. Android app structure
The Android client is organized in a classic MVVM-style split:
- ui/activities, ui/fragments, ui/adapters, ui/views
- viewmodels
- data/repo, data/networking, data/local
- models for domain objects
User-facing flows are split across onboarding, auth, dashboard/home, vocabulary browsing, quiz, progress, favorites, and profile screens.
11. Android data flow
The mobile app pulls remote data through Retrofit (ApiService, RetrofitClient) and a request interceptor for auth headers. It persists token state in TokenStore and caches structured content in a local database (AppDatabase, DAOs, entities, relations). Repositories sit between ViewModels and the data sources, so UI reads are mediated through a remote/local abstraction rather than direct API calls.
12. Mobile navigation and UI composition
The Android UI is built from multiple activities and fragments, with separate screens for auth, onboarding, category/subcategory browsing, word details, quiz, and profile setup. Adapters back list/grid views for categories, subcategories, words, avatars, and progress. Bottom sheets and dialogs handle focused interactions like avatar picking, DOB selection, and unlock prompts.
13. Shared content model between backend and app
The backend exposes vocabulary content and user state; the Android app mirrors that with DTOs and local models. This indicates a server-authoritative content model with client-side caching for speed and offline resilience, especially for category trees, word lists, and user progress/favorites.
14. Operational/tooling boundaries
Swagger/L5-Swagger documents the API, Pest covers tests, and the Laravel app uses database-backed cache/queue/session drivers. MySQL is the primary persistence layer, while storage/public and related assets support media such as avatars and generated audio.
15. How to draw the architecture
A useful diagram should show:
- Android client → Sanctum-protected REST API
- Admin browser → Laravel session-auth web app
- API/web controllers → service layer → Eloquent models/database
- Async jobs/commands → queue/database + audio automation/storage
- Android ViewModels → repositories → Retrofit/local DB/token store
The important boundary is that the backend owns business rules and persistence, while the Android app owns presentation, local caching, and token-managed API access.
Main entry points: V1 Mobile API · Services Services · Admin Admin controllers · repo Repositories
Components 19
Laravel backend
Server-side web, API, domain, and async automation.
- Admin web · Blade-based operator surface for managing content, avatars, users, and automation.
resources/views/admin - Admin controllers · Session-authenticated controllers for admin workflows.
app/Http/Controllers/Admin - Mobile API · Versioned REST controllers for auth, vocab content, quiz, favorites, profile, coins, and unlocks.
app/Http/Controllers/Api/V1 - API auth · Guest, login, register, OTP, password reset, verification, logout, and social login flows.
app/Http/Controllers/Api/V1/Auth - Services · Central business boundary for auth, OTP, social login, content, favorites, coins, reads, and unlocks.
app/Services - Eloquent models · Server domain objects for users, vocab, avatars, coins, unlocks, reads, and audio tracking.
app/Models - Requests · Dedicated request validation for admin and API inputs.
app/Http/Requests - API resources · JSON resource and DTO layer for mobile responses.
app/Http/Resources - Audio job · Queue-backed vocabulary audio generation work.
app/Jobs/GenerateNextVocabAudioJob.php - Console jobs · CLI automation for seeding unlocks and ticking audio generation.
app/Console/Commands - Routes · Web, API, auth, and console route definitions.
routes
Android client
Native app with MVVM UI, repositories, and local cache.
- Android app · Mobile learning client for onboarding, vocab browsing, quiz, and profile flows.
android/app/src/main/java/com/scholarlyapps/pathlingo - Screens · Activities, fragments, adapters, dialogs, and bottom sheets composing the app experience.
android/app/src/main/java/com/scholarlyapps/pathlingo/ui - ViewModels · State holders coordinating UI flows with repositories.
android/app/src/main/java/com/scholarlyapps/pathlingo/viewmodels - Repositories · Repository layer mediating between ViewModels, remote API, and local cache.
android/app/src/main/java/com/scholarlyapps/pathlingo/data/repo - Network stack · Retrofit service, client setup, and auth interceptor for Sanctum-protected API calls.
android/app/src/main/java/com/scholarlyapps/pathlingo/data/networking - Local store · Token storage plus Room database, DAOs, entities, and relations for offline-friendly content caching.
android/app/src/main/java/com/scholarlyapps/pathlingo/data/local
Connections 22
- Android app → Screens: renders · The app is composed from activities, fragments, adapters, and dialogs.
- Screens → ViewModels: binds to · Screens delegate state and actions to ViewModels.
- ViewModels → Repositories: uses · ViewModels coordinate data through repositories.
- Repositories → Network stack: fetches · Repositories call the Retrofit API layer for remote data.
- Repositories → Local store: caches · Repositories persist tokens and structured content locally.
- Network stack → Mobile API: calls · The Android client consumes the versioned REST API.
- Network stack → API auth: auth flow · Login and token-bearing auth requests go through API auth endpoints.
- Mobile API → Services: orchestrates · Controllers stay thin and delegate business rules to services.
- API auth → Services: orchestrates · Authentication endpoints use dedicated auth and OTP services.
- Admin controllers → Services: orchestrates · Admin controllers use the same service layer for content operations.
- Services → Eloquent models: mutates · Services implement the domain logic over Eloquent models.
- Services → Database: persists · Domain changes are stored in the database schema managed by migrations.
- Requests → Mobile API: validates · Request objects protect API inputs.
- Requests → Admin controllers: validates · Request objects protect admin form inputs.
- Mobile API → API resources: formats · API responses are shaped for the mobile client via resources and DTOs.
- Admin web → Admin controllers: views · Blade templates back the admin controller workflows.
- Audio job → Services: runs logic · Queued audio generation relies on the audio automation service.
- Console jobs → Audio job: ticks · Console commands drive background audio processing and seeding tasks.
- Console jobs → Database: operates on · Automation commands seed and update persisted platform state.
- API docs → Mobile API: documents · OpenAPI docs describe the mobile REST surface.
- Routes → Mobile API: dispatches · API routes bind mobile endpoints to controllers.
- Routes → Admin controllers: dispatches · Web routes bind admin pages to controllers.