Add an API-backed feature (console)
Read first: console/AGENTS.md → "Golden path", "The two-file API pattern", "Routing". For UI components/theming see console/.ai/oxygen-ui/AGENTS.md. This skill is the executable checklist.
Steps
- Fetch fn —
workspaces/libs/api-client/src/apis/<resource>.ts. Pure function takingparams(path),query(search),getToken. Use thehttpGET/POST/PUT/PATCH/DELETEhelpers from../utils(they readglobalConfig.apiBaseUrland set the Bearer header) — never hand-rollfetch. Prefix API paths withSERVICE_BASE(/api/v1), orOBS_SERVICE_BASEfor the observability service. - Hook —
workspaces/libs/api-client/src/hooks/<resource>.ts. Wrap withuseApiQuery/useApiMutation(from./react-query-notifications), not rawuseQuery/useMutation— the wrappers auto-fire snackbars. Get the token fromuseAuthHooks().getTokenand pass it into the fetch fn. - Export both from the package barrels (
apis/index.ts,hooks/index.ts). - Consume the hook in a page under
workspaces/pages/<feature>/. - Register the page — export
metaData({ title, icon, path, component }) from the feature package'sindex.ts; wire the route incore-uiusing the generated route maps.
Conventions that matter
queryKeyis a tuple:[domain, params, query]for a detail,[domain]for a collection. Invalidation is prefix-based —qc.invalidateQueries({ queryKey: ["agents"] })clears every["agents", …]. Invalidate in the mutation'sonSuccess.useApiMutationtakesaction: { verb, target }→ renders "Agent created successfully". Set it.- Routing: use
relativeRouteMap.…pathfor<Route path=…>andabsoluteRouteMap.…path+generatePath(path, {...})for links. Never hardcode path strings. - UI imports from
@wso2/oxygen-ui, not@mui/material. Forms are manualuseState+ inline validation (no react-hook-form).
Commands
# from inside the changed package dir:
rushx lint # eslint (flat config)
rushx build # build → dist/
rushx test # vitest
# from console/:
make build # rush build (cross-package changes)
make dev # dev server → http://localhost:3000
Done checklist
- Fetch fn + hook follow the two-file pattern and are exported from the barrels.
- Mutation invalidates the right prefix
queryKeyinonSuccess. - Token comes from
useAuthHooks().getToken. - Page exports
metaDataand is routed via the generated route maps. -
rushx lint+rushx buildclean for touched packages.