Skip to content

Commit 1e30f43

Browse files
auge2uclaude
andcommitted
docs: rewrite CLAUDE.md with critical patterns and plugin schema rules
Synced from internal repo with public scrub applied. Added: Neon RLS transaction requirement, schema split, Tailwind v4 @theme pattern, plugin schema rules, updated stack versions and repo structure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9888bbc commit 1e30f43

1 file changed

Lines changed: 73 additions & 38 deletions

File tree

CLAUDE.md

Lines changed: 73 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
# CLAUDE.md — webplatform4sync
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
24

35
## Repository Purpose
46

5-
Internal platform standards, skills, and scaffold templates for all SyncUpSuite projects. This repo defines **the standard** that every project — greenfield or brownfield — aligns to.
7+
Platform standards, skills, and scaffold templates for all SyncUpSuite projects. This repo defines **the standard** that every project — greenfield or brownfield — aligns to.
68

79
**Org**: `syncupsuite`
8-
****Repo**: `syncupsuite/webplatform4sync`
10+
**Repo**: `syncupsuite/webplatform4sync`
911

1012
---
1113

@@ -25,19 +27,21 @@ Simple projects use the same architecture with dormant tiers (hardcoded `tenant_
2527

2628
## Standard Stack
2729

30+
Source of truth: `shared/conventions/stack.md` — always check there for locked versions.
31+
2832
| Component | Technology | Version |
2933
|-----------|-----------|---------|
3034
| UI Framework | React | ^19.2 |
31-
| Language | TypeScript | ^5.9 |
35+
| Language | TypeScript | ^5.9 (strict mode) |
3236
| Styling | Tailwind CSS | ^4.1 (CSS-first `@theme`) |
3337
| Build | Vite | ^7.0 |
3438
| Edge Runtime | Cloudflare Workers | wrangler ^4.x |
3539
| Database | Neon PostgreSQL | Serverless driver + Hyperdrive |
3640
| ORM | Drizzle ORM | ^0.45 |
3741
| Auth (Sessions) | Better Auth | ^1.4 (`neon_auth` schema) |
3842
| Auth (Identity) | Firebase / Google Identity Platform | europe-west6 |
39-
| Design Tokens | Style Dictionary | W3C DTCG aligned |
40-
| Routing | React Router | ^7.13 (unified package) |
43+
| Design Tokens | @syncupsuite/themes | ^0.4.0 (12 themes, Semantic Color API) |
44+
| Routing | React Router | ^7.13 (unified `react-router` package) |
4145
| Analytics | PostHog | posthog-js ^1.x + reverse proxy |
4246

4347
---
@@ -53,75 +57,106 @@ skills/ # Claude Code skills (abstract, universal)
5357
5458
scaffold/ # Project scaffolding templates
5559
├── greenfield/ # New project from scratch
60+
│ └── base/ # Canonical project template (src/, styles/, db/, server/)
5661
├── brownfield/ # Migration to standards
5762
└── overlay/ # Token/theme system only
5863
5964
shared/ # Shared conventions, contracts, and validation
60-
├── contracts/ # Canonical types and constants (cross-skill)
61-
├── conventions/ # Naming, stack versions, deployment
65+
├── contracts/ # Canonical types and constants (auth.ts, tenant.ts, tokens.ts, constants.ts, env.ts)
66+
├── conventions/ # stack.md (versions), naming.md, deployment.md, analytics.md
6267
└── validation/ # Token and tenant validators
6368
69+
commands/ # Claude Code command files (.md)
70+
frames/ # Command frames (construction, shuhari)
71+
.claude-plugin/ # Plugin manifest (plugin.json, marketplace.json)
6472
docs/ # Canonical documentation
6573
```
6674

6775
---
6876

69-
## Naming Convention
77+
## Critical Patterns
78+
79+
### Neon RLS Tenant Isolation
7080

81+
Neon's serverless HTTP driver executes each query as a separate HTTP request. `set_config('app.tenant_id', ...)` **must** be in the same Drizzle transaction as the data queries — otherwise the config is lost.
82+
83+
**Correct pattern** (in `skills/neon-multi-tenant/templates/drizzle-tenant.ts`):
84+
```typescript
85+
// tenantQuery() wraps set_config + queries in a single transaction
86+
const results = await tenantQuery(db, tenantId, async (tx) => {
87+
return tx.select().from(items);
88+
});
7189
```
72-
repo name = domain name = Google project ID
90+
91+
### Schema Split
92+
93+
The greenfield scaffold uses two Drizzle schemas:
94+
- `platformSchema` (`platform`) — tenant infrastructure: tenants, domain_mappings, tenant_relationships
95+
- `appSchema` (`{{SCHEMA_NAME}}`) — application-domain tables
96+
97+
Both must be in `drizzle.config.ts` `schemaFilter`.
98+
99+
### Auth Graduation
100+
101+
Auth is not binary — projects support graduated access:
102+
103+
```
104+
Anonymous → Preview/Inquiry → OAuth (Google/GitHub) → Full Account (Better Auth + Firebase)
73105
```
74106

75-
Example: `brandsyncup-com``brandsyncup.com` → GCP project `brandsyncup-com`
107+
Firebase provides identity. Better Auth provides sessions, RBAC, and tenant-scoped authorization in Neon. See `shared/contracts/auth.ts` for the `AuthLevel` enum and discriminated union types.
108+
109+
### Tailwind v4 CSS-first
76110

77-
Google project IDs: max 30 chars, lowercase, hyphens only. If the domain exceeds 30 chars, use `{product}-{tld}` pattern.
111+
Tailwind v4 uses `@theme` blocks in CSS (no `tailwind.config.js`). Self-referential `var()` inside `@theme` is the standard registration pattern — not a bug:
112+
```css
113+
@theme {
114+
--color-primary: var(--color-primary); /* registers :root value as Tailwind token */
115+
}
116+
```
117+
118+
Dark mode uses `[data-theme="dark"]` selector (class strategy), not `@media (prefers-color-scheme)`.
78119

79120
---
80121

81-
## Scaffold Flow
122+
## Plugin Schema Rules
82123

83-
Three paths based on project state:
124+
When editing `.claude-plugin/plugin.json`:
125+
- Only flat fields: `name`, `version`, `description`, `commands` (path string), `skills` (path string), `agents`, `hooks`, `mcpServers`, `outputStyles`, `lspServers`
126+
- No custom nested objects — causes "invalid input" errors
84127

85-
| Template | When | What You Get |
86-
|----------|------|-------------|
87-
| **greenfield** | New project, new domain | Full 3-tier scaffold from scratch |
88-
| **brownfield** | Existing project | Migration guide + incremental adoption |
89-
| **overlay** | Adding design system only | Token pipeline, no infra changes |
128+
When editing `.claude-plugin/marketplace.json`:
129+
- Plugin `source` must be `"./"` for local plugins — not `"npm:package-name"` string format
130+
- `@syncupsuite/themes` is an npm package, not a Claude Code plugin — don't list it in marketplace.json
90131

91132
---
92133

93-
## Auth Graduation Model
94-
95-
Auth is not binary. Projects support graduated access:
134+
## Naming Convention
96135

97136
```
98-
Anonymous → Preview/Inquiry → OAuth (Google/GitHub) → Full Account (Better Auth + Firebase)
137+
repo name = domain name = Google project ID
99138
```
100139

101-
Firebase provides identity (Google Identity Platform, email delivery, `auth.domain.tld`).
102-
Better Auth provides sessions, RBAC, and tenant-scoped authorization in Neon.
103-
104-
---
105-
106-
## Key Relationships
140+
Example: `brandsyncup-com``brandsyncup.com` → GCP project `brandsyncup-com`
107141

108-
- **BrandSyncUp** (`brandsyncup.com`): Reference implementation of this standard
109-
- **LegalSyncUp** (`legalsyncup.com`): Loosely coupled partner, shared auth infrastructure
110-
- **SyncUpSuite**: Umbrella org, eventual public marketplace
142+
Google project IDs: max 30 chars, lowercase, hyphens only.
111143

112144
---
113145

114146
## Working with This Repo
115147

148+
- No build commands — this repo is templates and patterns only
116149
- Skills are standalone — each has a `skill.md` entry point
117-
- Scaffold templates are concrete files, not abstractions
150+
- Scaffold templates are concrete files with `{{PLACEHOLDER}}` tokens
118151
- `shared/conventions/stack.md` is the source of truth for dependency versions
119-
- Changes to skills should be validated against at least one existing project (BrandSyncUp or LegalSyncUp)
152+
- Changes to skills should be validated against BrandSyncUp or LegalSyncUp
153+
- No secrets — Doppler references are placeholders showing _where_ secrets go
120154

121155
---
122156

123-
## Security
157+
## Key Relationships
124158

125-
- No secrets in this repo — it's templates and patterns only
126-
- Doppler references are placeholders showing _where_ secrets go
127-
- Firebase/Neon/Cloudflare credentials are per-project, never shared here
159+
- **BrandSyncUp** (`brandsyncup.com`): Reference implementation of this standard
160+
- **LegalSyncUp** (`legalsyncup.com`): Loosely coupled partner, shared auth infrastructure
161+
- **@syncupsuite/themes**: npm package with 12 culturally-grounded themes (separate `themes/` repo)
162+
- **SyncUpSuite**: Umbrella org, public marketplace

0 commit comments

Comments
 (0)