---
name: teamshare-modularity
description: Enforce TeamShare's modular architecture when writing code in teamshare-backend, frontend, teamshare-mobile-app or teamshare-bridge. Follow the per-repo layout (src/modules/<feature>/{controller,service,dto,module}, src/components/{ui,shared}, modules/<feature>/{views,components,columns,hooks,utils}, src/lib/api per feature), never import vendor ui/ in app code, use TS* wrappers, zod-first DTOs, the response envelope, and pass the repo build/typecheck gates before done.
---

# TeamShare Modular Architecture Enforcement

TeamShare is four separate repos with strict internal layouts. Before writing
code, check which repo you are in and follow its module structure exactly.
These rules are enforced per repo — know where you are.

## 1. teamshare-backend (NestJS + Prisma 6 + zod)

- **Layout:** a feature lives in `src/modules/<plural-feature>/` with
  `<feature>.controller.ts`, `<feature>.service.ts`, `<feature>.dto.ts`,
  `<feature>.module.ts` (+ `*.spec.ts`). Cross-cutting infra goes in
  `src/common/<area>/` (constants, decorators, dto, filters, guards,
  interceptors, pipes, prisma, utils, ...) — never inside a feature module.
- **DTOs are zod-first:** `export const CreateXSchema = z.object({...})` +
  `export type CreateXDto = z.infer<typeof ...>`. Validate via
  `@Body(new ZodValidationPipe(Schema))`. Import enum schemas from
  `src/generated/zod/schemas/enums/...`; never hand-edit `src/generated/zod`.
- **Every endpoint returns the envelope** `{ success, data, pagination? }`
  (TransformInterceptor) — handlers return raw data, lists return
  `{ items, pagination }` via `computePagination`.
- **Every endpoint declares access metadata** (`@Permissions`, or
  `@Public()` + `@UseGuards(AgentsDualAuthGuard)` + `@ApiKeyScopes` for the
  agent+human surface) — see the teamshare-auth-rbac skill.
- **Prisma:** `prisma/schema.prisma` is the single source of truth. After a
  schema change run `npx prisma generate` (do not hand-edit generated zod).
  Deploy migrations with `npx prisma migrate deploy`, never `migrate dev`.
- **Error style:** throw exceptions with a machine-readable `code`
  (`new BadRequestException({ code: 'X', message: '...' })`).

## 2. frontend (Next.js App Router + Tailwind v4 + TanStack Query)

- **Two component layers, never mixed:**
  - `src/components/ui/` = VENDOR shadcn primitives — do not edit, do not
    import from app code.
  - `src/components/shared/` = TeamShare `TS*` wrappers. **App code imports
    ONLY from `@/components/shared`** (barrel `index.ts`). Build new shared
    components here, named `TS*`, with `data-slot="ts-*"` and `--ts-*` tokens.
- **Feature modules:** `src/modules/<feature>/{views,components,columns,hooks,utils}`.
  Pages under `src/app/` stay thin and delegate to views. Route tabs use
  `useUrlTab` (`?tab=...`).
- **API + data:** per-feature `src/lib/api/<feature>.ts` exporting a
  `<feature>Api` object of `listX/getX/createX/updateX/deleteX`; envelope-aware
  `apiFetch` from `@/lib/api/client`. Query keys via `qk.*` factory
  (`src/lib/query-keys.ts`), list state via `useListState`.
- **Validation mirror:** zod schemas live in `src/lib/validation/schemas.ts`
  and MIRROR the backend contract (backend is canonical). Enums derive from
  the schemas in `src/lib/constants/enums.ts`.
- **Tables/forms:** TanStack React Table **v8** inside `TSTable`; forms always
  `TSForm` + `TSFormField` + `zodResolver`.
- **IconSax hard rule:** `iconsax-react`, every icon passes `variant` AND
  `color`; pick names from `docs/ui-style-guide.md` §6.4. No emoji as icons.

## 3. teamshare-mobile-app (Expo SDK 57 + NativeWind v4)

Same two-layer rule (`ui/` vendor vs `shared/` `TS*`), same zod schema
mirroring, same `modules/<feature>/` organization. Themexing via `--ts-*`
tokens; run `npx expo start --clear` when classes misbehave on Windows.

## 4. teamshare-bridge (plain CommonJS TypeScript)

- `src/lib/` = shared modules (plain exported functions + classes, named
  exports, single quotes, JSDoc header naming the phase/IMP). `src/cli/` and
  `src/bridge/` hold the two binaries' entry points. Custom `parseArgs`, no
  arg libraries.
- **Best-effort by design:** heartbeats, closing comments, streaming, config
  writes and lock release never throw; log with `console.warn`/empty catch.
  Only the API client propagates errors (`ApiError`), with `msg()` for logs.
- Locks (`~/.teamshare/locks/<agentId>.lock`) gate every session; use
  `acquireLock`/`releaseLock`; never bypass the wake queue.
- **Gates:** `npm run build` and `npm run typecheck` — `npm run lint` is
  broken (eslint is not installed), do not rely on it.

## Cross-repo rules

- Backend schema is canonical; mirrors are for UX. A stale mirror is a bug.
- No new dependencies without a reason; prefer Node built-ins / existing libs.
- Commit per repo, never cross-commit.

## Git workflow (CRITICAL - read before any git operations)

> **The root directory is NOT a git repository.** Running `git add`, `git commit`,
> or `git push` from the root will fail with "not a git repository" errors.

### Rules for git operations

1. **Always `cd` into the app folder before git commands.** Example:
   ```bash
   cd frontend && git add . && git commit -m "feat: add new component"
   ```

2. **When work crosses multiple repos, commit separately in each repo.** Example:
   ```bash
   # Backend changes
   cd teamshare-backend && git add . && git commit -m "feat: add API endpoint"

   # Frontend changes
   cd frontend && git add . && git commit -m "feat: consume new API"
   ```

3. **Never try to commit from the root directory.** It will fail.

4. **Use the `workdir` parameter in bash commands** to run git operations in the correct folder:
   ```bash
   git add .
   git commit -m "feat: description"
   ```
   with `workdir` set to the app folder (e.g., `frontend/`).

5. **Branch naming:** use `teamshare/<taskId8>` format for task branches.

6. **One commit per logical change** in each repo. Don't mix unrelated changes.

### Multi-repo structure

| Path | Git repo name | Notes |
|---|---|---|
| `frontend/` | `teamshare-frontend` | Next.js web app |
| `teamshare-backend/` | `teamshare-backend` | NestJS API |
| `teamshare-mobile-app/` | `teamshare-mobile-app` | Expo mobile app |
| `teamshare-bridge/` | `teamshare-bridge` | Agent bridge/CLI |

### Cross-repo workflow example

When a task requires changes in both backend and frontend:

```
1. Make backend changes in teamshare-backend/
2. cd teamshare-backend && git add . && git commit -m "feat: add X endpoint"
3. Make frontend changes in frontend/
4. cd frontend && git add . && git commit -m "feat: consume X endpoint"
5. Push each repo separately: git push origin teamshare/<branch>
```

## Pre-done checklist (all must pass)

- [ ] Backend: `npm run build` green; eslint clean on the files you touched.
- [ ] Backend: zod-first DTO + `ZodValidationPipe` on every new endpoint.
- [ ] Backend: envelope + pagination + access metadata on every endpoint.
- [ ] Frontend/mobile: imports only from `@/components/shared`; `TS*` used.
- [ ] Frontend/mobile: `npm run build` (web) / `npx expo export` (mobile) green.
- [ ] Bridge: `npm run build` + `npm run typecheck` green.
- [ ] No generated files hand-edited; no secrets committed.