Skip to content

Frontend Guidelines

See Tech stack page for the full tech stack.

In general, respect the current project structure and file names.

If not specified otherwise, follow the following guidelines:

  • Use kebab-case for file names.
  • Use features folder to add route components or scoped components. Look at other features in the repo. It shoud look like this:
    • features/
      • common/ for common files, hooks, etc.
        • hooks/
        • utils/
        • atoms/
      • featureName/
        • components/
          • feature-component.tsx
          • another-component.tsx
        • hooks/ for hooks scoped to this feature
        • utils/ for utils scoped to this feature
  • Use app folder to had global components that are used in multiple features.
  • Use utils folder to had utility functions.
  • Use components from @boilerstone/ui in ./packages/ui.
  • Check types, schemas and sdk from @boilerstone/openapi-generator in ./packages/openapi-generator.
    • ./packages/openapi-generator/client/sdk.gen.ts
    • ./packages/openapi-generator/client/schemas.gen.ts
    • ./packages/openapi-generator/client/zod.gen.ts
    • ./packages/openapi-generator/client/types.gen.ts
  • Use shadcn/ui for components.
  • Use react-router for routing.
    • routes are usually defined in a routes.ts file
  • Use react-hook-form for form handling.
  • Use zod for form validation.
  • Use tanstack-query for data fetching
    • structure queries by features, put the queries options in /features/featureName/utils/featureName-queries.ts
export function fetchOrganizationQueryOptions(options: { pageSize: number, page: number, search?: string }) {
return {
queryKey: ['organizations', options.page, options.pageSize, options.search],
queryFn: () =>
apiClient.organizationsControllerFindAll({
query: {
offset: (options.page - 1) * options.pageSize,
pageSize: options.pageSize,
filter: options.search ? `name:like:${options.search}` : undefined,
},
}),
}
}
// in component
const { data: organizations } = useQuery({
...fetchOrganizationQueryOptions({ page: pageValue, search: searchValue, pageSize: PAGE_SIZE }),
})