Awesome-omni-skill sojustack-best-practices
Best-practice guidance for the SojuStack monorepo (NestJS + Drizzle + Better Auth + TanStack Start). Use when editing files in apps/api or apps/web, designing routes, query/form patterns, auth/transaction flows, or implementing cross-stack features.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/sojustack-best-practices" ~/.claude/skills/diegosouzapw-awesome-omni-skill-sojustack-best-practices && rm -rf "$T"
manifest:
skills/development/sojustack-best-practices/SKILL.mdsource content
SojuStack Best Practices
Use this skill to keep changes idiomatic and safe in this repository.
Repository Map
- Backend:
(NestJS + Drizzle ORM + Better Auth)apps/api/ - Frontend:
(TanStack Start + TanStack Query + TanStack Form + ShadCN/Base UI)apps/web/ - Shared config:
packages/typescript-config/
Universal Rules
- Keep scope tight to the user request; avoid opportunistic refactors.
- Maintain strict typing; avoid
and unsafe casts.any - Match naming and folder conventions already used in the touched area.
- Prefer small reusable helpers over duplicate logic.
- If behavior changes, update/add tests for the impacted area.
Frontend Rules (apps/web
)
apps/webRouting (TanStack Start)
- Keep route modules focused; move reusable logic to hooks or components.
Data Fetching (TanStack Query)
- Use stable query keys like
.['resource', id, 'sub-resource'] - Use
without parameters when broad refresh is intended.invalidateQueries() - Keep server-state logic in query/mutation hooks, not presentational components.
UI (ShadCN + Base UI)
- Prefer components from
.apps/web/src/components/ui/ - Prefer Base UI primitives over raw HTML where an equivalent exists.
- Use
fromcn()
for class composition.apps/web/src/lib/utils.ts - Keep Tailwind usage aligned with existing tokens and utility patterns.
Backend Rules (apps/api
)
apps/apiDatabase (Drizzle)
- Add tables in
.apps/api/src/databases/tables/{name}.table.ts - Export new tables from
.drizzle.schema.ts - Add/update relations in
.drizzle.relations.ts
Auth (Better Auth)
- Follow existing setup in
.apps/api/src/auth/better-auth.provider.ts - Use framework auth helpers (
,@Auth()
,@ActiveUser()
) rather than ad hoc request parsing.@ActiveSession()
Transactions
- Use
with@Transactional()
.TransactionHost<DrizzleTransactionClient> - Do not manually nest/start transactions via
.tx.transaction()
Services and Errors
- Keep controllers thin; place business logic in services or providers.
- Use NestJS exceptions (
,NotFoundException
, etc.) for expected failures.UnauthorizedException
API Type Safety
- Treat
as generated source of truth for E2E typing.apps/api/generated/openapi.d.ts - Use existing DTO and serialization patterns in the module.
Execution Workflow
- Read nearby code and existing module patterns.
- Implement the smallest correct change.
- Run repository validation commands from the repo root:
pnpm typecheckpnpm formatpnpm lint
- If any of those commands fail, fix the issues and re-run until they pass.
- Ensure unrelated files are not modified.
- Report what changed, why, and how it was validated.
Do / Don't
Do
- Prefer simplicity and human readability of code over complex or verbose implementations.
- Heir on asking more questions rather than too little.
- Beware of premature optimization
- Reuse existing providers/utilities before adding abstractions.
- Keep functions cohesive and predictable.
- Add short comments only for non-obvious logic.
Don't
- Introduce architectural shifts unless requested.
- Add dependencies when existing stack primitives are sufficient.
- Bypass validation, auth, or typing conventions.