think
16px
820px

Codebase Navigation Cheatsheet — AHU-OCR (dev_4)

A practical guide to going from "this is broken""that file" without knowing the whole system. Written around the real bugs we fixed so the examples are concrete.

The one trick that solves 80% of cases

Copy the exact text you see on screen (or in an error) and grep for it. Almost every user-visible string lives, verbatim, in the file that produces it.

cd backend   # or frontend
grep -rn "Tidak ditemukan" src        # → the KBLI rule that emits this message
grep -rn "Dokumen belum lengkap" src  # → the gate that blocks "Lanjut"

Indonesian UI text is usually in a frontend component; validation/error messages are usually in a backend service. Grep both if unsure.

The mental model

BACKEND  (backend/src/)              FRONTEND (frontend/src/)
─────────────────────────           ─────────────────────────
routes/    URLs  handlers          pages/       one file per screen
services/  business logic           hooks/        fetch + mutate (API calls)
lib/       DB clients, config       components/    reusable UI pieces
flow-engine/  which rules run        routes.tsx    URL  which page
review/    build the review screen   lib/          types + helpers
prisma/    database schema           main.tsx      app setup

Data flows left to right on each side, and the frontend talks to the backend through hooks/routes/.

Backend: where things live

Folder What's in it Example from our fixes
routes/ HTTP endpoints (one file per area). A URL like /api/submissions/:id/review maps to a handler here. routes/review-data.ts = the review screen's data + finalize
services/ The actual logic. Validation rules, the OCR/extraction pipeline, matching. services/cross-validator-kbli.ts = KBLI validation rules
lib/ Low-level clients & config. Database pools, logger, config.ts. lib/sabh-db.ts = the SABH MySQL connection
flow-engine/rules/ Which rules run for which flow. flow-engine/rules/pt-akta/index.ts lists PT's validation rules
review/projectors/ Turn stored data into the shape the review page needs. review/projectors/pt-pendirian-review.ts
prisma/schema.prisma The database tables.

Trace example (the KBLI fix): user sees "Tidak ditemukan: 62019" →
grep -rn "Tidak ditemukan" backend/srcservices/cross-validator-kbli.ts (the rule) →
it calls validateKbliCodes in lib/sabh-db.ts (the DB query). That's the whole chain: service → lib.

Frontend: where things live

Folder What's in it Example
pages/ Full screens, one per route. pages/PtPendirianReviewPageV2.tsx = the Tinjauan (review) screen
components/ Reusable UI blocks used by pages. components/pendirian/validation-results.tsx = the "Hasil Validasi" panel
hooks/ Everything that talks to the backend (TanStack Query). hooks/use-submission.ts (useOverrideValidation, etc.)
routes.tsx The URL → page map. Start here to find which file a URL renders. pendirian/:id/reviewPtPendirianReviewPageV2
lib/ Shared types + formatters. lib/submission-types.ts (ValidationResultItem)

Trace example (the override UI): "there's no way to override a validation on the review screen" →
routes.tsx tells you the review URL renders PtPendirianReviewPageV2.tsx
it renders <ValidationResults> from components/pendirian/validation-results.tsx
which calls useOverrideValidation from hooks/use-submission.ts
which POSTs to routes/submissions.ts on the backend. page → component → hook → route.

Symptom → where to look first

Symptom Start here
A screen looks wrong / is blank frontend/src/pages/<Screen>.tsx, then the hooks/ it calls
A button is disabled / a gate blocks you The page's gate logic (grep the tooltip text), e.g. PendirianExtractionPage.tsx
A validation says the wrong thing backend/src/services/cross-validator*.ts (the rule) + flow-engine/rules/<flow>/index.ts (whether it runs)
Data from SABH is missing/wrong backend/src/lib/sabh-db.ts (queries) + services/sabh-*.ts
An API call 404s or errors backend/src/routes/<area>.ts (grep the URL path)
A field was extracted incorrectly backend/src/services/document-processor.ts
"Which validation rules apply to flow X?" backend/src/flow-engine/rules/<flow>/index.ts

How to confirm you found the right file

  1. Read the test next to it. Most logic files have a *.test.ts (backend) or *.test.tsx (frontend) sibling, often in a __tests__/ folder. The test names describe the behavior in words.
  2. Run just that test to see it pass/fail:
    bash cd backend && bun test src/services/__tests__/cross-validator-kbli.test.ts cd frontend && node node_modules/.bin/vitest run src/components/pendirian/__tests__/validation-results-override.test.tsx
  3. Follow the imports at the top of the file — they point to the next link in the chain.

Useful grep recipes

# Which page does a URL render?
grep -n "pendirian/:submissionId" frontend/src/routes.tsx

# Which file emits an on-screen message?
grep -rn "SABH database tidak tersedia" backend/src

# Where is a function defined vs. used?
grep -rn "validateKbli" backend/src        # definition + all callers

# Which rules run for a flow?
sed -n '1,60p' backend/src/flow-engine/rules/pt-akta/index.ts

Rule of thumb: grep the words, follow the imports, read the test. Those three moves locate almost anything.