Skip to content

Dashboard Feature Template

Migrated from root technical docs.

Use this when adding a new dashboard feature or standardizing a small existing feature.

Not every feature needs every file. Add only what the feature uses.

apps/dashboard/src/features/{feature}/
api.ts
query-keys.ts
queries.ts
mutations.ts
model/
search-params.ts
components/
{Feature}Panel.tsx
pages/
{Feature}Page.tsx
hooks/
use{Feature}.ts
types.ts
index.ts
  • api.ts: dynamic import() + call() transport wrappers only
  • query-keys.ts: serializable, feature-owned query key factories
  • queries.ts: queryOptions(...) factories and invalidation helpers
  • mutations.ts: useMutation(...) wrappers and cache invalidation
  • model/: pure feature logic, mappers, filters, search defaults, validators
  • components/: reusable feature-owned UI only
  • pages/: route-level page entry rendered by thin route files
  • hooks/: feature-specific hooks that do not fit queries.ts or mutations.ts
  • types.ts: feature-local types
// apps/dashboard/src/features/{feature}/api.ts
import { call } from "@/shared/transport/server-fn-client";
export async function list{Feature}Items() {
const { list{Feature}Items } = await import("@/server/functions/{feature}");
return call(() => list{Feature}Items());
}
// apps/dashboard/src/features/{feature}/query-keys.ts
export const {feature}QueryKeys = {
all: ["{feature}"] as const,
list: (search: {Feature}Search) => ["{feature}", search] as const,
detail: (id: string) => ["{feature}-detail", id] as const,
} as const;
// apps/dashboard/src/features/{feature}/queries.ts
import { queryOptions } from "@tanstack/react-query";
import { list{Feature}Items } from "./api";
import { {feature}QueryKeys } from "./query-keys";
export const {feature}ListQueryOptions = (search: {Feature}Search) =>
queryOptions({
queryKey: {feature}QueryKeys.list(search),
queryFn: async () => list{Feature}Items(),
placeholderData: (previous) => previous,
});
// apps/dashboard/src/features/{feature}/pages/{Feature}Page.tsx
export function {Feature}Page() {
return <div>{Feature} page</div>;
}
  • Do not put route loaders, route declarations, or search validation here.
  • Do not put low-level shared primitives here if the component is generic.
  • Do not add helpers.ts or utils.ts if the logic belongs in model/.