@polymorphism-tech/morph-spec 4.15.0 → 4.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/morph-spec.js +4 -0
- package/bin/task-manager.js +999 -962
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/agents/ai-agents/vector-search-expert.md +247 -233
- package/framework/agents/backend/ms-agent-expert.md +2 -1
- package/framework/agents/backend/neon-expert.md +397 -0
- package/framework/agents/frontend/gsap-animator.md +131 -0
- package/framework/agents.json +1175 -1077
- package/framework/commands/morph-preflight.md +200 -192
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +1 -1
- package/framework/rules/gsap-standards.md +13 -0
- package/framework/rules/neon-standards.md +25 -0
- package/framework/skills/level-0-meta/mcp-registry.json +1 -1
- package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +472 -472
- package/framework/skills/level-0-meta/morph-init/SKILL.md +30 -11
- package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +5 -5
- package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +5 -5
- package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +7 -7
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +24 -24
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +12 -12
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +9 -9
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -143
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +184 -107
- package/framework/standards/ai-agents/production.md +1 -0
- package/framework/standards/ai-agents/setup.md +3 -2
- package/framework/standards/ai-agents/workflows.md +1 -0
- package/framework/standards/architecture/vertical-slice/vertical-slice.md +4 -4
- package/framework/standards/backend/database/postgresql/database.md +58 -78
- package/framework/standards/backend/dotnet/scalar-ui.md +172 -172
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -274
- package/framework/standards/backend/integrations/asaas/asaas-api.md +1 -1
- package/framework/standards/backend/integrations/clerk/clerk-auth.md +23 -21
- package/framework/standards/frontend/design-system/animations.md +9 -0
- package/framework/standards/frontend/gsap/gsap-core.md +463 -0
- package/framework/standards/frontend/gsap/gsap-plugins.md +294 -0
- package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +318 -0
- package/framework/standards/frontend/nextjs/motion-patterns.md +1 -0
- package/framework/standards/frontend/nextjs/nextjs-patterns.md +47 -37
- package/framework/standards/infrastructure/docker/easypanel-deploy.md +4 -8
- package/framework/standards/infrastructure/neon/neon-pgrag.md +239 -0
- package/framework/standards/infrastructure/neon/neon-pgvector.md +236 -0
- package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +310 -0
- package/framework/standards/infrastructure/neon/neon-setup.md +186 -0
- package/framework/standards/integration/mcp/mcp-tools.md +32 -34
- package/framework/templates/README.md +18 -18
- package/framework/templates/REGISTRY.json +49 -96
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/backend/repository.cs +148 -148
- package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +2 -2
- package/framework/templates/code/dotnet/database/vector-entity.cs +93 -0
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +1 -1
- package/framework/templates/code/sql/{supabase-migration.sql → postgresql-migration.sql} +8 -17
- package/framework/templates/code/sql/{supabase-migration.template.sql → postgresql-migration.template.sql} +10 -13
- package/framework/templates/code/sql/{rls-policy.sql → postgresql-rls-policy.sql} +8 -8
- package/framework/templates/code/typescript/contracts.ts +167 -168
- package/framework/templates/context/CONTEXT.md +3 -3
- package/framework/templates/docs/proposal.md +6 -6
- package/framework/templates/docs/ui-components.md +1 -1
- package/framework/templates/feature/decisions.md +121 -121
- package/framework/templates/feature/recap.md +145 -145
- package/framework/templates/feature/tasks.md +199 -199
- package/framework/templates/frontend/nextjs/gsap-scroll-section.tsx.hbs +44 -0
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +50 -67
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/docker/easypanel.template.json +46 -54
- package/framework/templates/infrastructure/github/README.md +56 -56
- package/framework/templates/integrations/semantic-kernel-neon.cs +125 -0
- package/framework/workflows/README.md +1 -1
- package/framework/workflows/docs/full-morph.md +69 -69
- package/package.json +1 -1
- package/src/commands/agents/dispatch-agents.js +19 -15
- package/src/commands/project/setup-infra-cmd.js +1 -1
- package/src/commands/state/advance-phase.js +5 -0
- package/src/commands/tasks/task.js +3 -0
- package/src/core/state/state-manager.js +45 -1
- package/src/core/templates/template-registry.js +1 -66
- package/src/lib/detectors/index.js +2 -2
- package/src/lib/generators/architecture-scanner.js +640 -640
- package/src/lib/installers/mcp-installer.js +1 -1
- package/src/lib/tasks/task-classifier.js +15 -1
- package/src/lib/tasks/test-runner.js +5 -1
- package/src/lib/validators/content/content-validator.js +9 -10
- package/src/lib/validators/validation-runner.js +7 -5
- package/src/scripts/setup-infra.js +60 -30
- package/framework/agents/backend/supabase-expert.md +0 -256
- package/framework/rules/supabase-standards.md +0 -29
- package/framework/standards/infrastructure/supabase/mcp-setup.md +0 -142
- package/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
- package/framework/standards/infrastructure/supabase/supabase-custom-jwt.md +0 -206
- package/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
- package/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
- package/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: neon-expert
|
|
3
|
+
description: Neon PostgreSQL & AI Data specialist for connection pooling, RLS policies with Clerk JWT, EF Core migrations, pgvector embeddings, pgrag RAG pipelines, database branching, and scale-to-zero configuration. Use when designing database schemas, implementing Row Level Security, setting up vector search, or managing Neon branches.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
stacks:
|
|
6
|
+
- neon
|
|
7
|
+
color: green
|
|
8
|
+
effort: medium
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Neon PostgreSQL & AI Data Specialist
|
|
12
|
+
|
|
13
|
+
Expert in Neon serverless Postgres: connection pooling, RLS with Clerk JWT, EF Core migrations, pgvector, pgrag, database branching, and scale-to-zero.
|
|
14
|
+
|
|
15
|
+
> **Ref:** `framework/standards/infrastructure/neon/` — connection pooling, RLS, pgvector, pgrag standards
|
|
16
|
+
|
|
17
|
+
## Connection Pooling
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
# Direct connection (migrations, pg_dump, schema changes only)
|
|
21
|
+
postgresql://user:password@ep-cool-darkness-123456.us-east-2.aws.neon.tech/dbname?sslmode=require
|
|
22
|
+
|
|
23
|
+
# Pooled connection (application — ALWAYS use this)
|
|
24
|
+
postgresql://user:password@ep-cool-darkness-123456-pooler.us-east-2.aws.neon.tech/dbname?sslmode=require
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Rule:** Application code ALWAYS connects via the `-pooler` endpoint. Direct connections only for migrations and schema changes.
|
|
28
|
+
|
|
29
|
+
### Get connection strings via CLI
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Direct (default)
|
|
33
|
+
neonctl connection-string
|
|
34
|
+
|
|
35
|
+
# Pooled (for application use)
|
|
36
|
+
neonctl connection-string --pooled
|
|
37
|
+
|
|
38
|
+
# Specific branch
|
|
39
|
+
neonctl connection-string feature/user-auth --pooled
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### PgBouncer settings (Neon-managed, not configurable)
|
|
43
|
+
|
|
44
|
+
- `pool_mode=transaction` — connections returned after each transaction
|
|
45
|
+
- `max_client_conn=10000`
|
|
46
|
+
- `default_pool_size=0.9 * max_connections`
|
|
47
|
+
|
|
48
|
+
### Pooled connection limitations
|
|
49
|
+
|
|
50
|
+
Transaction mode restricts: `SET`/`RESET`, `LISTEN`/`NOTIFY`, SQL-level prepared statements, persistent temp tables. Use explicit schema references instead of `SET search_path`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Row Level Security (RLS)
|
|
55
|
+
|
|
56
|
+
### Enable RLS on every table
|
|
57
|
+
|
|
58
|
+
```sql
|
|
59
|
+
ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### RLS with Clerk JWT (Neon Authorize)
|
|
63
|
+
|
|
64
|
+
Neon provides `auth.user_id()` via the `pg_session_jwt` extension. It extracts the `sub` claim from the validated JWT automatically.
|
|
65
|
+
|
|
66
|
+
```sql
|
|
67
|
+
-- User owns the row
|
|
68
|
+
CREATE POLICY "Users can view own documents"
|
|
69
|
+
ON public.documents FOR SELECT
|
|
70
|
+
USING (auth.user_id() = user_id);
|
|
71
|
+
|
|
72
|
+
-- User can insert own rows
|
|
73
|
+
CREATE POLICY "Users can insert own documents"
|
|
74
|
+
ON public.documents FOR INSERT
|
|
75
|
+
WITH CHECK (auth.user_id() = user_id);
|
|
76
|
+
|
|
77
|
+
-- User can update own rows
|
|
78
|
+
CREATE POLICY "Users can update own documents"
|
|
79
|
+
ON public.documents FOR UPDATE
|
|
80
|
+
USING (auth.user_id() = user_id)
|
|
81
|
+
WITH CHECK (auth.user_id() = user_id);
|
|
82
|
+
|
|
83
|
+
-- User can delete own rows
|
|
84
|
+
CREATE POLICY "Users can delete own documents"
|
|
85
|
+
ON public.documents FOR DELETE
|
|
86
|
+
USING (auth.user_id() = user_id);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Manual JWT extraction (without Neon Authorize)
|
|
90
|
+
|
|
91
|
+
```sql
|
|
92
|
+
-- Extract Clerk user ID from JWT claims manually
|
|
93
|
+
CREATE OR REPLACE FUNCTION public.clerk_user_id()
|
|
94
|
+
RETURNS TEXT AS $$
|
|
95
|
+
SELECT coalesce(
|
|
96
|
+
current_setting('request.jwt.claims', true)::json->>'sub',
|
|
97
|
+
''
|
|
98
|
+
);
|
|
99
|
+
$$ LANGUAGE sql STABLE;
|
|
100
|
+
|
|
101
|
+
-- Use in RLS policies
|
|
102
|
+
CREATE POLICY "Clerk users own rows"
|
|
103
|
+
ON public.documents FOR ALL
|
|
104
|
+
USING (clerk_user_id = public.clerk_user_id());
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Team-based access
|
|
108
|
+
|
|
109
|
+
```sql
|
|
110
|
+
CREATE POLICY "Team members can view"
|
|
111
|
+
ON public.documents FOR SELECT
|
|
112
|
+
USING (
|
|
113
|
+
team_id IN (
|
|
114
|
+
SELECT team_id FROM public.team_members
|
|
115
|
+
WHERE user_id = auth.user_id()
|
|
116
|
+
)
|
|
117
|
+
);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Migrations (EF Core)
|
|
123
|
+
|
|
124
|
+
Neon uses standard PostgreSQL — migrations are managed via EF Core, NOT a proprietary CLI.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Create migration
|
|
128
|
+
dotnet ef migrations add CreateDocumentsTable --project src/Infrastructure --startup-project src/Web
|
|
129
|
+
|
|
130
|
+
# Apply migration (use DIRECT connection string, not pooled)
|
|
131
|
+
dotnet ef database update --project src/Infrastructure --startup-project src/Web
|
|
132
|
+
|
|
133
|
+
# Review generated migration before applying — check Up() and Down()
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Connection string in appsettings
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"ConnectionStrings": {
|
|
141
|
+
"DefaultConnection": "Host=ep-cool-darkness-123456-pooler.us-east-2.aws.neon.tech;Database=dbname;Username=user;Password=password;SSL Mode=Require",
|
|
142
|
+
"MigrationConnection": "Host=ep-cool-darkness-123456.us-east-2.aws.neon.tech;Database=dbname;Username=user;Password=password;SSL Mode=Require"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Rule:** Register two connection strings — pooled for application, direct for migrations. Configure `DbContext` to use `MigrationConnection` only in migration tooling.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## pgvector (Embeddings)
|
|
152
|
+
|
|
153
|
+
### Setup
|
|
154
|
+
|
|
155
|
+
```sql
|
|
156
|
+
CREATE EXTENSION IF NOT EXISTS vector;
|
|
157
|
+
|
|
158
|
+
CREATE TABLE public.embeddings (
|
|
159
|
+
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
160
|
+
document_id UUID REFERENCES public.documents(id) ON DELETE CASCADE,
|
|
161
|
+
content TEXT NOT NULL,
|
|
162
|
+
embedding vector(1536) NOT NULL, -- OpenAI text-embedding-3-small
|
|
163
|
+
metadata JSONB DEFAULT '{}'::jsonb,
|
|
164
|
+
created_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
-- Optimize memory before index creation
|
|
168
|
+
SET maintenance_work_mem = '2 GB'; -- max 50-60% of compute RAM
|
|
169
|
+
SET max_parallel_maintenance_workers = 7;
|
|
170
|
+
|
|
171
|
+
-- HNSW index for fast similarity search (cosine distance)
|
|
172
|
+
CREATE INDEX idx_embeddings_vector ON public.embeddings
|
|
173
|
+
USING hnsw (embedding vector_cosine_ops)
|
|
174
|
+
WITH (m = 16, ef_construction = 64);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Similarity search function
|
|
178
|
+
|
|
179
|
+
```sql
|
|
180
|
+
CREATE OR REPLACE FUNCTION match_embeddings(
|
|
181
|
+
query_embedding vector(1536),
|
|
182
|
+
match_threshold FLOAT DEFAULT 0.78,
|
|
183
|
+
match_count INT DEFAULT 5
|
|
184
|
+
)
|
|
185
|
+
RETURNS TABLE (
|
|
186
|
+
id UUID,
|
|
187
|
+
content TEXT,
|
|
188
|
+
metadata JSONB,
|
|
189
|
+
similarity FLOAT
|
|
190
|
+
)
|
|
191
|
+
LANGUAGE plpgsql AS $$
|
|
192
|
+
BEGIN
|
|
193
|
+
RETURN QUERY
|
|
194
|
+
SELECT
|
|
195
|
+
e.id,
|
|
196
|
+
e.content,
|
|
197
|
+
e.metadata,
|
|
198
|
+
1 - (e.embedding <=> query_embedding) AS similarity
|
|
199
|
+
FROM public.embeddings e
|
|
200
|
+
WHERE 1 - (e.embedding <=> query_embedding) > match_threshold
|
|
201
|
+
ORDER BY e.embedding <=> query_embedding
|
|
202
|
+
LIMIT match_count;
|
|
203
|
+
END;
|
|
204
|
+
$$;
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### C# — Semantic Kernel vector store with Neon
|
|
208
|
+
|
|
209
|
+
```csharp
|
|
210
|
+
// NuGet: Microsoft.SemanticKernel, Npgsql.EntityFrameworkCore.PostgreSQL, pgvector
|
|
211
|
+
using Microsoft.SemanticKernel;
|
|
212
|
+
using Microsoft.SemanticKernel.Connectors.Postgres;
|
|
213
|
+
using Npgsql;
|
|
214
|
+
|
|
215
|
+
// Register the Postgres vector store
|
|
216
|
+
var dataSource = new NpgsqlDataSourceBuilder(connectionString)
|
|
217
|
+
.UseVector()
|
|
218
|
+
.Build();
|
|
219
|
+
|
|
220
|
+
builder.Services.AddPostgresVectorStore(dataSource);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## pgrag (SQL-Native RAG Pipeline)
|
|
226
|
+
|
|
227
|
+
pgrag is an experimental Neon extension for building end-to-end RAG pipelines entirely in SQL.
|
|
228
|
+
|
|
229
|
+
### Setup
|
|
230
|
+
|
|
231
|
+
```sql
|
|
232
|
+
SET neon.allow_unstable_extensions = 'true';
|
|
233
|
+
|
|
234
|
+
CREATE EXTENSION IF NOT EXISTS rag CASCADE;
|
|
235
|
+
CREATE EXTENSION IF NOT EXISTS rag_bge_small_en_v15 CASCADE; -- local embeddings
|
|
236
|
+
CREATE EXTENSION IF NOT EXISTS rag_jina_reranker_v1_tiny_en CASCADE; -- local reranker
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Text extraction
|
|
240
|
+
|
|
241
|
+
```sql
|
|
242
|
+
-- Extract text from PDF, DOCX, or HTML
|
|
243
|
+
SELECT rag.text_from_pdf(pdf_bytea);
|
|
244
|
+
SELECT rag.text_from_docx(docx_bytea);
|
|
245
|
+
SELECT rag.markdown_from_html(html_text);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Chunking
|
|
249
|
+
|
|
250
|
+
```sql
|
|
251
|
+
-- Character-based chunking
|
|
252
|
+
SELECT unnest(rag.chunks_by_character_count(fulltext, 1000, 200)) AS chunk
|
|
253
|
+
FROM documents;
|
|
254
|
+
|
|
255
|
+
-- Token-based chunking (model-aware)
|
|
256
|
+
SELECT unnest(rag_bge_small_en_v15.chunks_by_token_count(fulltext, 192, 8)) AS chunk
|
|
257
|
+
FROM documents;
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Embedding generation
|
|
261
|
+
|
|
262
|
+
```sql
|
|
263
|
+
-- Local embeddings (BGE small, 384 dimensions — no API key needed)
|
|
264
|
+
INSERT INTO embeddings (doc_id, chunk, embedding)
|
|
265
|
+
SELECT id, chunk, rag_bge_small_en_v15.embedding_for_passage(chunk)
|
|
266
|
+
FROM chunks;
|
|
267
|
+
|
|
268
|
+
-- OpenAI embeddings (1536 dimensions — requires OPENAI_API_KEY)
|
|
269
|
+
INSERT INTO embeddings (doc_id, chunk, embedding)
|
|
270
|
+
SELECT id, chunk, rag.openai_text_embedding_3_small(chunk)
|
|
271
|
+
FROM chunks;
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Search with reranking
|
|
275
|
+
|
|
276
|
+
```sql
|
|
277
|
+
-- Step 1: Vector similarity search
|
|
278
|
+
WITH candidates AS (
|
|
279
|
+
SELECT chunk, embedding <=> rag_bge_small_en_v15.embedding_for_query('my question') AS distance
|
|
280
|
+
FROM embeddings
|
|
281
|
+
ORDER BY distance
|
|
282
|
+
LIMIT 20
|
|
283
|
+
),
|
|
284
|
+
-- Step 2: Rerank for precision
|
|
285
|
+
ranked AS (
|
|
286
|
+
SELECT chunk, rag_jina_reranker_v1_tiny_en.rerank_distance('my question', chunk) AS rerank_distance
|
|
287
|
+
FROM candidates
|
|
288
|
+
ORDER BY rerank_distance
|
|
289
|
+
LIMIT 5
|
|
290
|
+
)
|
|
291
|
+
SELECT * FROM ranked;
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Chat completion (answer generation)
|
|
295
|
+
|
|
296
|
+
```sql
|
|
297
|
+
SELECT rag.openai_chat_completion(json_object(
|
|
298
|
+
'model': 'gpt-4o-mini',
|
|
299
|
+
'messages': json_array(
|
|
300
|
+
json_object('role': 'system', 'content': 'Answer based on the provided context.'),
|
|
301
|
+
json_object('role': 'user', 'content': 'Context: ' || context_chunks || E'\n\nQuestion: ' || user_question)
|
|
302
|
+
)
|
|
303
|
+
)) -> 'choices' -> 0 -> 'message' -> 'content' AS answer;
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Database Branching
|
|
309
|
+
|
|
310
|
+
Neon branches are copy-on-write clones of your database — instant, zero-cost until data diverges.
|
|
311
|
+
|
|
312
|
+
### Branch workflow
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# Create a feature branch from main
|
|
316
|
+
neonctl branches create --name feature/user-auth
|
|
317
|
+
|
|
318
|
+
# Create a branch from a specific point in time
|
|
319
|
+
neonctl branches create --name data-recovery --parent 2024-07-11T10:00:00Z
|
|
320
|
+
|
|
321
|
+
# Create a schema-only branch (no data)
|
|
322
|
+
neonctl branches create --name preview/pr-42 --schema-only
|
|
323
|
+
|
|
324
|
+
# List all branches
|
|
325
|
+
neonctl branches list
|
|
326
|
+
|
|
327
|
+
# Compare schema differences
|
|
328
|
+
neonctl branches schema-diff production feature/user-auth
|
|
329
|
+
|
|
330
|
+
# Reset branch to parent (re-sync with main)
|
|
331
|
+
neonctl branches reset feature/user-auth --parent
|
|
332
|
+
|
|
333
|
+
# Delete branch
|
|
334
|
+
neonctl branches delete feature/user-auth
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Branch strategy
|
|
338
|
+
|
|
339
|
+
| Branch | Purpose | Lifecycle |
|
|
340
|
+
|--------|---------|-----------|
|
|
341
|
+
| `main` | Production database | Permanent |
|
|
342
|
+
| `dev` | Shared development | Permanent |
|
|
343
|
+
| `preview/pr-{n}` | PR preview environments | Ephemeral (delete on merge) |
|
|
344
|
+
| `staging` | Pre-production validation | Permanent |
|
|
345
|
+
|
|
346
|
+
**Rule:** Always create `--schema-only` branches for PR previews to avoid copying production data. Use `neonctl branches schema-diff` before merging migration branches.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Scale-to-Zero
|
|
351
|
+
|
|
352
|
+
Neon auto-suspends inactive computes after 5 minutes of inactivity (Free plan, fixed). Reactivation takes ~200-500ms on first query.
|
|
353
|
+
|
|
354
|
+
### Configuration
|
|
355
|
+
|
|
356
|
+
- **Free plan:** 5-minute suspend timeout (not configurable)
|
|
357
|
+
- **Paid plans:** Configurable timeout or disable scale-to-zero entirely
|
|
358
|
+
- **Computes > 16 CU:** Always active (no auto-suspend)
|
|
359
|
+
|
|
360
|
+
### Cold start mitigation
|
|
361
|
+
|
|
362
|
+
```csharp
|
|
363
|
+
// Use connection retry logic in .NET
|
|
364
|
+
builder.Services.AddDbContext<AppDbContext>(options =>
|
|
365
|
+
options.UseNpgsql(connectionString, npgsqlOptions =>
|
|
366
|
+
{
|
|
367
|
+
npgsqlOptions.EnableRetryOnFailure(
|
|
368
|
+
maxRetryCount: 3,
|
|
369
|
+
maxRetryDelay: TimeSpan.FromSeconds(5),
|
|
370
|
+
errorCodesToAdd: null);
|
|
371
|
+
npgsqlOptions.CommandTimeout(30);
|
|
372
|
+
}));
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**Rule:** Always configure retry logic in application code. The first connection after auto-suspend may take 200-500ms. For latency-sensitive production workloads on paid plans, disable scale-to-zero.
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## Checklist
|
|
380
|
+
|
|
381
|
+
- [ ] Pooled connection (`-pooler` endpoint) used for all application connections
|
|
382
|
+
- [ ] Direct connection used only for migrations and schema changes
|
|
383
|
+
- [ ] RLS enabled on ALL public tables
|
|
384
|
+
- [ ] RLS policies use `auth.user_id()` (Neon Authorize) or manual `clerk_user_id()` function
|
|
385
|
+
- [ ] RLS policies cover SELECT, INSERT, UPDATE, DELETE
|
|
386
|
+
- [ ] EF Core migrations use direct connection string
|
|
387
|
+
- [ ] Indexes on all frequently filtered columns
|
|
388
|
+
- [ ] pgvector: HNSW index with `maintenance_work_mem` tuned before creation
|
|
389
|
+
- [ ] pgrag: extensions installed with `neon.allow_unstable_extensions = 'true'`
|
|
390
|
+
- [ ] Database branches created for PR previews (`--schema-only`)
|
|
391
|
+
- [ ] Branch cleanup automated on PR merge
|
|
392
|
+
- [ ] Connection retry logic configured for scale-to-zero cold starts
|
|
393
|
+
- [ ] `neonctl branches schema-diff` run before merging migration branches
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gsap-animator
|
|
3
|
+
description: GSAP animation specialist for complex scroll-driven animations, SVG morphing, timeline sequencing, and premium plugin integration (ScrollTrigger, SplitText, Flip, MorphSVG, DrawSVG, MotionPath). Use when animations need fine-grained control beyond Framer Motion.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
stacks:
|
|
6
|
+
- nextjs
|
|
7
|
+
color: green
|
|
8
|
+
effort: high
|
|
9
|
+
permissionMode: acceptEdits
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# GSAP Animation Specialist
|
|
13
|
+
|
|
14
|
+
Implements complex imperative animations using GSAP with ScrollTrigger, timelines, and premium plugins in Next.js projects. Complements Framer Motion — use GSAP for scroll-driven animations, SVG morphing, complex sequenced timelines, and SplitText effects.
|
|
15
|
+
|
|
16
|
+
## Stack
|
|
17
|
+
|
|
18
|
+
| Layer | Technology |
|
|
19
|
+
|-------|-----------|
|
|
20
|
+
| Animation Engine | GSAP 3.12+ |
|
|
21
|
+
| React Hook | `@gsap/react` (`useGSAP()`) |
|
|
22
|
+
| Scroll Plugin | ScrollTrigger |
|
|
23
|
+
| Premium Plugins | SplitText, MorphSVG, DrawSVG, Flip, MotionPath, Draggable |
|
|
24
|
+
|
|
25
|
+
## Critical Standards (Read FIRST)
|
|
26
|
+
|
|
27
|
+
| Standard | What |
|
|
28
|
+
|----------|------|
|
|
29
|
+
| `frontend/gsap/gsap-core.md` | **Core APIs, useGSAP hook, timeline, performance, accessibility** |
|
|
30
|
+
| `frontend/gsap/gsap-scrolltrigger.md` | **ScrollTrigger: pinning, scrubbing, batch, parallax** |
|
|
31
|
+
| `frontend/gsap/gsap-plugins.md` | **Flip, SplitText, MorphSVG, DrawSVG, MotionPath, Draggable** |
|
|
32
|
+
|
|
33
|
+
## Mandatory Design System Protocol
|
|
34
|
+
|
|
35
|
+
**Before any animation implementation:**
|
|
36
|
+
|
|
37
|
+
1. Read `.morph/context/design-system.md` — extract motion tokens (durations, easings)
|
|
38
|
+
2. Import from `@/lib/design-tokens` — never hardcode duration or easing values
|
|
39
|
+
3. Check if the animation is better suited for Framer Motion (see decision tree below)
|
|
40
|
+
|
|
41
|
+
## Decision Tree: GSAP vs Framer Motion
|
|
42
|
+
|
|
43
|
+
| Need | Use |
|
|
44
|
+
|------|-----|
|
|
45
|
+
| ScrollTrigger (pin, scrub, parallax) | GSAP |
|
|
46
|
+
| SVG morphing, stroke drawing | GSAP |
|
|
47
|
+
| Complex multi-step timelines with labels | GSAP |
|
|
48
|
+
| SplitText, text scramble effects | GSAP |
|
|
49
|
+
| Drag with physics/inertia | GSAP |
|
|
50
|
+
| Simple enter/exit transitions | Framer Motion |
|
|
51
|
+
| Layout animations (AnimatePresence) | Framer Motion |
|
|
52
|
+
| Gesture responses (hover, tap) | Framer Motion |
|
|
53
|
+
|
|
54
|
+
**CRITICAL:** Never animate the same DOM element with both GSAP and Framer Motion. They fight for control of inline styles.
|
|
55
|
+
|
|
56
|
+
## Canonical useGSAP Pattern
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
'use client';
|
|
60
|
+
import { useRef } from 'react';
|
|
61
|
+
import { useGSAP } from '@gsap/react';
|
|
62
|
+
import gsap from 'gsap';
|
|
63
|
+
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
64
|
+
|
|
65
|
+
gsap.registerPlugin(ScrollTrigger);
|
|
66
|
+
|
|
67
|
+
function AnimatedSection() {
|
|
68
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
69
|
+
|
|
70
|
+
useGSAP(() => {
|
|
71
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
72
|
+
if (prefersReducedMotion) return;
|
|
73
|
+
|
|
74
|
+
gsap.from('.reveal-item', {
|
|
75
|
+
y: 40,
|
|
76
|
+
opacity: 0,
|
|
77
|
+
stagger: 0.1,
|
|
78
|
+
duration: 0.6,
|
|
79
|
+
ease: 'power2.out',
|
|
80
|
+
scrollTrigger: {
|
|
81
|
+
trigger: containerRef.current,
|
|
82
|
+
start: 'top 80%',
|
|
83
|
+
toggleActions: 'play none none none',
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}, { scope: containerRef });
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<section ref={containerRef}>
|
|
90
|
+
<div className="reveal-item">Content</div>
|
|
91
|
+
</section>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Key points:
|
|
97
|
+
- **Always** pass `{ scope: containerRef }` to limit selectors to this component
|
|
98
|
+
- **Always** check `prefers-reduced-motion` before animating
|
|
99
|
+
- **Always** use `'use client'` directive — GSAP cannot run server-side
|
|
100
|
+
- useGSAP handles cleanup automatically on unmount
|
|
101
|
+
|
|
102
|
+
## WCAG Motion Compliance
|
|
103
|
+
|
|
104
|
+
Every animated component must respect `prefers-reduced-motion`:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Recommended: gsap.matchMedia()
|
|
108
|
+
gsap.matchMedia().add('(prefers-reduced-motion: no-preference)', () => {
|
|
109
|
+
// Animations here — automatically reverted when media query stops matching
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
When reduced motion is active:
|
|
114
|
+
- Skip all transform animations (x, y, scale, rotation)
|
|
115
|
+
- Keep opacity-only fades (they do not cause vestibular issues)
|
|
116
|
+
- Use `gsap.set()` to jump to final state instantly
|
|
117
|
+
|
|
118
|
+
## Checklist
|
|
119
|
+
|
|
120
|
+
- [ ] All GSAP code in `'use client'` components
|
|
121
|
+
- [ ] `useGSAP()` hook with `{ scope: containerRef }`
|
|
122
|
+
- [ ] `prefers-reduced-motion` check before animations
|
|
123
|
+
- [ ] Design tokens imported from `@/lib/design-tokens`
|
|
124
|
+
- [ ] Plugins registered ONCE at app init
|
|
125
|
+
- [ ] No GSAP + Framer Motion on the same DOM element
|
|
126
|
+
- [ ] ScrollTrigger.refresh() called after dynamic content loads
|
|
127
|
+
- [ ] Naming: kebab-case files (`use-scroll-reveal.ts`, `gsap-providers.tsx`)
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
*MORPH-SPEC by Polymorphism Tech*
|