@riligar/agents-kit 1.16.0 → 1.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.
@@ -104,10 +104,3 @@ Ao pedir código ou design para uma IA, use este formato:
104
104
  - **Modais:** Devem ter um backdrop com blur (`backdrop-blur-sm`) e fundo branco sólido. Sem cabeçalhos coloridos.
105
105
  - **Dashboards:** Devem privilegiar números grandes (Big Numbers) em monocromia, com rótulos pequenos abaixo. Gráficos devem ser limpos, sem grid lines pesadas.
106
106
 
107
- ---
108
-
109
- ## 🤖 Integração com Gemini CLI
110
-
111
- Este repositório possui uma **Skill do Gemini CLI** configurada em [`riligar-design-system/SKILL.md`](../SKILL.md). Ao usar o Gemini CLI neste repositório, o agente aplicará automaticamente estas diretrizes a qualquer código ou design gerado.
112
-
113
- Para saber como usar, veja o [README principal](../../README.md).
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: riligar-dev-database
3
+ description: Database patterns for RiLiGar using Drizzle ORM + bun:sqlite. Use when setting up database connections, defining schemas, creating migrations, or writing queries. Covers SQLite on Fly.io volumes with the drizzle-kit workflow.
4
+ ---
5
+
6
+ # Database — Drizzle + bun:sqlite
7
+
8
+ > SQLite nativo no Bun. Zero drivers externos. Base de dados no volume do Fly.io (`/app/data`).
9
+
10
+ ## Referências
11
+
12
+ | Arquivo | Quando usar |
13
+ | --- | --- |
14
+ | [connection.md](references/connection.md) | Setup inicial: instalação, db.js, drizzle.config |
15
+ | [schema.md](references/schema.md) | Definir tabelas, tipos de colunas, relações |
16
+ | [migrations.md](references/migrations.md) | Criar e executar migrations com drizzle-kit |
17
+ | [queries.md](references/queries.md) | Select, insert, update, delete, queries com relações |
18
+
19
+ ## Quick Start
20
+
21
+ ```javascript
22
+ // database/db.js
23
+ import { drizzle } from 'drizzle-orm/bun-sqlite'
24
+ import Database from 'bun:sqlite'
25
+
26
+ const sqlite = new Database(process.env.DB_PATH ?? './data/database.db')
27
+ const db = drizzle({ client: sqlite })
28
+
29
+ export { db }
30
+ ```
31
+
32
+ ## Regras
33
+
34
+ - **Caminho do banco:** `/app/data/database.db` em produção (volume Fly.io). `./data/database.db` em desenvolvimento.
35
+ - **Migrations sempre:** Use `drizzle-kit generate` + `drizzle-kit migrate`. Nunca edite migrations à mão.
36
+ - **Schema único:** Todas as tabelas em `database/schema.js`.
37
+ - **Migrations no startup:** Use `migrate()` no `index.js` antes de `.listen()`.
38
+
39
+ ## Related Skills
40
+
41
+ | Need | Skill |
42
+ | --- | --- |
43
+ | **Backend (Elysia)** | @[.agent/skills/riligar-dev-manager] |
44
+ | **Payments (Stripe)** | @[.agent/skills/riligar-infra-stripe] |
45
+ | **Infrastructure** | @[.agent/skills/riligar-infra-fly] |
@@ -0,0 +1,74 @@
1
+ # Database Connection
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ bun add drizzle-orm
7
+ bun add -d drizzle-kit
8
+ ```
9
+
10
+ No additional drivers needed — `bun:sqlite` is built into Bun.
11
+
12
+ ## db.js
13
+
14
+ ```javascript
15
+ // database/db.js
16
+ import { drizzle } from 'drizzle-orm/bun-sqlite'
17
+ import Database from 'bun:sqlite'
18
+
19
+ const sqlite = new Database(process.env.DB_PATH ?? './data/database.db')
20
+ const db = drizzle({ client: sqlite })
21
+
22
+ export { db }
23
+ ```
24
+
25
+ - Em **desenvolvimento**: `DB_PATH` não é definido → usa `./data/database.db`
26
+ - Em **produção** (Fly.io): `fly secrets set DB_PATH=/app/data/database.db`
27
+
28
+ ## drizzle.config.js
29
+
30
+ ```javascript
31
+ // drizzle.config.js (na raiz do projeto)
32
+ import { defineConfig } from 'drizzle-kit'
33
+
34
+ export default defineConfig({
35
+ dialect: 'sqlite',
36
+ schema: './database/schema.js',
37
+ out: './database/migrations',
38
+ dbCredentials: {
39
+ url: process.env.DB_PATH ?? './data/database.db',
40
+ },
41
+ })
42
+ ```
43
+
44
+ ## Migrations no Startup
45
+
46
+ No `index.js`, execute migrations antes de iniciar o servidor:
47
+
48
+ ```javascript
49
+ // index.js
50
+ import { migrate } from 'drizzle-orm/bun-sqlite/migrator'
51
+ import { db } from './database/db'
52
+
53
+ await migrate(db, { migrationsFolder: './database/migrations' })
54
+
55
+ // ... resto do setup
56
+ const app = new Elysia()
57
+ .use(routes)
58
+ .listen(3000)
59
+ ```
60
+
61
+ Isso garante que o banco esteja sempre atualizado quando o servidor inicia no Fly.io.
62
+
63
+ ## Estrutura de Arquivos
64
+
65
+ ```
66
+ database/
67
+ ├── db.js # Conexão (drizzle + bun:sqlite)
68
+ ├── schema.js # Todas as tabelas e relações
69
+ └── migrations/
70
+ ├── 0000_*.sql # Migrations geradas pelo drizzle-kit
71
+ ├── 0001_*.sql
72
+ └── meta/
73
+ └── _journal.json
74
+ ```
@@ -0,0 +1,70 @@
1
+ # Migrations — drizzle-kit
2
+
3
+ ## Fluxo Padrão
4
+
5
+ ```
6
+ 1. Edite database/schema.js
7
+ 2. bun run db:generate → gera migration SQL
8
+ 3. bun run db:migrate → aplica no banco
9
+ ```
10
+
11
+ ## Scripts no package.json
12
+
13
+ ```javascript
14
+ {
15
+ "scripts": {
16
+ "db:generate": "drizzle-kit generate",
17
+ "db:migrate": "drizzle-kit migrate",
18
+ "db:push": "drizzle-kit push",
19
+ "db:studio": "drizzle-kit studio"
20
+ }
21
+ }
22
+ ```
23
+
24
+ ## Comandos
25
+
26
+ ### Gerar migration
27
+
28
+ ```bash
29
+ bun run db:generate
30
+ ```
31
+
32
+ Compara o schema atual com o último snapshot. Gera um arquivo `.sql` em `database/migrations/`. Pergunta se algum campo foi renomeado (vs criado novo + deletado).
33
+
34
+ ### Aplicar migrations
35
+
36
+ ```bash
37
+ bun run db:migrate
38
+ ```
39
+
40
+ Lê as migrations não aplicadas, executa em ordem. Mantém histórico no banco.
41
+
42
+ ### Push (apenas desenvolvimento)
43
+
44
+ ```bash
45
+ bun run db:push
46
+ ```
47
+
48
+ Aplica mudanças diretamente no banco sem gerar arquivos de migration. Útil durante prototipage rápido. **Nunca use em produção.**
49
+
50
+ ### Studio (GUI)
51
+
52
+ ```bash
53
+ bun run db:studio
54
+ ```
55
+
56
+ Abre uma interface visual para explorar e editar dados no banco.
57
+
58
+ ## Migrations Programáticas (Startup)
59
+
60
+ Em produção, as migrations são executadas automaticamente no startup da aplicação:
61
+
62
+ ```javascript
63
+ // index.js
64
+ import { migrate } from 'drizzle-orm/bun-sqlite/migrator'
65
+ import { db } from './database/db'
66
+
67
+ await migrate(db, { migrationsFolder: './database/migrations' })
68
+ ```
69
+
70
+ Isso garante que o banco esteja sempre atualizado quando o servidor inicia no Fly.io.
@@ -0,0 +1,173 @@
1
+ # Queries — Drizzle
2
+
3
+ ## Imports Comuns
4
+
5
+ ```javascript
6
+ import { db } from '../database/db'
7
+ import { users, posts } from '../database/schema'
8
+ import { eq, and, or, desc, asc } from 'drizzle-orm'
9
+ ```
10
+
11
+ ## Select
12
+
13
+ ### Básico
14
+
15
+ ```javascript
16
+ // Todos os registros
17
+ const allUsers = await db.select().from(users)
18
+
19
+ // Campos específicos
20
+ const names = await db.select({
21
+ id: users.id,
22
+ name: users.name,
23
+ }).from(users)
24
+ ```
25
+
26
+ ### Filtrar
27
+
28
+ ```javascript
29
+ // Por campo único
30
+ const [user] = await db.select().from(users).where(eq(users.id, userId)).limit(1)
31
+
32
+ // Múltiplos filtros (AND)
33
+ const results = await db.select().from(users).where(
34
+ and(
35
+ eq(users.active, true),
36
+ eq(users.plan, 'pro')
37
+ )
38
+ )
39
+
40
+ // OR
41
+ const results = await db.select().from(users).where(
42
+ or(eq(users.id, '1'), eq(users.id, '2'))
43
+ )
44
+ ```
45
+
46
+ ### Ordenar e Paginar
47
+
48
+ ```javascript
49
+ const page = await db.select().from(posts)
50
+ .orderBy(desc(posts.createdAt))
51
+ .limit(10)
52
+ .offset(pageIndex * 10)
53
+ ```
54
+
55
+ ## Insert
56
+
57
+ ```javascript
58
+ // Básico
59
+ await db.insert(users).values({ name: 'Dan', email: 'dan@email.com' })
60
+
61
+ // Com retorno
62
+ const [user] = await db.insert(users)
63
+ .values({ name: 'Dan', email: 'dan@email.com' })
64
+ .returning()
65
+
66
+ // Múltiplos
67
+ await db.insert(users).values([
68
+ { name: 'Dan', email: 'dan@email.com' },
69
+ { name: 'Ana', email: 'ana@email.com' },
70
+ ])
71
+
72
+ // Upsert (conflict handling)
73
+ await db.insert(users)
74
+ .values({ id: '1', name: 'Dan' })
75
+ .onConflictDoUpdate({
76
+ target: users.id,
77
+ set: { name: 'Dan', updatedAt: new Date() },
78
+ })
79
+ ```
80
+
81
+ ## Update
82
+
83
+ ```javascript
84
+ await db.update(users)
85
+ .set({ name: 'Mr. Dan', updatedAt: new Date() })
86
+ .where(eq(users.id, userId))
87
+
88
+ // Com retorno
89
+ const [updated] = await db.update(users)
90
+ .set({ plan: 'pro' })
91
+ .where(eq(users.id, userId))
92
+ .returning()
93
+ ```
94
+
95
+ ## Delete
96
+
97
+ ```javascript
98
+ await db.delete(users).where(eq(users.id, userId))
99
+
100
+ // Com retorno
101
+ const [deleted] = await db.delete(users)
102
+ .where(eq(users.id, userId))
103
+ .returning()
104
+ ```
105
+
106
+ ## Queries com Relações
107
+
108
+ Quando tiver relações definidas no schema, use `db.query` em vez de `db.select`:
109
+
110
+ ```javascript
111
+ // Usuário com todos os posts
112
+ const user = await db.query.users.findOne({
113
+ where: eq(users.id, userId),
114
+ with: {
115
+ posts: true,
116
+ },
117
+ })
118
+
119
+ // Posts com autor
120
+ const posts = await db.query.posts.findMany({
121
+ with: {
122
+ author: true,
123
+ },
124
+ orderBy: desc(posts.createdAt),
125
+ limit: 10,
126
+ })
127
+
128
+ // Nesting profundo
129
+ const user = await db.query.users.findOne({
130
+ where: eq(users.id, userId),
131
+ with: {
132
+ posts: {
133
+ with: {
134
+ comments: true,
135
+ },
136
+ },
137
+ },
138
+ })
139
+ ```
140
+
141
+ ## Padrão de Serviço
142
+
143
+ Sempre encapsule queries em serviços:
144
+
145
+ ```javascript
146
+ // services/user.js
147
+ import { db } from '../database/db'
148
+ import { users } from '../database/schema'
149
+ import { eq } from 'drizzle-orm'
150
+
151
+ export async function getUserById(id) {
152
+ const [user] = await db.select().from(users).where(eq(users.id, id)).limit(1)
153
+ return user ?? null
154
+ }
155
+
156
+ export async function createUser(data) {
157
+ const [user] = await db.insert(users).values(data).returning()
158
+ return user
159
+ }
160
+
161
+ export async function updateUser(id, data) {
162
+ const [user] = await db.update(users)
163
+ .set({ ...data, updatedAt: new Date() })
164
+ .where(eq(users.id, id))
165
+ .returning()
166
+ return user ?? null
167
+ }
168
+
169
+ export async function deleteUser(id) {
170
+ const [user] = await db.delete(users).where(eq(users.id, id)).returning()
171
+ return user ?? null
172
+ }
173
+ ```
@@ -0,0 +1,106 @@
1
+ # Schema — Drizzle SQLite
2
+
3
+ ## Definição Básica
4
+
5
+ ```javascript
6
+ // database/schema.js
7
+ import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
8
+ import { relations } from 'drizzle-orm'
9
+
10
+ export const users = sqliteTable('users', {
11
+ id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
12
+ email: text('email').notNull().unique(),
13
+ name: text('name'),
14
+ createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
15
+ updatedAt: integer('updated_at', { mode: 'timestamp' }),
16
+ })
17
+ ```
18
+
19
+ ## Tipos de Colunas
20
+
21
+ | Tipo | Uso | Exemplo |
22
+ | --- | --- | --- |
23
+ | `text()` | Strings, UUIDs, JSON | `text('name').notNull()` |
24
+ | `integer()` | Números, booleans, timestamps | `integer('age')` |
25
+ | `real()` | Decimais (float) | `real('price')` |
26
+ | `blob()` | Dados binários | `blob('avatar')` |
27
+ | `numeric()` | Valores numéricos precisos | `numeric('amount')` |
28
+
29
+ ### Modes do `integer()`
30
+
31
+ ```javascript
32
+ integer('count') // número
33
+ integer('active', { mode: 'boolean' }) // boolean (0/1)
34
+ integer('created_at', { mode: 'timestamp' }) // Date (segundos)
35
+ integer('created_at', { mode: 'timestamp_ms' }) // Date (milissegundos)
36
+ ```
37
+
38
+ ### JSON via `text()`
39
+
40
+ ```javascript
41
+ text('metadata', { mode: 'json' }) // armazena JSON como text
42
+ ```
43
+
44
+ ## Primary Key
45
+
46
+ ```javascript
47
+ // UUID (padrão RiLiGar)
48
+ id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
49
+
50
+ // Auto-increment (quando necessário)
51
+ id: integer('id').primaryKey({ autoIncrement: true }),
52
+ ```
53
+
54
+ ## Foreign Keys
55
+
56
+ ```javascript
57
+ export const posts = sqliteTable('posts', {
58
+ id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
59
+ authorId: text('author_id').notNull().references(() => users.id),
60
+ title: text('title').notNull(),
61
+ body: text('body'),
62
+ createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
63
+ })
64
+ ```
65
+
66
+ ## Relações
67
+
68
+ Relações são definidas separadamente do schema — são apenas para queries, não afetam o banco:
69
+
70
+ ```javascript
71
+ export const usersRelations = relations(users, ({ many }) => ({
72
+ posts: many(posts),
73
+ }))
74
+
75
+ export const postsRelations = relations(posts, ({ one }) => ({
76
+ author: one(users, {
77
+ fields: [posts.authorId],
78
+ references: [users.id],
79
+ }),
80
+ }))
81
+ ```
82
+
83
+ ### Many-to-Many (via junction table)
84
+
85
+ ```javascript
86
+ export const usersToGroups = sqliteTable('users_to_groups', {
87
+ userId: text('user_id').notNull().references(() => users.id),
88
+ groupId: text('group_id').notNull().references(() => groups.id),
89
+ })
90
+
91
+ export const usersRelations = relations(users, ({ many }) => ({
92
+ groups: many(usersToGroups),
93
+ }))
94
+
95
+ export const groupsRelations = relations(groups, ({ many }) => ({
96
+ users: many(usersToGroups),
97
+ }))
98
+ ```
99
+
100
+ ## Defaults e Constraints
101
+
102
+ ```javascript
103
+ plan: text('plan').default('free'),
104
+ active: integer('active', { mode: 'boolean' }).default(true),
105
+ createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
106
+ ```
@@ -115,6 +115,7 @@ console.log(`Server running at ${app.server?.url}`)
115
115
  | Need | Skill |
116
116
  | --- | --- |
117
117
  | **Authentication** | @[.agent/skills/riligar-dev-auth-elysia] |
118
+ | **Database** | @[.agent/skills/riligar-dev-database] |
118
119
  | **Infrastructure** | @[.agent/skills/riligar-infra-fly] |
119
120
 
120
121
  ## Decision Checklist
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: riligar-infra-cloudfare
3
- description: "Setup domains in Cloudflare with DNS for Clerk, Vercel, and email routing. Use when adding new domains, configuring DNS records, or setting up email redirects."
3
+ description: "Setup domains in Cloudflare with DNS, email routing, and R2 storage. Use when adding new domains, configuring DNS records, or setting up email redirects."
4
4
  ---
5
5
 
6
6
  # Cloudflare Setup
7
7
 
8
- Automate Cloudflare workflows: DNS setup, Clerk integration, Vercel deployment, email routing, and R2 storage.
8
+ Automate Cloudflare workflows: DNS setup, email routing, and R2 storage.
9
9
 
10
10
  ## Prerequisites
11
11
 
@@ -38,13 +38,6 @@ wrangler login
38
38
  wrangler whoami
39
39
  ```
40
40
 
41
- ### Other Tools
42
- ```bash
43
- # Vercel CLI (required)
44
- bun add -g vercel
45
- vercel login
46
- ```
47
-
48
41
  ## Workflow
49
42
 
50
43
  When setting up a new domain, follow these steps:
@@ -53,10 +46,8 @@ When setting up a new domain, follow these steps:
53
46
 
54
47
  Ask the user for:
55
48
  1. **Domain name** (e.g., `example.com`)
56
- 2. **Clerk DNS records** (paste from Clerk dashboard)
57
- 3. **Vercel project name** (e.g., `my-app`)
58
- 4. **Email addresses** to create (e.g., `contact`, `support`)
59
- 5. **Redirect target email** (e.g., `me@gmail.com`)
49
+ 2. **Email addresses** to create (e.g., `contact`, `support`)
50
+ 3. **Redirect target email** (e.g., `me@gmail.com`)
60
51
 
61
52
  ### Step 2: Get Zone ID
62
53
 
@@ -70,74 +61,7 @@ curl -X GET "https://api.cloudflare.com/client/v4/zones?name=DOMAIN" \
70
61
  wrangler pages project list # Shows associated zones
71
62
  ```
72
63
 
73
- ### Step 3: Create DNS Records for Clerk
74
-
75
- Clerk provides specific DNS records for each project. Common patterns:
76
-
77
- ```bash
78
- # Example: CNAME record
79
- curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
80
- -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
81
- -H "Content-Type: application/json" \
82
- --data '{
83
- "type": "CNAME",
84
- "name": "clerk",
85
- "content": "frontend-api.clerk.dev",
86
- "ttl": 1,
87
- "proxied": false
88
- }'
89
-
90
- # Example: TXT record for verification
91
- curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
92
- -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
93
- -H "Content-Type: application/json" \
94
- --data '{
95
- "type": "TXT",
96
- "name": "@",
97
- "content": "clerk-verification=xxxxx",
98
- "ttl": 1
99
- }'
100
- ```
101
-
102
- ### Step 4: Add Domain to Vercel
103
-
104
- ```bash
105
- # Add domain to Vercel project
106
- vercel domains add DOMAIN --scope=TEAM_SLUG
107
-
108
- # Or link to specific project
109
- vercel domains add DOMAIN PROJECT_NAME
110
- ```
111
-
112
- Then create Vercel DNS records:
113
-
114
- ```bash
115
- # A record for root domain
116
- curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
117
- -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
118
- -H "Content-Type: application/json" \
119
- --data '{
120
- "type": "A",
121
- "name": "@",
122
- "content": "76.76.21.21",
123
- "ttl": 1,
124
- "proxied": false
125
- }'
126
-
127
- # CNAME for www subdomain
128
- curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
129
- -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
130
- -H "Content-Type: application/json" \
131
- --data '{
132
- "type": "CNAME",
133
- "name": "www",
134
- "content": "cname.vercel-dns.com",
135
- "ttl": 1,
136
- "proxied": false
137
- }'
138
- ```
139
-
140
- ### Step 5: Setup Email Routing
64
+ ### Step 3: Setup Email Routing
141
65
 
142
66
  First, enable email routing for the zone (do this in Cloudflare dashboard first time).
143
67
 
@@ -212,7 +136,7 @@ curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
212
136
  }'
213
137
  ```
214
138
 
215
- ### Step 6: Verification Checklist
139
+ ### Step 4: Verification Checklist
216
140
 
217
141
  After setup, verify:
218
142
 
@@ -221,9 +145,6 @@ After setup, verify:
221
145
  curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
222
146
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result[] | {type, name, content}'
223
147
 
224
- # Check Vercel domain status
225
- vercel domains inspect DOMAIN
226
-
227
148
  # Test email routing (send test email to contact@DOMAIN)
228
149
  ```
229
150
 
@@ -235,12 +156,6 @@ When running `/cloudflare`, ask:
235
156
  What domain are you setting up?
236
157
  > example.com
237
158
 
238
- Paste the Clerk DNS records from your Clerk dashboard:
239
- > [user pastes records]
240
-
241
- What's the Vercel project name?
242
- > my-saas-app
243
-
244
159
  What email addresses should I create? (comma-separated)
245
160
  > contact, support, hello
246
161
 
@@ -252,8 +167,8 @@ What email should these redirect to?
252
167
 
253
168
  | Type | Use Case | Proxied |
254
169
  |------|----------|---------|
255
- | A | Root domain to IP | No (for Vercel) |
256
- | CNAME | Subdomain to hostname | No (for Clerk/Vercel) |
170
+ | A | Root domain to IP | Yes (production) |
171
+ | CNAME | Subdomain to hostname | Yes (production) |
257
172
  | TXT | Verification, SPF | N/A |
258
173
  | MX | Email routing | N/A |
259
174
 
@@ -264,8 +179,6 @@ What email should these redirect to?
264
179
  | Zone not found | Domain must be added to Cloudflare first |
265
180
  | DNS propagation slow | Wait 5-10 minutes, check with `dig` |
266
181
  | Email not forwarding | Verify destination email first |
267
- | Vercel 404 | Check DNS proxied=false for Vercel records |
268
- | Clerk verification failed | Ensure TXT record is on root (@) |
269
182
 
270
183
  ## Useful Commands
271
184
 
@@ -1043,9 +1043,3 @@ If you need more context:
1043
1043
 
1044
1044
  ---
1045
1045
 
1046
- ## Related Skills
1047
-
1048
- - **onboarding-cro**: For in-app onboarding (email supports this)
1049
- - **copywriting**: For landing pages emails link to
1050
- - **ab-test-setup**: For testing email elements
1051
- - **popup-cro**: For email capture popups
@@ -33,7 +33,7 @@ The Feasibility Index answers one question:
33
33
 
34
34
  ---
35
35
 
36
- ## 🔢 Programmatic SEO Feasibility Index
36
+ ## Programmatic SEO Feasibility Index
37
37
 
38
38
  ### Total Score: **0–100**
39
39
 
@@ -337,9 +337,3 @@ If triggered, **halt indexing or roll back**:
337
337
 
338
338
  ---
339
339
 
340
- ## Related Skills
341
-
342
- - **seo-audit** – Audit programmatic pages post-launch
343
- - **schema-markup** – Add structured data to templates
344
- - **copywriting** – Improve non-templated sections
345
- - **analytics-tracking** – Measure performance and validate value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riligar/agents-kit",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },