Panduan ini menjelaskan cara menyiapkan, menjalankan, menguji, dan mengembangkan backend Nihongo Master pada mesin lokal.
Backend menggunakan:
- Go standard library
net/http - Go module bernama
nihongo-master-backend - GORM dan MariaDB untuk persistence akun, billing, progress, dan kamus; sesi/attempt aktif masih di memori
- Setup database MariaDB
- JSON REST API
- OpenAPI 3.1 contract pada
backend/openapi.yaml
| Requirement | Version |
|---|---|
| Minimum | Go 1.22 |
| Tested in this repository | Go 1.26.5 windows/amd64 |
| Recommendation | Versi stable terbaru yang kompatibel dengan Go 1.22+ |
Go 1.22 dibutuhkan karena router memakai pola method-aware dari http.ServeMux,
misalnya GET /v1/home dan path value seperti {lessonID}.
Periksa versi yang aktif:
go versionContoh output yang valid:
go version go1.26.5 windows/amd64
Jika versi lebih rendah dari 1.22, upgrade melalui halaman download resmi Go: https://go.dev/dl/.
- Download installer Windows dari https://go.dev/dl/.
- Jalankan installer dengan lokasi default.
- Tutup dan buka kembali PowerShell atau terminal IDE.
- Verifikasi:
go version
go env GOROOT GOPATHPastikan MariaDB aktif dan backend/.env memiliki konfigurasi DB_*.
Ikuti setup MariaDB sebelum menjalankan API.
Untuk menjelajahi kontrak endpoint, buka backend/openapi.yaml di Swagger
Editor. Kontrak ini mencakup autentikasi, Beranda, pembelajaran, ujian, paket,
profil, progress, dan achievement.
Gunakan installer resmi atau Homebrew:
brew install go
go versionGunakan paket distribusi atau archive resmi dari https://go.dev/dl/, kemudian:
go versionPastikan executable go tersedia pada PATH terminal dan IDE.
Dari root repository:
cd backend
go run ./cmd/apiOutput normal:
nihongo master API listening on http://localhost:8080
Server tetap berjalan selama terminal tersebut terbuka. Hentikan dengan
Ctrl+C.
PowerShell:
$env:PORT = '9090'
go run ./cmd/apiBash/zsh:
PORT=9090 go run ./cmd/apiEnvironment variable backend:
| Variable | Required | Default | Kegunaan |
|---|---|---|---|
PORT |
Tidak | 8080 |
Port HTTP server |
GOOGLE_CLIENT_ID |
Hanya Google login | - | Web OAuth Client ID untuk validasi audience |
Health endpoint tidak membutuhkan autentikasi.
PowerShell:
Invoke-RestMethod http://localhost:8080/healthzcurl:
curl http://localhost:8080/healthzContoh response:
{
"status": "ok",
"time": "2026-07-22T15:00:00Z"
}Login development account dan ambil bearer token:
$session = Invoke-RestMethod `
-Method Post `
-Uri http://localhost:8080/v1/auth/login `
-ContentType application/json `
-Body '{"email":"demo@nihongomaster.app","password":"Demo123!"}'
$authHeaders = @{
Authorization = "Bearer $($session.data.token)"
}Endpoint katalog bersifat public. Endpoint /v1/me/*, logout, dan memulai exam
membutuhkan bearer token. Google OAuth dijelaskan lengkap pada
Authentication and Google OAuth Setup.
Flutter membaca base URL dari compile-time variable API_BASE_URL di
lib/core/network/dio_client.dart.
Android Emulator memakai 10.0.2.2 untuk mengakses localhost komputer host.
Nilai ini sudah menjadi default aplikasi. Jika API_BASE_URL diisi dengan
localhost atau 127.0.0.1 pada Android, aplikasi juga menormalkannya otomatis
menjadi 10.0.2.2:
http://10.0.2.2:8080/v1
Jalankan backend terlebih dahulu, lalu:
flutter runGunakan localhost:
flutter run --dart-define=API_BASE_URL=http://localhost:8080/v1localhost dan 10.0.2.2 tidak menunjuk ke komputer developer dari perangkat
fisik. Gunakan alamat IPv4 LAN komputer, misalnya:
flutter run `
--dart-define=API_BASE_URL=http://192.168.1.20:8080/v1Pastikan:
- Komputer dan perangkat berada pada jaringan yang sama.
- Windows Firewall atau firewall OS mengizinkan port backend.
- Jaringan tidak mengaktifkan client isolation.
backend/
|- cmd/api/main.go Application entry point dan HTTP server
|- internal/api/server.go Routes, middleware, request/response JSON
|- internal/api/server_test.go HTTP contract tests
|- internal/auth/google.go Official Google ID-token verification
|- internal/domain/auth.go Session dan Google identity models
|- internal/domain/models.go Domain dan API data structures
|- internal/store/auth.go Account, bcrypt, dan revocable session
|- internal/store/memory.go In-memory repository dan seed data
|- go.sum Dependency integrity checksums
|- go.mod Module dan minimum Go version
`- README.md Quick reference
Tanggung jawab masing-masing package:
cmd/api: composition root. Membuat dependency dan menjalankan server.internal/api: transport HTTP. Tidak menyimpan business state secara global.internal/auth: verifikasi identitas dari provider eksternal.internal/domain: tipe domain tanpa ketergantungan pada HTTP.internal/store: penyimpanan dan aturan phase-1 seperti premium access.
Response berhasil memakai envelope data:
{
"data": {
"id": "demo-user",
"displayName": "Nihongo Learner"
}
}Response gagal memakai envelope error:
{
"error": {
"code": "premium_required",
"message": "premium entitlement required"
}
}Status penting:
| Status | Arti |
|---|---|
| 200 | Request berhasil |
| 201 | Resource, misalnya exam attempt, berhasil dibuat |
| 401 | Bearer token tidak ada, salah, atau sudah dicabut |
| 402 | Fitur membutuhkan entitlement premium |
| 404 | Resource tidak ditemukan |
| 422 | JSON valid tetapi data melanggar aturan domain |
| 500 | Error internal yang tidak diharapkan |
Invoke-RestMethod `
-Uri http://localhost:8080/v1/homeInvoke-RestMethod `
-Uri 'http://localhost:8080/v1/learning/tracks?system=JLPT'Nilai system saat ini: JLPT, NAT, atau JFT.
Invoke-RestMethod `
-Method Patch `
-Uri http://localhost:8080/v1/me/profile `
-Headers $authHeaders `
-ContentType application/json `
-Body '{"displayName":"Rabih","target":"JLPT N4"}'Mobile memilih foto dari galeri atau kamera lalu mengirim JPEG yang sudah
dikompres. Backend hanya menerima gambar JPEG, PNG, atau GIF hingga 8 MB,
memeriksa batas dimensi, mengecilkannya hingga 512 px, mengubahnya ke JPEG
quality 82 tanpa metadata EXIF, lalu menyimpan objek ke Tencent COS. Endpoint
POST /v1/me/profile/photo membutuhkan sesi login dan field multipart photo;
responsnya berisi profil terbaru dengan photoUrl. URL foto dapat dibuka oleh
siapa pun yang memiliki tautannya. Pastikan COS dan URL publik dikonfigurasi
seperti pada panduan backend.
completion harus berada antara 0 dan 100. Endpoint legacy ini tidak memberikan
XP atau achievement. Lesson vocabulary, grammar, kanji, dan reading harus
diselesaikan melalui kuis yang dinilai server; lihat aturan gamifikasi.
Invoke-RestMethod `
-Method Put `
-Uri http://localhost:8080/v1/me/progress/n5-grammar-001 `
-Headers $authHeaders `
-ContentType application/json `
-Body '{"completion":100,"lastPosition":420}'Invoke-RestMethod `
-Method Post `
-Uri http://localhost:8080/v1/exam-attempts `
-Headers $authHeaders `
-ContentType application/json `
-Body '{"examId":"jlpt-n5-diagnostic"}'Exam premium akan menghasilkan HTTP 402 untuk pengguna free.
Sebelum membuka pull request, jalankan dari folder backend:
go fmt ./...
go vet ./...
go test ./...Menjalankan satu package:
go test ./internal/api -vMenjalankan satu test:
go test ./internal/api -run TestFreeUserCannotStartPremiumExam -vgo mod download atau go mod tidy akan mengunduh official Google API client
untuk validasi ID token dan x/crypto untuk bcrypt password hashing.
- Tambahkan atau ubah model di
internal/domain. - Tambahkan operasi penyimpanan di
internal/store. - Daftarkan route dan handler di
internal/api/server.go. - Gunakan
writeData,writeError, dan status HTTP yang sesuai. - Tambahkan contract test dengan
httptest. - Jalankan formatter, vet, dan test.
- Akun, billing, XP/progress lesson, achievements, serta cache dan arsip kamus disimpan di MariaDB.
- Session login, attempt aktif, dan detail riwayat ujian masih berada di memori.
- Satu proses API memegang named writer lock per database untuk menjaga konsistensi cache akun/progress.
- Schema dibuat saat startup. Data lama dapat dipindahkan melalui importer; lihat panduan MariaDB.
Go belum terpasang atau terminal belum membaca PATH baru.
- Jalankan
where.exe gopada Windows atauwhich gopada macOS/Linux. - Install/upgrade Go dari https://go.dev/dl/.
- Tutup dan buka kembali terminal serta IDE.
- Jalankan
go version.
Gunakan port lain:
$env:PORT = '9090'
go run ./cmd/apiJangan lupa menyesuaikan Flutter:
flutter run --dart-define=API_BASE_URL=http://10.0.2.2:9090/v1- Utamakan
10.0.2.2; aplikasi akan menormalkanlocalhostuntuk Android Emulator, tetapi URL eksplisit lebih mudah diverifikasi dari log. - Pastikan backend masih berjalan.
- Coba health check dari komputer terlebih dahulu.
- Periksa firewall dan Android network security apabila memakai HTTP lokal.
Login kembali dan kirim token yang baru:
Authorization: Bearer <session-token>
Session login dan attempt aktif masih berada di memori. Akun, billing, dan
progress lesson tersimpan di MariaDB; periksa koneksi DB_* dan database yang
dipakai jika data tersebut tidak muncul.
- Perluas persistence MariaDB untuk data pengguna yang masih berada di memori.
- Persistent session dengan expiry, refresh rotation, dan device management.
- Payment provider webhook dengan signature validation dan idempotency key.
- Premium/lifetime entitlement audit log.
- Exam question bank, scoring engine, timer, dan attempt recovery.
- Object storage serta signed URL untuk audio dan materi offline.
- Background jobs untuk streak, reminder, leaderboard, dan achievement.
- Observability: structured logs, tracing, metrics, dan error reporting.