Rules for building full-stack features with frontend and backend changes.
Follow these rules when creating features that span the client-portal frontend and Node.js backend.
Add an exported function in /client-portal/app/jupiter-api/index.ts using the request wrappers:
// Example: GET request
export const getInvoices = (clientId: string) =>
get<Invoice[]>(`/customer/client/invoices?clientId=${clientId}`);
// Example: POST request
export const createPayment = (data: CreatePaymentRequest) =>
post<Payment>('/customer/client/payments', data);
// For GET requests
const { data, isLoading } = useQuery({
queryKey: ['invoices', clientId],
queryFn: () => getInvoices(clientId),
});
// For mutations (POST/PATCH/DELETE)
const mutation = useMutation({
mutationFn: createPayment,
onSuccess: () => queryClient.invalidateQueries(['invoices']),
});
Refer to @./client-portal-frontend-components
Main router: /backend/routes/customer/index.ts (mounted at /customer) Auth routes: /backend/routes/customer/auth.ts (mounted at /customer/auth) Client routes: /backend/routes/customer/client.ts (mounted at /customer/client)
// /backend/routes/customer/client.ts router.get('/invoices', authMiddleware, invoiceController.getInvoices);
Controllers: /backend/controllers/ - request/response handling Services: /backend/services/ - business logic Middleware: /backend/middleware/ - auth, validation, etc.
E2E tests use Playwright and live in /client-portal/e2e/.