@gallopsystems/agent-skills 1.0.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 +137 -0
- package/package.json +26 -0
- package/plugins/doctl/.claude-plugin/plugin.json +8 -0
- package/plugins/doctl/skills/doctl/SKILL.md +93 -0
- package/plugins/kysely-postgres/.claude-plugin/plugin.json +8 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/SKILL.md +1101 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/aggregations.ts +167 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/ctes.ts +165 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/expressions.ts +272 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/joins.ts +206 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/json-arrays.ts +398 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/mutations.ts +199 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/orderby-pagination.ts +117 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/relations.ts +176 -0
- package/plugins/kysely-postgres/skills/kysely-postgres/references/select-where.ts +146 -0
- package/plugins/linear/.claude-plugin/plugin.json +8 -0
- package/plugins/linear/skills/linear/SKILL.md +1040 -0
- package/plugins/linear/skills/linear/bin/linear.mjs +1228 -0
- package/plugins/linear/skills/linear/tech-stack.md +273 -0
- package/plugins/nitro-testing/.claude-plugin/plugin.json +8 -0
- package/plugins/nitro-testing/skills/nitro-testing/SKILL.md +497 -0
- package/plugins/nitro-testing/skills/nitro-testing/async-testing.md +270 -0
- package/plugins/nitro-testing/skills/nitro-testing/ci-setup.md +226 -0
- package/plugins/nitro-testing/skills/nitro-testing/examples/global-setup.ts +90 -0
- package/plugins/nitro-testing/skills/nitro-testing/examples/handler.test.ts +167 -0
- package/plugins/nitro-testing/skills/nitro-testing/examples/setup.ts +29 -0
- package/plugins/nitro-testing/skills/nitro-testing/examples/test-utils-index.ts +297 -0
- package/plugins/nitro-testing/skills/nitro-testing/examples/vitest.config.ts +42 -0
- package/plugins/nitro-testing/skills/nitro-testing/factories.md +278 -0
- package/plugins/nitro-testing/skills/nitro-testing/frontend-testing.md +512 -0
- package/plugins/nitro-testing/skills/nitro-testing/test-utils.md +262 -0
- package/plugins/nitro-testing/skills/nitro-testing/transaction-rollback.md +183 -0
- package/plugins/nitro-testing/skills/nitro-testing/vitest-config.md +236 -0
- package/plugins/nuxt-nitro-api/.claude-plugin/plugin.json +8 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/SKILL.md +260 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/auth-patterns.md +228 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/composables-utils.md +174 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/deep-linking.md +190 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/examples/auth-middleware.ts +32 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/examples/auth-utils.ts +51 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/examples/deep-link-page.vue +61 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/examples/service-util.ts +63 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/examples/sse-endpoint.ts +59 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/examples/validation-endpoint.ts +38 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/fetch-patterns.md +178 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/nitro-tasks.md +243 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/page-structure.md +162 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/server-services.md +238 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/sse.md +221 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/ssr-client.md +166 -0
- package/plugins/nuxt-nitro-api/skills/nuxt-nitro-api/validation.md +131 -0
- package/scripts/link-skills.mjs +252 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# Gallop Systems — Tech Stack Reference
|
|
2
|
+
|
|
3
|
+
This document describes the standard tech stack used across all Gallop Systems projects, based on the [nuxt-copier-template](https://github.com/gallop-systems/nuxt-copier-template).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Stack Overview
|
|
8
|
+
|
|
9
|
+
| Layer | Technology | Version |
|
|
10
|
+
|-------|-----------|---------|
|
|
11
|
+
| **Framework** | Nuxt 4 (Vue 3) | ^4.2.2 |
|
|
12
|
+
| **Server** | Nitro (built into Nuxt) | — |
|
|
13
|
+
| **Database** | PostgreSQL | 15+ |
|
|
14
|
+
| **Query Builder** | Kysely (type-safe SQL) | ^0.28.9 |
|
|
15
|
+
| **Auth** | nuxt-auth-utils (session-based) | ^0.5.27 |
|
|
16
|
+
| **OAuth** | Google OAuth (optional) | via nuxt-auth-utils |
|
|
17
|
+
| **UI Components** | PrimeVue (unstyled) + Volt | ^4.5.4 |
|
|
18
|
+
| **Styling** | Tailwind CSS v4 | ^4.1.18 |
|
|
19
|
+
| **Icons** | PrimeIcons | ^7.0.0 |
|
|
20
|
+
| **Validation** | Zod | ^4.3.5 |
|
|
21
|
+
| **Date Handling** | date-fns | ^4.1.0 |
|
|
22
|
+
| **Testing** | Vitest | ^4.0.17 |
|
|
23
|
+
| **Linter** | oxlint | latest |
|
|
24
|
+
| **Formatter** | oxfmt | latest |
|
|
25
|
+
| **Package Manager** | Yarn 4 (Berry) | 4.12.0 |
|
|
26
|
+
| **Node Version** | 22 | (see .nvmrc) |
|
|
27
|
+
| **Git Hooks** | Lefthook (optional) | latest |
|
|
28
|
+
| **Deployment** | DigitalOcean App Platform | — |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Project Structure (Nuxt 4)
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
app/ # Frontend
|
|
36
|
+
├── assets/css/main.css # Tailwind + PrimeUI imports + CSS variables
|
|
37
|
+
├── components/ # Vue components (auto-imported)
|
|
38
|
+
├── composables/ # Vue composables (auto-imported)
|
|
39
|
+
├── layouts/ # Layout templates
|
|
40
|
+
├── middleware/ # Client-side route middleware
|
|
41
|
+
├── pages/ # File-based routing
|
|
42
|
+
└── plugins/ # Vue plugins (PrimeVue setup)
|
|
43
|
+
|
|
44
|
+
server/ # Backend (Nitro)
|
|
45
|
+
├── api/ # API routes (file-based: users/index.get.ts → GET /api/users)
|
|
46
|
+
│ ├── auth/ # Auth endpoints (OAuth handlers)
|
|
47
|
+
│ ├── public/ # Public endpoints (no auth required)
|
|
48
|
+
│ └── webhooks/ # Webhook endpoints (own auth)
|
|
49
|
+
├── db/
|
|
50
|
+
│ ├── db.d.ts # Auto-generated Kysely types (yarn db:codegen)
|
|
51
|
+
│ └── migrations/ # Kysely migrations
|
|
52
|
+
├── middleware/ # Server middleware (auth guard)
|
|
53
|
+
├── test-utils/ # Test infrastructure
|
|
54
|
+
│ ├── index.ts # Factories, mock helpers, test fixture
|
|
55
|
+
│ ├── setup.ts # Global stubs (useRuntimeConfig, handler mocks)
|
|
56
|
+
│ └── global-setup.ts # DB reset + migrations before test suite
|
|
57
|
+
└── utils/
|
|
58
|
+
└── db.ts # Kysely database connection (exports db, useDatabase())
|
|
59
|
+
|
|
60
|
+
shared/ # Shared between frontend + backend
|
|
61
|
+
└── types/ # Type declarations (auth.d.ts)
|
|
62
|
+
|
|
63
|
+
src/volt/ # Volt UI components (PrimeVue unstyled + Tailwind)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Key Patterns & Conventions
|
|
69
|
+
|
|
70
|
+
### API Handlers (Nitro)
|
|
71
|
+
|
|
72
|
+
File naming determines the HTTP method and route:
|
|
73
|
+
- `server/api/users/index.get.ts` → `GET /api/users`
|
|
74
|
+
- `server/api/users/index.post.ts` → `POST /api/users`
|
|
75
|
+
- `server/api/users/[id].get.ts` → `GET /api/users/:id`
|
|
76
|
+
- `server/api/users/[id].put.ts` → `PUT /api/users/:id`
|
|
77
|
+
- `server/api/users/[id].delete.ts` → `DELETE /api/users/:id`
|
|
78
|
+
|
|
79
|
+
Standard handler pattern:
|
|
80
|
+
```typescript
|
|
81
|
+
import { z } from "zod";
|
|
82
|
+
|
|
83
|
+
export default defineEventHandler(async (event) => {
|
|
84
|
+
const db = useDatabase();
|
|
85
|
+
|
|
86
|
+
// Route params
|
|
87
|
+
const { id } = await getValidatedRouterParams(event, z.object({
|
|
88
|
+
id: z.coerce.number(),
|
|
89
|
+
}).parse);
|
|
90
|
+
|
|
91
|
+
// Request body (POST/PUT)
|
|
92
|
+
const body = await readValidatedBody(event, z.object({
|
|
93
|
+
name: z.string(),
|
|
94
|
+
}).parse);
|
|
95
|
+
|
|
96
|
+
// Query params
|
|
97
|
+
const query = await getValidatedQuery(event, z.object({
|
|
98
|
+
page: z.coerce.number().optional(),
|
|
99
|
+
}).parse);
|
|
100
|
+
|
|
101
|
+
// Access authenticated user
|
|
102
|
+
const user = event.context.user;
|
|
103
|
+
|
|
104
|
+
// Database operations with Kysely
|
|
105
|
+
return db.selectFrom("users").selectAll().execute();
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Authentication
|
|
110
|
+
|
|
111
|
+
- **Server middleware** (`server/middleware/auth.ts`) protects all `/api/*` routes automatically
|
|
112
|
+
- **Exempt paths:** `/api/public/*`, `/api/webhooks/*`, `/api/auth/*`
|
|
113
|
+
- **Client middleware** (`app/middleware/auth.global.ts`) redirects unauthenticated users to `/login`
|
|
114
|
+
- **Session access:** `getUserSession(event)` on server, `useUserSession()` on client
|
|
115
|
+
- Authenticated user is available at `event.context.user` in API handlers
|
|
116
|
+
|
|
117
|
+
### Database (Kysely + PostgreSQL)
|
|
118
|
+
|
|
119
|
+
- **Connection:** `useDatabase()` returns a Kysely instance (auto-imported in Nitro handlers)
|
|
120
|
+
- **Type generation:** Run `yarn db:codegen` after schema changes to regenerate `server/db/db.d.ts`
|
|
121
|
+
- **Migrations:** Use `yarn db:migrate:make <name>` to create, `yarn db:migrate` to run
|
|
122
|
+
- **Environment variable:** `NUXT_DATABASE_URL` (auto-binds to `runtimeConfig.databaseUrl`)
|
|
123
|
+
- **ID columns:** Use `bigint` with `generatedAlwaysAsIdentity()` (not serial)
|
|
124
|
+
- **Timestamps:** Use `timestamptz` with `defaultTo(sql\`now()\`)` for `created_at`/`updated_at`
|
|
125
|
+
- **Column naming:** Use `snake_case` for database columns (e.g., `first_name`, `created_at`)
|
|
126
|
+
- **SSL:** Auto-detected — disabled for localhost, enabled for remote connections
|
|
127
|
+
|
|
128
|
+
### Migration Pattern
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import type { Kysely } from "kysely";
|
|
132
|
+
import { sql } from "kysely";
|
|
133
|
+
|
|
134
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
135
|
+
await db.schema
|
|
136
|
+
.createTable("table_name")
|
|
137
|
+
.addColumn("id", "bigint", (col) => col.primaryKey().generatedAlwaysAsIdentity())
|
|
138
|
+
.addColumn("name", "text", (col) => col.notNull())
|
|
139
|
+
.addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`))
|
|
140
|
+
.addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`))
|
|
141
|
+
.execute();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
145
|
+
await db.schema.dropTable("table_name").execute();
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Testing
|
|
150
|
+
|
|
151
|
+
**Backend tests** use real PostgreSQL with transaction rollback isolation:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { describe, test, expect, mockGet, mockPost, expectHttpError } from "~/server/test-utils";
|
|
155
|
+
import handler from "./endpoint.get";
|
|
156
|
+
|
|
157
|
+
describe("GET /api/endpoint", () => {
|
|
158
|
+
test("description", async ({ factories }) => {
|
|
159
|
+
// Create test data (auto-rolled back after test)
|
|
160
|
+
const user = await factories.user({ email: "test@example.com" });
|
|
161
|
+
|
|
162
|
+
// Create mock HTTP event
|
|
163
|
+
const event = mockGet(); // GET with no params
|
|
164
|
+
const event = mockGet({ id: "1" }); // GET with route params
|
|
165
|
+
const event = mockGet({}, { page: "1" }); // GET with query params
|
|
166
|
+
const event = mockPost({}, { name: "Test" }); // POST with body
|
|
167
|
+
const event = mockPut({ id: "1" }, { name: "X" }); // PUT with params + body
|
|
168
|
+
const event = mockDelete({ id: "1" }); // DELETE with params
|
|
169
|
+
|
|
170
|
+
// Call handler directly
|
|
171
|
+
const result = await handler(event);
|
|
172
|
+
expect(result).toHaveLength(1);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("throws 404", async ({ factories: _ }) => {
|
|
176
|
+
// Always destructure factories (even as _) to set up transaction
|
|
177
|
+
const event = mockGet({ id: "999" });
|
|
178
|
+
await expectHttpError(handler(event), { statusCode: 404 });
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Frontend tests** use Nuxt test environment:
|
|
184
|
+
```bash
|
|
185
|
+
VITEST_ENV=nuxt vitest # or yarn test:frontend
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Test file locations:
|
|
189
|
+
- Backend: `server/**/*.test.ts` (co-located with handlers)
|
|
190
|
+
- Frontend: `app/components/**/*.test.ts`, `app/pages/**/*.test.ts`, `app/composables/**/*.test.ts`
|
|
191
|
+
|
|
192
|
+
### UI Components (Volt + PrimeVue)
|
|
193
|
+
|
|
194
|
+
- Volt components are PrimeVue unstyled components styled with Tailwind
|
|
195
|
+
- Registered with `Volt` prefix: `VoltButton`, `VoltCard`, `VoltDataTable`, etc.
|
|
196
|
+
- Customize via `pt:section:class` pass-through syntax (NOT via Tailwind `class` prop)
|
|
197
|
+
- See `DESIGN_LANGUAGE.md` for the complete design system
|
|
198
|
+
|
|
199
|
+
Available Volt components:
|
|
200
|
+
`VoltButton`, `VoltSecondaryButton`, `VoltCard`, `VoltDataTable`, `VoltDialog`, `VoltConfirmDialog`, `VoltInputText`, `VoltPassword`, `VoltSelect`, `VoltTextarea`, `VoltAvatar`, `VoltTag`, `VoltMessage`, `VoltToast`
|
|
201
|
+
|
|
202
|
+
### Design System Essentials
|
|
203
|
+
|
|
204
|
+
- **Zinc-first palette** — zinc for almost everything, color only for semantic meaning
|
|
205
|
+
- **No decorative shadows** — shadows only on hover for interactivity
|
|
206
|
+
- **Rounding:** `rounded-xl` for inputs/buttons, `rounded-2xl` for cards
|
|
207
|
+
- **Icons:** PrimeIcons (`pi pi-*` classes)
|
|
208
|
+
- **Refer to `DESIGN_LANGUAGE.md`** for full component styling reference
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Commands Reference
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Development
|
|
216
|
+
yarn dev # Dev server on localhost:3000
|
|
217
|
+
|
|
218
|
+
# Database
|
|
219
|
+
yarn db:migrate # Run all pending migrations
|
|
220
|
+
yarn db:migrate:down # Rollback last migration
|
|
221
|
+
yarn db:migrate:make <name> # Create new migration file
|
|
222
|
+
yarn db:codegen # Regenerate TypeScript types from DB schema
|
|
223
|
+
|
|
224
|
+
# Testing
|
|
225
|
+
yarn test # Backend tests (watch mode)
|
|
226
|
+
yarn test:run # Backend tests (single run)
|
|
227
|
+
yarn test:frontend # Frontend tests (watch mode)
|
|
228
|
+
yarn test:frontend:run # Frontend tests (single run)
|
|
229
|
+
|
|
230
|
+
# Code Quality
|
|
231
|
+
yarn typecheck # TypeScript type checking
|
|
232
|
+
yarn lint # oxlint
|
|
233
|
+
yarn lint:fix # oxlint with auto-fix
|
|
234
|
+
yarn fmt # oxfmt format
|
|
235
|
+
yarn fmt:check # oxfmt check only
|
|
236
|
+
|
|
237
|
+
# Build
|
|
238
|
+
yarn build # Production build
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## CI/CD
|
|
244
|
+
|
|
245
|
+
GitHub Actions CI runs on push/PR to `main`:
|
|
246
|
+
1. **Test job:** Backend tests with coverage + frontend tests (uses PostgreSQL service container)
|
|
247
|
+
2. **Lint job:** Typecheck + oxlint + oxfmt check
|
|
248
|
+
3. **Coverage job:** Posts coverage report on PRs
|
|
249
|
+
|
|
250
|
+
Deployment: DigitalOcean App Platform with a pre-deploy migration job (`yarn db:migrate`).
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Environment Variables
|
|
255
|
+
|
|
256
|
+
| Variable | Purpose |
|
|
257
|
+
|----------|---------|
|
|
258
|
+
| `NUXT_DATABASE_URL` | PostgreSQL connection string |
|
|
259
|
+
| `NUXT_SESSION_PASSWORD` | Session encryption secret |
|
|
260
|
+
| `NUXT_OAUTH_GOOGLE_CLIENT_ID` | Google OAuth client ID (optional) |
|
|
261
|
+
| `NUXT_OAUTH_GOOGLE_CLIENT_SECRET` | Google OAuth client secret (optional) |
|
|
262
|
+
|
|
263
|
+
The `NUXT_` prefix auto-binds to `runtimeConfig` in `nuxt.config.ts`.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Git Hooks (Lefthook)
|
|
268
|
+
|
|
269
|
+
| Hook | Actions |
|
|
270
|
+
|------|---------|
|
|
271
|
+
| **pre-commit** | Format (oxfmt) + lint fix (oxlint) on staged `.ts/.vue/.js` files |
|
|
272
|
+
| **pre-push** | Backend tests, frontend tests, typecheck, lint (in parallel) |
|
|
273
|
+
| **post-merge** | Auto `yarn install` if `package.json`/`yarn.lock` changed; warns if new migrations detected |
|