Imported from yanarkhan/lms-project (
AGENTS.md). Install upstream withnpx skills add yanarkhan/lms-project. Copyright stays with the author.
AGENTS.md — LMS Project
Panduan kerja untuk siapa pun (manusia atau agent) yang berkontribusi pada repository ini.
Lokasi: root repository (lms-project/), berlaku untuk fe-lms/ dan be-lms/.
Dokumen ini berfokus pada aturan kerja, command, standar TypeScript, definisi selesai, dan
peta dokumen. Untuk daftar risiko, snapshot implementasi, dan riwayat pemeriksaan, lihat
docs/PROJECT_STATUS.md — jangan duplikasikan isinya di sini.
1. Tentang proyek ini
LMS (Learning Management System) yang dibangun mengikuti course "Kelas Online Full-Stack JavaScript MERN 2025: Web Course LMS" (BuildWithAngga). Tujuan akhir: portfolio project production-grade.
Perbedaan penting dari tutorial: proyek ini ditulis dalam TypeScript (TS/TSX), bukan JavaScript seperti materi course. Alur fitur dan struktur produk tetap mengikuti course; hanya implementasi bahasanya yang berbeda.
2. Struktur repository
Satu repository Git di root (lms-project/.git), bukan repo terpisah per aplikasi.
lms-project/
├── AGENTS.md (dokumen ini)
├── docs/
│ ├── PROJECT_STATUS.md
│ ├── ARCHITECTURE.md
│ └── PRD.md
├── fe-lms/ frontend — React + Vite
└── be-lms/ backend — Express + MongoDB
3. Stack teknis — versi ACTUAL, bukan versi course
Course mengajarkan React 18 dan Express 4. Repository ini terverifikasi memakai versi
di bawah (dikonfirmasi dari lockfile resolved + node_modules terpasang — keduanya cocok).
Catatan: package.json menyatakan range semver (mis. react: "^19.0.0"), bukan versi
exact — ini normal untuk semver, bukan inkonsistensi. Tabel di bawah adalah versi terpasang
sesungguhnya, bukan range yang diminta.
| Layer | Package | Versi terpasang |
|---|---|---|
| Frontend | react / react-dom | 19.2.4 |
| Frontend | react-router-dom | 7.13.1 |
| Frontend | vite | 6.4.1 |
| Frontend | typescript | 5.7.3 |
| Frontend | zod | 4.3.6 |
| Frontend | @tanstack/react-query | 5.90.21 |
| Backend | express | 5.1.0 |
| Backend | mongoose | 8.15.1 |
| Backend | typescript | 5.8.3 |
| Backend | zod | 3.25.64 |
| Backend | bcrypt | 6.0.0 |
| Backend | jsonwebtoken | 9.0.2 |
Implikasi konkret saat mengikuti tutorial:
- Express 5 mengubah parsing pola path tertentu (
path-to-regexp) dibanding Express 4. Jangan menyalin pola route opsional/wildcard gaya lama secara literal — verifikasi kompatibilitasnya. - React 19 mengubah sejumlah perilaku default dibanding React 18. Saat menulis pola baru dari tutorial, verifikasi dulu, jangan asumsikan identik.
- Node.js runtime terverifikasi: v24.14.0. Tidak ada
.nvmrcatau fieldenginesdi package.json.
4. Environment variables (nama saja — nilai tidak pernah dicatat di sini atau di laporan mana pun)
Backend (be-lms/.env): MONGODB_URL, APP_URL, PORT, SECRET_KEY_JWT,
MIDTRANS_SERVER_KEY, MIDTRANS_URL, CLIENT_CALLBACK_URL.
Frontend (fe-lms/.env, prefix Vite wajib VITE_): VITE_API_URL,
VITE_SECURE_LOCAL_STORAGE_HASH_KEY.
Tidak ada .env.example di kedua aplikasi pada saat pemeriksaan terakhir.
5. Standar TypeScript — berlaku mulai sekarang, bukan pasca-redesign
Baseline aktif saat ini (terverifikasi dari tsconfig): strict: true di FE (app & node config)
dan BE, plus noUnusedLocals, noUnusedParameters, noFallthroughCasesInSwitch,
noUncheckedSideEffectImports di FE. Standar di bawah ini dibangun DI ATAS baseline itu — tidak
ada yang boleh melemahkan baseline yang sudah aktif.
5.1 Opsi compiler tambahan (diusulkan, belum aktif — verifikasi & aktifkan bertahap)
noUncheckedIndexedAccess— disarankan aktif di FE dan BE. Ini akan memunculkan error baru pada akses array/object index yang selama ini diasumsikan selalu ada; jangan diaktifkan serentak lalu ditambal dengan!di semua titik — perbaiki per-modul sambil menyentuhnya.exactOptionalPropertyTypes— disarankan untuk FE, dievaluasi lebih hati-hati untuk BE karena interaksi dengan tipe Mongoose bisa berisik. Aktifkan setelahnoUncheckedIndexedAccessstabil.- Verifikasi status aktual kedua opsi ini di keempat file tsconfig sebelum mengasumsikan status di atas masih berlaku — proyek ini bisa berubah sejak dokumen ini ditulis.
5.2 Kebijakan any dan type assertion
anyeksplisit tidak diperbolehkan tanpa komentar yang menjelaskan alasannya dan, jika memungkinkan, rencana penghapusannya. Tidak untuk kenyamanan mengatasi error compiler.ashanya digunakan untuk mempersempit (narrow) tipe yang sudah dijamin benar oleh validasi runtime (mis. setelah Zod.parse()), atau narrowing union yang sudah diverifikasi lewat pengecekan eksplisit (typeof,in, discriminated union). Bukan untuk memaksa bentuk data yang belum tentu sesuai — itu menyembunyikan bug, bukan menyelesaikannya.as anydanas unknown as Xdilarang kecuali ada justifikasi tertulis di komentar dan sepengetahuan reviewer (Claude/user), bukan keputusan sepihak saat mengejar error hilang.- Non-null assertion (
!) memerlukan komentar yang menjelaskan mengapa nilai tersebut dijamin ada di titik itu. Lebih diutamakan guard clause eksplisit.
5.3 Validasi runtime dan typing API
- Setiap boundary yang menerima data dari luar (request body/query/params di controller, respons API di frontend sebelum dipakai) harus divalidasi lewat Zod sebelum diperlakukan sebagai tipe yang dipercaya — pola ini sudah dipakai sebagian di proyek, jadikan konsisten.
- Tidak ada shared type package antara FE dan BE saat ini (dikonfirmasi dari struktur repo) —
tipe request/response didefinisikan terpisah di kedua sisi dan bisa drift tanpa terdeteksi
compiler. Ini gap arsitektural yang dicatat, bukan diselesaikan otomatis oleh aturan ini;
lihat
docs/ARCHITECTURE.md§6 untuk opsi ke depan.
5.4 Typing Mongoose
- Model dan interface TypeScript-nya harus selaras; hindari
Schema.Types.Mixedtanpa justifikasi tertulis. - Gunakan tipe eksplisit dari Mongoose (
HydratedDocument<T>,Types.ObjectId) daripada membiarkan hasil query jatuh keany. - Klarifikasi: menggunakan inferensi tipe bawaan Mongoose sendiri (generic pada
Schema<T>/model<T>, atauInferSchemaType) adalah valid dan dianjurkan — ini BUKAN kategori "any implisit" yang dilarang di §5.2. Yang dilarang adalah membiarkan hasil query benar-benar tidak bertipe (fallback keany) atau memaksa cast tanpa jaminan runtime, bukan memanfaatkan mekanisme inferensi resmi yang disediakan library.
5.5 Null/error handling
- Tidak ada penanganan error terpusat yang teraudit di backend saat ini (belum diverifikasi
secara sistematis — dicatat sebagai gap, lihat
docs/ARCHITECTURE.md§5). Sampai ada keputusan pola standar, gunakan guard clause eksplisit dan try-catch di titik yang berisiko, bukan mengandalkan asumsi bahwa data selalu ada.
5.6 Linting FE dan BE
- FE:
eslint.config.jssudah ada (ESLint + typescript-eslint recommended + react-hooks). - BE: tidak ada konfigurasi ESLint sama sekali saat ini (dikonfirmasi kosong). Ini gap
konkret — menambahkan ESLint + typescript-eslint ke
be-lmsadalah item kerja yang layak dijadwalkan, bukan opsional.
5.7 Pemeriksaan otomatis vs panduan tertulis
Bagian 5.1–5.6 di atas adalah panduan untuk Codex saat menulis/mengedit kode. Panduan tertulis TIDAK SAMA dengan kepatuhan yang terverifikasi. Kepatuhan hanya dianggap terverifikasi setelah dicek lewat compiler dan linter yang benar-benar dijalankan (lihat §6 untuk command). CI belum diputuskan/dibangun — kandidat untuk fase berikutnya, bukan keputusan sekarang.
Aturan tegas: error compiler/linter TIDAK BOLEH diselesaikan dengan melemahkan konfigurasi (menonaktifkan rule, menurunkan strictness) atau menambahkan type assertion yang tidak didukung validasi data. Perbaikan harus menyentuh akar masalah atau menambahkan validasi runtime yang sesuai.
6. Command verifikasi (lingkungan Windows — npx diblokir Execution Policy)
Jangan mengubah Execution Policy sistem. Panggil executable langsung lewat node:
Semua command di bawah diasumsikan dijalankan berurutan mulai dari root repository
(lms-project/). Perhatikan cd .. di antara blok FE dan BE — tanpa ini, cd be-lms akan
mencoba masuk ke fe-lms/be-lms/ yang tidak ada.
# Frontend (dari root repository)
cd fe-lms
node node_modules/eslint/bin/eslint.js .
node node_modules/typescript/bin/tsc --noEmit -p tsconfig.app.json
node node_modules/typescript/bin/tsc --noEmit -p tsconfig.node.json
cd ..
# Backend (dari root repository)
cd be-lms
node node_modules/typescript/bin/tsc --noEmit -p tsconfig.json
cd ..
Untuk keperluan verifikasi rutin (mengecek error sebelum dianggap selesai), gunakan
--noEmit seperti di atas — jangan jalankan script build apa adanya (menulis dist/).
Ini bukan larangan permanen terhadap build itu sendiri — build production tetap boleh
dijalankan nanti dengan persetujuan eksplisit (misalnya menjelang persiapan deployment),
hanya saja bukan sebagai pengganti pemeriksaan tipe rutin.
7. Aturan kerja untuk agent (Codex atau lainnya) di proyek ini
- Jangan menebak sebagai fakta. Nama file, endpoint, schema, atau perilaku yang belum diverifikasi langsung dari source code harus ditandai sebagai INFERENSI atau BELUM DIKETAHUI.
- Sertakan bukti. Setiap klaim tentang kode disertai path file (dan baris jika relevan).
- Pisahkan FAKTA (source) / FAKTA (command) / INFERENSI / BELUM DIKETAHUI di setiap laporan.
- Jangan mencetak nilai secret dalam bentuk apa pun, termasuk dalam laporan atau contoh kode.
- Jangan menjalankan operasi yang mengubah data, memicu pembayaran sungguhan, atau berdampak ke layanan eksternal tanpa persetujuan eksplisit sebelumnya.
- Jangan commit atau push tanpa scope yang jelas disepakati lebih dulu.
6a. Perubahan lokal yang sudah ada di working tree tidak boleh ditimpa, di-checkout ulang,
di-stash, atau dibuang tanpa persetujuan eksplisit — termasuk saat menjalankan operasi
Git investigatif read-only (mis. jangan
checkoutbranch lain hanya untuk membaca isinya; gunakangit show <ref>:pathyang tidak mengubah working tree). Lihatdocs/PROJECT_STATUS.md§6 untuk snapshot working tree terbaru yang perlu dijaga. - Klaim "selesai" atau "test berhasil" harus disertai bukti — output command, path file yang diubah — bukan pernyataan tanpa verifikasi.
- Jika informasi tidak cukup, catat kekurangannya secara eksplisit, jangan mengisi kekosongan dengan asumsi.
- Error compiler/linter diselesaikan di akar masalah, bukan dengan melemahkan konfigurasi atau menambahkan assertion yang tidak didukung data (lihat §5.7).
8. Definisi selesai (umum)
Kriteria penerimaan spesifik per fitur ada di docs/PRD.md §4. Secara umum, sebuah pekerjaan
dianggap selesai bila:
- Kode terhubung end-to-end (bukan sebagian, bukan hardcoded sebagai pengganti API nyata).
-
tsc --noEmitdan lint (§6) berjalan bersih di area yang disentuh, tanpa melemahkan konfigurasi untuk mencapainya. - Ownership/akses diverifikasi sesuai pola yang berlaku di area terkait (lihat
docs/ARCHITECTURE.mduntuk peta otorisasi saat ini). - Diverifikasi manual (belum ada automated test) dengan langkah yang dapat diulang dicatat.
-
docs/PROJECT_STATUS.mddiperbarui: status fitur, risiko baru/hilang, hasil verifikasi.
9. Dokumen terkait
docs/PROJECT_STATUS.md— daftar risiko, snapshot implementasi, riwayat pemeriksaan, hal yang masih butuh keputusan user. Sumber kebenaran untuk status, bukan dokumen ini.docs/ARCHITECTURE.md— tanggung jawab komponen, alur utama, kontrak API, relasi data, keputusan arsitektur yang belum final.docs/PRD.md— cakupan produk dan kriteria penerimaan per fitur.README.md— dikelola terpisah, ditulis berdasarkan verifikasi langsung instalasi/build/run.
