Frontend Developer Guide — Golan Sertifikasi Web
Stack: AngularRepository:
golan-webPrimary consumers: Students, instructors, admins, finance users, customer service
Backend: versioned REST/JSON public API through KrakenD Community Edition (
golan-backend)
The Angular application is a client of the backend. It must not become a second source of truth for authorization, payments, finance, course completion, or certificate eligibility.
1. Frontend Scope
Angular web is the MVP client for:- Google login/session handling and onboarding.
- Catalog/course detail.
- Midtrans top-up return/status, wallet balance and wallet-only cart/checkout.
- Order/top-up/ledger history and wallet-refund request/status.
- Permanent regular-course access, learning, progress, quiz, assignment, and regular certificate.
- BNSP registration/fulfillment status and secure LSP access display.
- In-app notification center and web push integration where supported by the selected provider/browser strategy.
1.1 Public Client Architecture
Angular is a public API client. Its network boundary is:- call internal gRPC ports;
- publish to or consume RabbitMQ directly;
- connect to PostgreSQL or Dragonfly;
- connect to ClamAV;
- construct internal service URLs or discover services;
- depend on private service database schemas or protobuf contracts;
- bypass KrakenD to call a service directly in production.
/openapi/openapi.yaml in the backend repository) under /api/v1/.... Internal gRPC/protobuf and RabbitMQ event schemas are backend implementation contracts, not Angular contracts.
Angular may know domain ownership for diagnostics and UI semantics, but it must address public resources, not deployment units. A future backend service split/merge that preserves OpenAPI should not require a frontend architectural rewrite.
2. Recommended Angular Structure
Use feature-based boundaries.components/ directory containing unrelated features.
3. Routing
Example:4. Authentication
Google login flow should be thin on the frontend:- If backend architecture supports same-site cookies, prefer secure HttpOnly session/refresh cookies.
- Do not store long-lived sensitive tokens in localStorage unless architecture requires it and risks are explicitly accepted.
5. Auth State
Central auth state should contain only what the UI needs. Example:6. Guards
Examples:- Authenticated but onboarding incomplete →
/onboarding. - Guest accessing private route →
/login. - User lacking frontend permission → render 403/access denied.
- Never assume route guard equals backend authorization.
7. HTTP Layer
Use one consistent public API client layer whose base URL points to KrakenD, not to individual services.- UI logic may branch on stable
error.code; do not branch on arbitrary message text. - Surface
fieldsfor form validation when supplied. - Preserve
request_idfor support/diagnostics. - Do not expose raw gateway/service stack traces.
- Do not scatter raw
HttpClientcalls through components. - Do not blindly retry mutation requests. A retryable mutation requires an explicit idempotency contract/key or a backend-provided safe recovery flow.
502,503, timeout, and network errors mean canonical state may be unknown; refetch authoritative resources before claiming failure/success for critical workflows.
8. API Models
Do not manually invent slightly different models per screen. Use:- Shared generated API types from OpenAPI, or
- A disciplined API model layer.
9. State Management
Do not add a heavy global store by default for every screen. Recommended approach:- Local component state for small isolated UI.
- Signals/services for feature state.
- Introduce NgRx only where state complexity justifies it.
10. Public Catalog
Course cards should clearly distinguish:- Golan issues the BNSP certificate.
- Assessment happens inside Golan.
- Passing is guaranteed by purchase.
11. Course Detail
Regular course
May show:BNSP product
Should show:12. Onboarding
Three steps:Step 1 — Profile
Step 2 — Interests
Multi-select course categories.Step 3 — Acquisition
Single-select source +Other text when needed.
Requirements:
- Preserve entered values between steps.
- Load categories from API.
- Validate client-side for UX.
- Backend remains authoritative.
- Completion request only after required steps are saved.
13. Cart
Cart must support both course types. Each item should show type:14. Top-up and Wallet Checkout
Suggested flow:A successful Midtrans browser callback is not proof of a wallet credit or course purchase. Midtrans never pays a course order directly.The UI must wait for backend canonical status. States:
15. Payment Result UX
After Midtrans top-up UI closes/returns:- Do not instantly create local enrollment state.
- Refetch top-up and wallet; never create or mark a course order paid from the redirect.
- If pending, show top-up verification state.
- Offer manual “Check top-up status”.
- After wallet credit, checkout via Commerce and refetch its order until it reports paid:
- Regular course → link to My Courses.
- BNSP → link to BNSP Registration status.
16. Student Regular Learning
Suggested layout:17. Quiz UX
Support:- Timer only when the backend/API returns an effective timed-attempt policy.
- Warn before leaving an active attempt.
- Submit through backend with double-submit protection.
- Show score/status according to backend response.
- Never expose correct-answer metadata before submission unless backend review policy explicitly permits it.
- Essay submission must render
pending_reviewor equivalent when manual grading is outstanding. - Do not show
passedmerely because the HTTP submission request succeeded. - Manual grading screens are available only to actors with grading permission and must show grading actor/result history where the API exposes it.
- After grading mutation, refetch/reconcile the canonical attempt rather than locally manufacturing final course-completion state.
18. Assignment UX
Support:- The current MVP default is three submissions, but Angular must never embed
3as the business authority. - Render
max_submissions,submissions_used,can_resubmit, and any deadline/reason from the backend response. - Every submission is shown as its own historical record where UX requires history; a resubmission must not visually overwrite the prior attempt as though it never existed.
- Disable/enable resubmit controls from canonical backend capability fields and still handle server rejection because policy may change between render and click.
- Grading success is not inferred from upload/submission success.
19. Regular Certificates
Student area:20. BNSP Student Experience
Dedicated area:Credential UX
Credentials are sensitive. Requirements:- Password hidden by default.
- Explicit “Show” action.
- Copy button available.
- No secret in browser URL.
- No secret in analytics payload.
- No secret in error logging.
- Avoid persisting secret in application state longer than necessary.
- API response containing secret should not be cached.
- Clear secret state when navigating away if practical.
pending_access should communicate that payment is confirmed and admin is preparing LSP access without promising a client-computed timestamp.
access_delivered means authorized staff have recorded delivery. Student opening/viewing credentials must not trigger that status transition. If a future acknowledgement feature exists, render it as a separate concept.
This is not an internal BNSP assessment screen.
21. Admin BNSP Fulfillment
Admin screen:- Creating/updating credentials and marking delivery are distinct mutations.
- “Mark Delivered” is an explicit authorized action; merely viewing the admin screen or student screen does not set delivery state.
- After mark-delivered succeeds, refetch the backend record before showing final state.
- SLA overdue styling/badges are derived from backend fields/filter results, not from a locally embedded policy duration.
- Credential mutation forms must avoid accidental resubmission and must not write secrets to logs, analytics, URL state, or persistent client caches.
- Monitoring/escalation queues should be operationally sortable/filterable without inventing a new certification state.
22. Admin Course Management
Course editor should conditionally render sections. Forregular:
bnsp:
23. RBAC UX
Navigation visibility can use permissions. Examples:- Hidden button ≠ authorization.
- Handle backend 403 cleanly.
- Provide a generic access denied page.
24. Reviews and Wishlist
wishlist is Phase 2 and must not block MVP delivery. If its existing UI/domain code remains, keep it isolated from core checkout/catalog paths.
reviews/ratings have not been explicitly assigned to MVP or Phase 2 in the current product decision. Treat release scope for reviews as an Open Product Decision; do not silently make reviews a release blocker.
For any enabled review UI, backend remains authoritative for eligibility and moderation state.
24.1 Media Upload and Scan Contract
Assignments, course media, certificate files, and other binary objects are governed by Media Service behind the public API. Angular must not construct arbitrary S3 object keys or treat a successful upload transfer as proof that a file is usable. Expected untrusted-upload lifecycle:- Only
cleanmedia can be treated as trusted/usable. pending_scan,scanning, andscan_failedrequire a waiting/error state; do not silently attach them as completed assignment content.infectedmust be rejected and never offered for normal download.- Private downloads use authorized temporary URLs or another backend-controlled access mechanism.
- Original filenames are presentation metadata, not trusted object identifiers.
- BNSP credentials and auth tokens must never be sent through media metadata.
25. Errors
Map backend error codes to useful UI. Examples:26. Loading and Empty States
Every data screen needs:27. Analytics
Track approved UI events only. Examples:28. Accessibility
Minimum:- Keyboard navigable controls.
- Form labels.
- Semantic headings.
- Error messages associated with fields.
- Accessible dialogs.
- Color is not the only status indicator.
- Video content should support accessibility improvements when content production allows.
29. Responsive Design
Primary breakpoints should support:30. Performance
Use:- Lazy routes.
- Image optimization.
- Pagination/infinite load where appropriate.
- Avoid loading complete course content in catalog payload.
- Avoid repeated
/mecalls. - Cache only non-sensitive data appropriately.
- Use trackBy/equivalent stable identity for lists.
31. Environment and Runtime Configuration
Typical environments:Business-policy rule
Do not add frontend environment variables such as:31.1 Distributed Backend Workflow Semantics
The backend uses service-owned transactions plus asynchronous RabbitMQ processing for many cross-domain effects. Angular must not assume that one HTTP response means every downstream service has converged. Examples:- After Midtrans top-up return, fetch canonical top-up and wallet status; never infer wallet credit or paid order from redirect parameters.
- If Commerce confirms wallet capture and the order is paid but enrollment/BNSP registration is not yet visible, show a neutral processing state and refetch with bounded backoff.
- A timeout on a mutation is an unknown outcome until the resource is refetched or the idempotent command result is resolved.
- Duplicate notifications/events must not trigger duplicate UI mutations.
- Do not build UI logic around RabbitMQ event names or queue timing.
- Use backend-exposed business statuses, timestamps, capabilities, and reason codes.
32. Testing
Unit
Focus on:Component
Focus on:E2E
Critical web flows:33. Frontend Definition of Done
A feature is complete when:- Success/loading/empty/error states exist.
- Backend validation errors are rendered correctly.
- Permissions affect UX without pretending to provide backend security.
- Sensitive data is not persisted unnecessarily.
- BNSP and regular product semantics are clearly separated.
- Payment success waits for backend canonical status.
- Mobile-responsive behavior is acceptable.
- Tests cover critical interactions.
- API contract matches current OpenAPI/SSOT.
- All production API traffic uses the configured KrakenD/public API origin; no feature calls internal service hosts/gRPC.
- Distributed-workflow screens tolerate eventual convergence and unknown mutation outcomes.
- Upload-dependent flows respect Media Service scan state before considering a file usable.
34. Frontend Engineering Baseline
The web repository should define a small set of non-negotiable conventions so feature teams do not create incompatible patterns. Recommended baseline:35. Route and Access Contract
Routes should encode presentation/navigation, while the backend remains authoritative for access. Recommended route metadata concept:admin. Route access should use backend-supplied permissions where practical.
When a protected API returns 403 despite the UI believing access exists, the UI must accept the backend result, show access denied, and refresh permissions if appropriate.
36. Session and Authentication Lifecycle
The web app must handle more than the initial Google button. Canonical client states:- Prevent multiple simultaneous refresh attempts from producing a refresh storm.
- Queue or fail requests consistently while a refresh is in progress.
- A failed refresh that definitively means session expiry must clear authenticated state.
- A temporary network error must not be confused with explicit logout/session invalidation.
- Logout must clear client auth state and sensitive feature state.
- Never log OAuth credentials, access tokens, refresh tokens, or raw auth responses.
37. DTO, View Model, and Enum Discipline
API DTOs and UI view models solve different problems and should not be conflated. Recommended pattern:paid.
Prefer exhaustive handling of known states so a new backend enum causes a visible development/test failure rather than silent incorrect UI.
38. Form Architecture and Validation
Use reactive forms for onboarding, checkout-adjacent forms, admin forms, refund/withdrawal forms, and other multi-field workflows. Validation layers:- Preserve form values after server validation failure.
- Disable duplicate submit while the same mutation is in flight.
- Do not permanently disable the button after recoverable network failures.
- Dirty-form navigation warnings should be used for high-loss forms such as course editing and admin BNSP credential entry.
39. Query, Pagination, Filter, and URL State
Catalog and admin lists should have predictable URL-addressable state. Recommended URL parameters:- Refreshing the page should preserve meaningful list/filter state.
- Back/forward navigation should behave correctly.
- Do not fetch on every keystroke without debounce for search.
- Cancel or ignore stale requests when new query state supersedes them.
- Pagination metadata comes from backend.
- Do not infer total pages from current page length.
40. Mutation and Idempotency UX
Client mutation state should distinguish:unknown_result matters for operations where the request may have reached the server but the response was lost.
For checkout/payment/financial mutations:
- Prefer backend-supported idempotency keys where defined.
- Do not automatically replay a request merely because a timeout occurred.
- Provide a safe reconciliation action such as refetching order status.
41. Detailed BNSP Credential Retrieval Contract
The student credential screen should be deliberately isolated from ordinary cached feature state. Suggested UI flow:- Password/secret is never shown in list rows.
- Edit behavior must not accidentally blank an existing encrypted secret when the secret field is left untouched.
- If the backend uses explicit replace semantics, the form must distinguish
unchanged,replace, andclearwhere clearing is permitted. - After saving, scrub the plaintext secret from the form model as soon as practical.
42. Admin and Backoffice Interaction Standards
Backoffice screens are operational tools and should prioritize correctness over decorative UI. Every table/list that can trigger consequential actions should expose enough context to avoid acting on the wrong entity. Examples:Are you sure? for financial or irreversible actions.
43. Design System and UI State Contract
Create shared primitives for repeated behavior rather than one-off implementations. Minimum reusable components/patterns:44. Frontend Observability and Privacy
Production frontend telemetry should help diagnose failures without collecting secrets. Useful context:45. Expanded Frontend Test Matrix
Testing should be organized by risk and locked business semantics, not just component count.Contract tests
Verify that generated/central API models compile against the current OpenAPI contract and that enum/field changes are surfaced, including derived policy fields.Auth tests
Commerce + refund tests
Learning tests
BNSP tests
Notification tests
Backoffice tests
Accessibility tests
Critical flows should be usable by keyboard and expose labels/roles for automated accessibility checks.46. Build, Delivery, and Runtime Configuration
The built Angular artifact must not contain backend-only secrets. CI stages should include at minimum:47. Frontend Feature Acceptance Template
Every substantial feature should be reviewed against this template before merge/release.48. Refund Workflow UX
Refund is MVP and is manual/admin reviewed. Student flow:- Current default request window is seven days after payment, but the UI must never calculate eligibility from
payment_date + 7 daysas authority. - Prefer rendering
refund_request_deadline_at,can_request_refund, and reason codes supplied by backend. - Request success does not mean refund approval or completed financial reversal.
- Do not revoke/hide course/BNSP access client-side merely because a request was submitted.
- BNSP with
access_deliveredis non-refundable by default; render backend decision/reason rather than reproducing this logic locally.
49. Push + In-App Notification Contract
The locked product SSOT and backend guide require push in MVP alongside in-app and email. Angular must not compensate for notification delivery delays or failures by inventing notification business state. Rules:- Backend notification/event state is canonical.
- A browser push payload is a navigation/refetch hint, not the final business state.
- Opening a notification should route using a safe reference and fetch the current resource through KrakenD.
- Duplicate push events must not cause duplicate mutations.
- Handle permission denied, unsupported browser, subscription rotation, logout, and revoked-session cleanup without breaking the in-app notification center.
- Never put LSP credentials, auth tokens, payment secrets, private document URLs, or sensitive financial values in push payloads.
- Do not require WebSocket for MVP notification correctness. Persistent in-app notification state plus refetch/push is sufficient; if one-way live UI updates are later required, evaluate an explicit backend-supported mechanism rather than opening arbitrary service sockets.
50. MVP Scope and Open Product Decisions
Web MVP includes student web plus admin/instructor/finance/customer-service operational workflows. Phase 2 features listed in the SSOT are non-blocking. If a product behavior is not specified by the SSOT/API, Angular must not invent a durable rule. Important unresolved examples currently include:Open Product Decision until the SSOT is revised. UI can show generic backend-provided capability/reason fields without defining the missing policy itself.