Skip to main content

Development Guide

Introduction

This guide describes how to safely add or modify frontend features in the Ravenxcope frontend.


Before Changing Code

  1. Identify the route and feature folder involved.
  2. Check whether the workflow already has an API method in src/lib/api.ts.
  3. Check whether shared types already exist in src/types/index.ts.
  4. Check whether the UI action needs permission gating.
  5. Check whether text should be localized in src/locales/en.json and src/locales/id.json.
  6. Check whether the feature needs runtime configuration.

Adding an API Endpoint

  1. Add or update TypeScript types in src/types/index.ts.
  2. Add the endpoint method to the relevant group in src/lib/api.ts.
  3. Use the shared apiClient unless the endpoint specifically needs fetch streaming.
  4. Keep the backend path relative to API_BASE.
  5. Return a typed Promise<AxiosResponse<ApiResponse<T>>> where possible.
  6. Use buildRepeatedQueryParams() for array query params that backend expects as repeated keys.

Avoid creating new Axios instances in feature components.


Adding a Route

  1. Create the route-level component in src/modules/<domain>/pages.
  2. Put feature-specific sections in src/modules/<domain>/partials.
  3. Put modal flows in src/modules/<domain>/dialogs.
  4. Import the page in src/app/routes.tsx.
  5. Add a public route or nested dashboard route definition.
  6. If it belongs in the sidebar, set showInNav, navLabelKey, and icon on the dashboard route.
  7. If other modules need the path, add/update ROUTES in src/lib/constants.ts.

Adding a Feature Screen

Follow existing feature screen patterns:

  • Use shared UI primitives from src/components/ui.
  • Wrap dashboard route content in RoutePage.
  • Use DataTableCard for management list/table pages.
  • Use Card, Table, Dialog, Badge, Skeleton, and Button consistently.
  • Keep create/edit forms in dialogs when matching user, role, and sensor flows.
  • Use local state flags to trigger refetches when following current hooks.
  • Show user feedback through existing alert/toast helpers.

Adding Data Fetching

For common resource reads, add or extend hooks in src/hooks/useApi.ts.

Current hook conventions:

  • Use useState for data, loading, and error.
  • Use useEffect for request lifecycle.
  • Check auth.isAuthenticated() when data is private.
  • Use AbortController to avoid setting state after unmount.
  • Return empty fallback arrays for list-style hooks.
  • Expose refetch only where callers need it.

For feature-specific one-off requests, calling api directly inside the component is acceptable when it matches surrounding code.


Adding Permission-Gated Actions

  1. Add the permission slug to PERMISSIONS in src/lib/constants.ts if it does not already exist.
  2. Use useUserPermissions() in the screen.
  3. Hide the action when hasPermission(slug) is false.
  4. Keep destructive actions behind confirmation.
  5. Do not rely on frontend checks for security; backend authorization must still enforce the rule.

Adding Forms

Current forms use controlled state and manual submit handlers.

Recommended pattern:

  1. Initialize form state with all required fields.
  2. Load select options in useEffect when needed.
  3. Validate simple required/cross-field rules before calling the API.
  4. Disable form controls while submitting.
  5. Convert UI field names to backend payload names in one place.
  6. Use showSuccess, showError, or toast for feedback.
  7. Close the dialog or navigate only after a successful response.

Adding Localized Text

  1. Add English keys to src/locales/en.json.
  2. Add Indonesian keys to src/locales/id.json.
  3. Use const { t } = useTranslation() in the component.
  4. Avoid introducing new hard-coded user-facing strings in screens that already use i18n.

If a screen is currently hard-coded, localize touched text when reasonable, but avoid broad unrelated rewrites.


Updating Runtime Configuration

When adding a new runtime flag:

  1. Extend AppRuntimeConfig and AppConfig in src/config/appConfig.ts.
  2. Parse and validate the value in getRuntimeConfig().
  3. Add it to .env.example.
  4. Add it to docker-entrypoint.sh.
  5. Document it in the Configuration and Deployment Runbook.
  6. Ensure invalid values fail closed or fall back safely.

Manual Verification Checklist

For UI changes:

  1. Run TypeScript/build if behavior changed:
yarn build
  1. Run lint if code changed:
yarn lint
  1. Test login and /dashboard route protection.
  2. Test the changed route directly and after browser refresh.
  3. Test success and failure paths for API mutations.
  4. Test permission-hidden states when relevant.
  5. Test mobile layout for sidebar, tables, dialogs, or sheets.

For documentation-only changes, verify file names and path references. A frontend build is not required.


Documentation Updates

Update the documentation when:

  • A route is added, removed, or renamed.
  • A runtime config key changes.
  • API endpoint groups or payload contracts change.
  • Auth/session behavior changes.
  • Feature behavior changes in sensors, analytics, users, roles, or organizations.
  • Deployment behavior changes in Docker, Nginx, or config injection.