@usequark/quark-create-app 1.23.11
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 +210 -0
- package/package.json +56 -0
- package/src/dependabot-config.test.js +128 -0
- package/src/deploy/adapters/iac.js +203 -0
- package/src/deploy/adapters/index.js +27 -0
- package/src/deploy/adapters/railway.js +508 -0
- package/src/deploy/adapters/railway.test.js +318 -0
- package/src/deploy/contract.js +59 -0
- package/src/deploy/deploy.integration.test.js +183 -0
- package/src/deploy/deploy.js +430 -0
- package/src/deploy/deploy.test.js +105 -0
- package/src/deploy/discovery.js +115 -0
- package/src/deploy/discovery.test.js +141 -0
- package/src/deploy/index.js +38 -0
- package/src/deploy/inspect.js +130 -0
- package/src/index.js +2920 -0
- package/src/mobile-template.test.js +232 -0
- package/src/prepare-hooks.test.js +535 -0
- package/src/scaffold-guards.test.js +140 -0
- package/src/scaffold-output.test.js +228 -0
- package/src/template-scripts.test.js +160 -0
- package/src/utils.js +77 -0
- package/src/utils.test.js +95 -0
- package/src/worker-dockerfile.test.js +85 -0
- package/templates/base-project/.cursor/rules/quark.mdc +172 -0
- package/templates/base-project/.dockerignore +14 -0
- package/templates/base-project/.env.railway.example +87 -0
- package/templates/base-project/.github/copilot-instructions.md +65 -0
- package/templates/base-project/.github/dependabot.yml +31 -0
- package/templates/base-project/.github/skills/project-context/SKILL.md +109 -0
- package/templates/base-project/.github/workflows/ci.yml +116 -0
- package/templates/base-project/.github/workflows/dependabot-auto-merge.yml +22 -0
- package/templates/base-project/.github/workflows/install-windows.yml +27 -0
- package/templates/base-project/.github/workflows/release.yml +67 -0
- package/templates/base-project/.railway/railway.ts +40 -0
- package/templates/base-project/CLAUDE.md +163 -0
- package/templates/base-project/MAIN.md +21 -0
- package/templates/base-project/README.md +164 -0
- package/templates/base-project/apps/web/.env.example +99 -0
- package/templates/base-project/apps/web/Dockerfile +38 -0
- package/templates/base-project/apps/web/biome.json +8 -0
- package/templates/base-project/apps/web/jsconfig.json +9 -0
- package/templates/base-project/apps/web/next.config.js +154 -0
- package/templates/base-project/apps/web/package.json +42 -0
- package/templates/base-project/apps/web/postcss.config.mjs +7 -0
- package/templates/base-project/apps/web/public/.well-known/security.txt +3 -0
- package/templates/base-project/apps/web/public/quark.svg +47 -0
- package/templates/base-project/apps/web/scripts/prepare-standalone.mjs +71 -0
- package/templates/base-project/apps/web/src/app/_components/AsciiPanel.js +103 -0
- package/templates/base-project/apps/web/src/app/_components/HealthIndicator.js +85 -0
- package/templates/base-project/apps/web/src/app/_components/HomeThemeToggle.js +63 -0
- package/templates/base-project/apps/web/src/app/_components/QuarkAnimation.js +168 -0
- package/templates/base-project/apps/web/src/app/_components/SyncedPanels.js +212 -0
- package/templates/base-project/apps/web/src/app/_components/UmamiReplayRecorder.js +198 -0
- package/templates/base-project/apps/web/src/app/_components/UmamiWebVitals.js +39 -0
- package/templates/base-project/apps/web/src/app/api/auth/[...nextauth]/route.js +7 -0
- package/templates/base-project/apps/web/src/app/api/auth/apple/route.js +82 -0
- package/templates/base-project/apps/web/src/app/api/auth/google/route.js +59 -0
- package/templates/base-project/apps/web/src/app/api/auth/refresh/route.js +48 -0
- package/templates/base-project/apps/web/src/app/api/auth/register/route.js +63 -0
- package/templates/base-project/apps/web/src/app/api/auth/token/route.js +44 -0
- package/templates/base-project/apps/web/src/app/api/csrf/route.js +40 -0
- package/templates/base-project/apps/web/src/app/api/device/register/route.js +57 -0
- package/templates/base-project/apps/web/src/app/api/error-handler.js +23 -0
- package/templates/base-project/apps/web/src/app/api/files/[id]/route.js +89 -0
- package/templates/base-project/apps/web/src/app/api/files/route.js +120 -0
- package/templates/base-project/apps/web/src/app/api/health/route.js +160 -0
- package/templates/base-project/apps/web/src/app/api/users/[id]/route.js +54 -0
- package/templates/base-project/apps/web/src/app/api/users/me/route.js +67 -0
- package/templates/base-project/apps/web/src/app/api/users/route.js +45 -0
- package/templates/base-project/apps/web/src/app/auth/error/page.js +83 -0
- package/templates/base-project/apps/web/src/app/auth/forgot-password/page.js +58 -0
- package/templates/base-project/apps/web/src/app/auth/provider-loading.js +25 -0
- package/templates/base-project/apps/web/src/app/auth/register/RegisterPageClient.js +340 -0
- package/templates/base-project/apps/web/src/app/auth/register/page.js +17 -0
- package/templates/base-project/apps/web/src/app/auth/signin/SignInPageClient.js +230 -0
- package/templates/base-project/apps/web/src/app/auth/signin/page.js +10 -0
- package/templates/base-project/apps/web/src/app/favicon.ico +0 -0
- package/templates/base-project/apps/web/src/app/global-error.js +58 -0
- package/templates/base-project/apps/web/src/app/globals.css +1166 -0
- package/templates/base-project/apps/web/src/app/icon.svg +47 -0
- package/templates/base-project/apps/web/src/app/layout.js +57 -0
- package/templates/base-project/apps/web/src/app/manifest.js +12 -0
- package/templates/base-project/apps/web/src/app/not-found.js +39 -0
- package/templates/base-project/apps/web/src/app/page.js +262 -0
- package/templates/base-project/apps/web/src/app/robots.js +23 -0
- package/templates/base-project/apps/web/src/app/sitemap.js +14 -0
- package/templates/base-project/apps/web/src/lib/analytics/umami-before-send.js +29 -0
- package/templates/base-project/apps/web/src/lib/analytics/umami-config.js +95 -0
- package/templates/base-project/apps/web/src/lib/analytics/umami-csp.js +24 -0
- package/templates/base-project/apps/web/src/lib/analytics/umami-marketing.js +131 -0
- package/templates/base-project/apps/web/src/lib/analytics/umami-replay.js +204 -0
- package/templates/base-project/apps/web/src/lib/analytics/umami-web-vitals.js +237 -0
- package/templates/base-project/apps/web/src/lib/analytics/umami.js +57 -0
- package/templates/base-project/apps/web/src/lib/auth-middleware.js +82 -0
- package/templates/base-project/apps/web/src/lib/auth-signup.js +5 -0
- package/templates/base-project/apps/web/src/lib/auth.js +191 -0
- package/templates/base-project/apps/web/src/lib/csrf-cookie.js +11 -0
- package/templates/base-project/apps/web/src/lib/jwt.js +84 -0
- package/templates/base-project/apps/web/src/lib/load-crm-config.js +35 -0
- package/templates/base-project/apps/web/src/lib/normalize-auth-request.js +33 -0
- package/templates/base-project/apps/web/src/lib/proxy-auth.js +80 -0
- package/templates/base-project/apps/web/src/lib/seo/indexing.js +25 -0
- package/templates/base-project/apps/web/src/lib/seo/site-metadata.js +74 -0
- package/templates/base-project/apps/web/src/lib/sitemap-entries.js +22 -0
- package/templates/base-project/apps/web/src/preflight.js +55 -0
- package/templates/base-project/apps/web/src/proxy.js +328 -0
- package/templates/base-project/biome.json +52 -0
- package/templates/base-project/docker-compose.override.yml +17 -0
- package/templates/base-project/docker-compose.yml +37 -0
- package/templates/base-project/docs/FIRST_FEATURE.md +74 -0
- package/templates/base-project/docs/START_HERE.md +70 -0
- package/templates/base-project/docs/adr/README.md +42 -0
- package/templates/base-project/package.json +58 -0
- package/templates/base-project/packages/db/package.json +38 -0
- package/templates/base-project/packages/db/prisma/migrations/20260202061128_initial/migration.sql +202 -0
- package/templates/base-project/packages/db/prisma/migrations/migration_lock.toml +3 -0
- package/templates/base-project/packages/db/prisma/schema.prisma +161 -0
- package/templates/base-project/packages/db/prisma/seed.js +152 -0
- package/templates/base-project/packages/db/prisma.config.js +27 -0
- package/templates/base-project/packages/db/src/client.js +75 -0
- package/templates/base-project/packages/db/src/connection.js +44 -0
- package/templates/base-project/packages/db/src/context.js +275 -0
- package/templates/base-project/packages/db/src/index.js +5 -0
- package/templates/base-project/packages/db/src/ping.js +66 -0
- package/templates/base-project/packages/db/src/queries.js +292 -0
- package/templates/base-project/packages/db/src/schemas.js +30 -0
- package/templates/base-project/packages/db/src/umami.js +299 -0
- package/templates/base-project/pnpm-workspace.yaml +20 -0
- package/templates/base-project/scripts/check-loading.mjs +49 -0
- package/templates/base-project/scripts/check-standards.mjs +186 -0
- package/templates/base-project/scripts/clean-workspace.mjs +479 -0
- package/templates/base-project/scripts/dev-preflight.mjs +48 -0
- package/templates/base-project/scripts/doctor.js +408 -0
- package/templates/base-project/scripts/prepare.js +490 -0
- package/templates/base-project/scripts/run-tests.mjs +71 -0
- package/templates/base-project/skills/add-dashboard/SKILL.md +28 -0
- package/templates/base-project/skills/add-endpoint/SKILL.md +29 -0
- package/templates/base-project/skills/add-model/SKILL.md +28 -0
- package/templates/base-project/skills/ecommerce/SKILL.md +224 -0
- package/templates/base-project/skills/ecommerce-cart/SKILL.md +193 -0
- package/templates/base-project/skills/ecommerce-catalog/SKILL.md +179 -0
- package/templates/base-project/skills/ecommerce-checkout/SKILL.md +195 -0
- package/templates/base-project/skills/i18n/SKILL.md +211 -0
- package/templates/base-project/skills/payment/SKILL.md +280 -0
- package/templates/base-project/skills/quark-skills/SKILL.md +37 -0
- package/templates/base-project/turbo.json +143 -0
- package/templates/config/package.json +20 -0
- package/templates/config/src/app-url.js +134 -0
- package/templates/config/src/environment.js +284 -0
- package/templates/config/src/index.js +16 -0
- package/templates/config/src/load-config.js +157 -0
- package/templates/config/src/rate-limit.js +136 -0
- package/templates/config/src/redis.js +43 -0
- package/templates/config/src/validate-env.js +532 -0
- package/templates/jobs/README.md +52 -0
- package/templates/jobs/package.json +9 -0
- package/templates/jobs/src/definitions.js +13 -0
- package/templates/jobs/src/index.js +1 -0
- package/templates/mobile/.env.example +16 -0
- package/templates/mobile/CHECKLIST.md +40 -0
- package/templates/mobile/README.md +130 -0
- package/templates/mobile/app/(app)/_layout.tsx +83 -0
- package/templates/mobile/app/(app)/index.tsx +147 -0
- package/templates/mobile/app/(app)/profile.tsx +204 -0
- package/templates/mobile/app/(app)/settings.tsx +80 -0
- package/templates/mobile/app/(auth)/_layout.tsx +10 -0
- package/templates/mobile/app/(auth)/sign-in.tsx +140 -0
- package/templates/mobile/app/(auth)/sign-up.tsx +178 -0
- package/templates/mobile/app/+not-found.tsx +32 -0
- package/templates/mobile/app/_layout.tsx +18 -0
- package/templates/mobile/app.json +47 -0
- package/templates/mobile/assets/adaptive-icon.png +0 -0
- package/templates/mobile/assets/icon.png +0 -0
- package/templates/mobile/assets/notification-icon.png +0 -0
- package/templates/mobile/assets/splash.png +0 -0
- package/templates/mobile/biome.json +27 -0
- package/templates/mobile/components/AuthGate.tsx +19 -0
- package/templates/mobile/components/ThemeProvider.tsx +23 -0
- package/templates/mobile/eas.json +29 -0
- package/templates/mobile/hooks/use-auth.ts +127 -0
- package/templates/mobile/lib/api-client.ts +138 -0
- package/templates/mobile/lib/api.ts +83 -0
- package/templates/mobile/lib/auth-providers-google.ts +74 -0
- package/templates/mobile/lib/auth-providers.ts +74 -0
- package/templates/mobile/lib/auth.ts +100 -0
- package/templates/mobile/lib/config.ts +14 -0
- package/templates/mobile/lib/errors.ts +46 -0
- package/templates/mobile/lib/notifications.ts +77 -0
- package/templates/mobile/lib/storage.ts +25 -0
- package/templates/mobile/lib/theme-tokens.ts +16 -0
- package/templates/mobile/package.json +37 -0
- package/templates/mobile/tsconfig.json +10 -0
- package/templates/pwa/app/_components/PWARegister.js +15 -0
- package/templates/pwa/app/manifest.js +32 -0
- package/templates/pwa/public/sw.js +72 -0
- package/templates/ui/README.md +44 -0
- package/templates/ui/package.json +21 -0
- package/templates/ui/src/badge.js +23 -0
- package/templates/ui/src/button.js +111 -0
- package/templates/ui/src/card.js +128 -0
- package/templates/ui/src/checkbox.js +20 -0
- package/templates/ui/src/container.js +13 -0
- package/templates/ui/src/dialog.js +137 -0
- package/templates/ui/src/error-banner.js +15 -0
- package/templates/ui/src/footer.js +239 -0
- package/templates/ui/src/form-field.integration-test.js +142 -0
- package/templates/ui/src/form-field.js +50 -0
- package/templates/ui/src/index.js +24 -0
- package/templates/ui/src/input.js +11 -0
- package/templates/ui/src/label.js +14 -0
- package/templates/ui/src/lightbox.integration-test.js +167 -0
- package/templates/ui/src/lightbox.js +243 -0
- package/templates/ui/src/logo.js +52 -0
- package/templates/ui/src/navbar.js +602 -0
- package/templates/ui/src/password-input.js +31 -0
- package/templates/ui/src/rich-text.js +514 -0
- package/templates/ui/src/select.js +317 -0
- package/templates/ui/src/skeleton.js +10 -0
- package/templates/ui/src/spinner.js +31 -0
- package/templates/ui/src/table.js +169 -0
- package/templates/ui/src/textarea.js +11 -0
- package/templates/ui/src/theme-constants.js +24 -0
- package/templates/ui/src/theme.js +196 -0
- package/templates/ui/src/toast.js +206 -0
- package/templates/worker/Dockerfile +64 -0
- package/templates/worker/README.md +56 -0
- package/templates/worker/package.json +36 -0
- package/templates/worker/src/config/pricing.js +46 -0
- package/templates/worker/src/handlers/email-job-validation.js +36 -0
- package/templates/worker/src/handlers/email.js +98 -0
- package/templates/worker/src/handlers/files.js +59 -0
- package/templates/worker/src/handlers/index.js +20 -0
- package/templates/worker/src/handlers/push-notification.js +234 -0
- package/templates/worker/src/index.js +505 -0
- package/templates/worker/src/lib/railway.js +438 -0
- package/templates/worker/src/lib/tokens.js +81 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Quark project conventions for __QUARK_PROJECT_NAME__. Covers all layers: UI, backend, database, auth, jobs, testing, and deployment.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Quark Project: __QUARK_PROJECT_NAME__
|
|
7
|
+
|
|
8
|
+
Package scope: `@__QUARK_SCOPE__` - use this for ALL workspace packages.
|
|
9
|
+
Scaffolded: __QUARK_SCAFFOLD_DATE__
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Non-Negotiable Rules
|
|
14
|
+
|
|
15
|
+
1. **ESM only.** Always `import`/`export`. Never `require()` or `module.exports`.
|
|
16
|
+
2. **No authored TypeScript.** Plain `.js` and `.jsx` files only - no repo-authored `.ts`, `.tsx`, or type annotations. Generated code is the only exception.
|
|
17
|
+
3. **Validate everything at boundaries.** Server Actions and API routes must use Zod. No raw `req.body` access without parsing.
|
|
18
|
+
4. **Use AppError at runtime boundaries.** Throw `AppError` / `ValidationError` / `NotFoundError` from `@techstream/quark-core/errors` in application/runtime code. Native `Error` is reserved for library, bootstrap, CLI, and test code.
|
|
19
|
+
5. **Log with createLogger in runtime code.** Use `createLogger(name)` from `@techstream/quark-core` for application/runtime code. Console output is reserved for bootstrap, CLI, and test code.
|
|
20
|
+
6. **DB models always have timestamps.** Every Prisma model: `createdAt DateTime @default(now())` + `updatedAt DateTime @updatedAt`.
|
|
21
|
+
7. **Workspace import scope.** Use `@__QUARK_SCOPE__/*` for local packages. Never `@techstream/quark-db`, `@techstream/quark-config`, etc.
|
|
22
|
+
8. **Co-located tests.** `feature.test.js` lives next to `feature.js`. Tests use `node --test` - no Jest, no Vitest.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Import Reference
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
// ✅ Workspace packages - always @__QUARK_SCOPE__/*:
|
|
30
|
+
import { prisma, user, post } from "@__QUARK_SCOPE__/db";
|
|
31
|
+
import { loadConfig } from "@__QUARK_SCOPE__/config";
|
|
32
|
+
import { Button, Card, Input } from "@__QUARK_SCOPE__/ui";
|
|
33
|
+
import { JOB_TYPES } from "@__QUARK_SCOPE__/jobs";
|
|
34
|
+
|
|
35
|
+
// ✅ Published runtime - @techstream/quark-core:
|
|
36
|
+
import { AppError, ValidationError, NotFoundError } from "@techstream/quark-core/errors";
|
|
37
|
+
import { createLogger, getCurrentSession } from "@techstream/quark-core";
|
|
38
|
+
import { createQueue, addJob } from "@techstream/quark-core";
|
|
39
|
+
import { metrics, cache, storage } from "@techstream/quark-core";
|
|
40
|
+
|
|
41
|
+
// ❌ Never:
|
|
42
|
+
import { Button } from "@/components/ui/button"; // wrong path convention
|
|
43
|
+
import { prisma } from "@techstream/quark-db"; // wrong scope for workspace pkg
|
|
44
|
+
import something from "@techstream/quark-config"; // wrong scope for workspace pkg
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## UI & Design System
|
|
50
|
+
|
|
51
|
+
- Styling: **Tailwind CSS utility classes only**. No inline styles, no CSS modules.
|
|
52
|
+
- Components from `@__QUARK_SCOPE__/ui`. All accept `className` for overrides.
|
|
53
|
+
- Available: `Button`, `Input`, `Label`, `Textarea`, `Select`, `Checkbox`, `Badge`, `Card`/`CardHeader`/`CardTitle`/`CardContent`/`CardFooter`, `Table`/`TableHeader`/`TableBody`/`TableRow`/`TableHead`/`TableCell`, `Skeleton`, `QuarkLogo` *(server)*, `Dialog` *(client)*, `Toast`/`useToast` *(client)*, `ThemeProvider`/`useTheme` *(client)*.
|
|
54
|
+
- Loading states → `<Skeleton>` + `<Suspense>` boundaries.
|
|
55
|
+
- User feedback → `useToast()` (mark component `"use client"`).
|
|
56
|
+
- Modals → `<Dialog>` (mark parent `"use client"`).
|
|
57
|
+
- Default to **Server Components**. Only add `"use client"` when necessary.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Server Action Pattern
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
"use server";
|
|
65
|
+
import { z } from "zod";
|
|
66
|
+
import { ValidationError, AppError } from "@techstream/quark-core/errors";
|
|
67
|
+
import { getCurrentSession, createLogger } from "@techstream/quark-core";
|
|
68
|
+
import { prisma } from "@__QUARK_SCOPE__/db";
|
|
69
|
+
|
|
70
|
+
const log = createLogger("action:example");
|
|
71
|
+
const schema = z.object({ title: z.string().min(1).max(255) });
|
|
72
|
+
|
|
73
|
+
export async function createExample(formData) {
|
|
74
|
+
const session = await getCurrentSession();
|
|
75
|
+
if (!session) throw new AppError("Unauthorized", 401);
|
|
76
|
+
|
|
77
|
+
const parsed = schema.safeParse(Object.fromEntries(formData));
|
|
78
|
+
if (!parsed.success) throw new ValidationError(parsed.error.flatten());
|
|
79
|
+
|
|
80
|
+
const result = await prisma.example.create({ data: parsed.data });
|
|
81
|
+
log.info("created", { id: result.id });
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## API Route Pattern
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
import { NextResponse } from "next/server";
|
|
92
|
+
import { AppError } from "@techstream/quark-core/errors";
|
|
93
|
+
import { createLogger } from "@techstream/quark-core";
|
|
94
|
+
|
|
95
|
+
const log = createLogger("api:example");
|
|
96
|
+
|
|
97
|
+
export async function GET(request) {
|
|
98
|
+
try {
|
|
99
|
+
return NextResponse.json({ data });
|
|
100
|
+
} catch (error) {
|
|
101
|
+
log.error("request failed", { error });
|
|
102
|
+
if (error instanceof AppError)
|
|
103
|
+
return NextResponse.json({ error: error.message }, { status: error.statusCode });
|
|
104
|
+
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Database
|
|
112
|
+
|
|
113
|
+
- Schema: `packages/db/prisma/schema.prisma`
|
|
114
|
+
- Query helpers: `packages/db/src/queries.js` - add functions here, don't call `prisma.*` directly in components or actions.
|
|
115
|
+
- Always run `pnpm db:generate` after schema changes, then `pnpm db:migrate`.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Auth
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
import { getCurrentSession } from "@techstream/quark-core";
|
|
123
|
+
|
|
124
|
+
const session = await getCurrentSession(); // null if unauthenticated
|
|
125
|
+
if (!session) redirect("/login"); // Server Component
|
|
126
|
+
if (!session) throw new AppError("Unauthorized", 401); // Server Action / API
|
|
127
|
+
if (session.user.role !== "ADMIN") throw new AppError("Forbidden", 403);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Background Jobs
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
// Dispatch (from Server Action or API route):
|
|
136
|
+
import { createQueue, addJob } from "@techstream/quark-core";
|
|
137
|
+
import { JOB_TYPES } from "@__QUARK_SCOPE__/jobs";
|
|
138
|
+
const queue = createQueue("default");
|
|
139
|
+
await addJob(queue, JOB_TYPES.MY_JOB, { userId });
|
|
140
|
+
|
|
141
|
+
// Handle (apps/worker/src/handlers/):
|
|
142
|
+
import { createLogger } from "@techstream/quark-core";
|
|
143
|
+
const log = createLogger("job:my-job");
|
|
144
|
+
export async function handleMyJob({ data }) { log.info("processing", data); }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Testing
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
import { test } from "node:test";
|
|
153
|
+
import assert from "node:assert";
|
|
154
|
+
|
|
155
|
+
test("feature", async (t) => {
|
|
156
|
+
await t.test("does X", async () => {
|
|
157
|
+
assert.strictEqual(actual, expected);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Environment
|
|
165
|
+
|
|
166
|
+
New env vars must be registered in `packages/config/src/validate-env.js` before use. Load config via `loadConfig()` from `@__QUARK_SCOPE__/config`.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Deployment
|
|
171
|
+
|
|
172
|
+
Railway: two services (`web` + `worker`). Migrations auto-run on deploy via `preDeploy` in `.railway/railway.ts`. Env vars managed in Railway dashboard - never committed.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Default Railway runtime variables for __QUARK_PROJECT_NAME__.
|
|
2
|
+
# Copy these values into Railway shared/service variables as a starting point.
|
|
3
|
+
# Railway does not read docker-compose.yml or the local .env example.
|
|
4
|
+
# Add managed PostgreSQL and Redis services in Railway first, then wire the
|
|
5
|
+
# placeholders below with Railway service references or pasted connection
|
|
6
|
+
# strings before the first deploy.
|
|
7
|
+
# Railway injects PORT automatically, so do not set it manually here.
|
|
8
|
+
|
|
9
|
+
# --- Core runtime ---
|
|
10
|
+
NODE_ENV=production
|
|
11
|
+
# Forces the standalone Next.js server to bind on Railway's network interface.
|
|
12
|
+
HOSTNAME=0.0.0.0
|
|
13
|
+
APP_NAME=__QUARK_PROJECT_NAME__
|
|
14
|
+
APP_DESCRIPTION=Update this before production deployment.
|
|
15
|
+
# APP_URL must be an absolute public URL with https://
|
|
16
|
+
APP_URL=https://__QUARK_PROJECT_NAME__.railway.app
|
|
17
|
+
ALLOW_INDEXING=false
|
|
18
|
+
AUTH_ALLOW_SIGNUP=false
|
|
19
|
+
|
|
20
|
+
# --- Auth ---
|
|
21
|
+
# Generate with: openssl rand -base64 32
|
|
22
|
+
# AUTH_SECRET is an alternative name; the deploy CLI auto-sets both.
|
|
23
|
+
# Must be at least 32 characters or startup validation fails.
|
|
24
|
+
NEXTAUTH_SECRET=CHANGE_ME_TO_A_32_CHARACTERS_OR_LONGER_SECRET
|
|
25
|
+
|
|
26
|
+
# APP_URL is the canonical public URL. NEXTAUTH_URL is derived automatically.
|
|
27
|
+
# Uncomment only if you need to override it explicitly.
|
|
28
|
+
# NEXTAUTH_URL=https://__QUARK_PROJECT_NAME__.railway.app
|
|
29
|
+
|
|
30
|
+
# --- Managed infrastructure ---
|
|
31
|
+
# `quark deploy railway` automatically sets DATABASE_URL and REDIS_URL using
|
|
32
|
+
# Railway service references (${{Postgres.DATABASE_URL}}, ${{Redis.REDIS_URL}}).
|
|
33
|
+
# You only need to set these manually if you are not using the CLI deploy flow.
|
|
34
|
+
# DATABASE_URL=postgresql://user:pass@host:5432/db
|
|
35
|
+
# REDIS_URL=redis://user:pass@host:6379
|
|
36
|
+
|
|
37
|
+
# --- Worker ---
|
|
38
|
+
WORKER_CONCURRENCY=5
|
|
39
|
+
|
|
40
|
+
# --- Optional remote seed defaults ---
|
|
41
|
+
# Used only when you intentionally run `pnpm db:seed` against Railway.
|
|
42
|
+
# Remove these after the first seed if you do not want bootstrap admin
|
|
43
|
+
# credentials stored in Railway long term.
|
|
44
|
+
SEED_PROFILE=minimal
|
|
45
|
+
ADMIN_EMAIL=admin@example.com
|
|
46
|
+
ADMIN_PASSWORD=CHANGE_ME_TO_STRONG_ADMIN_PASSWORD
|
|
47
|
+
# ADMIN_NAME=Admin
|
|
48
|
+
|
|
49
|
+
# --- Storage ---
|
|
50
|
+
# Local storage is ephemeral on Railway. Keep this only if uploaded files do not
|
|
51
|
+
# need to survive redeploys or reschedules. For durable uploads, switch to s3.
|
|
52
|
+
STORAGE_PROVIDER=local
|
|
53
|
+
# STORAGE_PROVIDER=s3
|
|
54
|
+
# S3_BUCKET=your-bucket-name
|
|
55
|
+
# S3_REGION=auto
|
|
56
|
+
# S3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
|
|
57
|
+
# S3_ACCESS_KEY_ID=your-access-key
|
|
58
|
+
# S3_SECRET_ACCESS_KEY=your-secret-key
|
|
59
|
+
# S3_PUBLIC_URL=https://your-public-bucket-domain.com
|
|
60
|
+
|
|
61
|
+
# --- Email ---
|
|
62
|
+
# Configure a real provider before enabling email in Railway.
|
|
63
|
+
# EMAIL_PROVIDER=smtp
|
|
64
|
+
# EMAIL_FROM=__QUARK_PROJECT_NAME__ <noreply@yourdomain.com>
|
|
65
|
+
# SMTP_HOST=smtp.example.com
|
|
66
|
+
# SMTP_PORT=587
|
|
67
|
+
# SMTP_SECURE=true
|
|
68
|
+
# SMTP_USER=your_smtp_user
|
|
69
|
+
# SMTP_PASSWORD=your_smtp_password
|
|
70
|
+
# RESEND_API_KEY=re_xxxxxxxxxxxxx
|
|
71
|
+
# ZEPTOMAIL_TOKEN=Zoho-enczapikey your_zeptomail_api_key
|
|
72
|
+
# ZEPTOMAIL_URL=https://api.zeptomail.com
|
|
73
|
+
# ZEPTOMAIL_BOUNCE_EMAIL=bounce@yourdomain.com
|
|
74
|
+
|
|
75
|
+
# --- Optional analytics ---
|
|
76
|
+
# NEXT_PUBLIC_UMAMI_URL=https://umami.example.com
|
|
77
|
+
# NEXT_PUBLIC_UMAMI_WEBSITE_ID=00000000-0000-0000-0000-000000000000
|
|
78
|
+
# NEXT_PUBLIC_UMAMI_REPLAY_ENABLED=false
|
|
79
|
+
|
|
80
|
+
# --- Optional tuning ---
|
|
81
|
+
# LOG_LEVEL=info
|
|
82
|
+
# CACHE_TTL=600
|
|
83
|
+
# RATE_LIMIT_MAX=100
|
|
84
|
+
# RATE_LIMIT_WINDOW_MS=900000
|
|
85
|
+
# API_BODY_SIZE_LIMIT=2097152
|
|
86
|
+
# UPLOAD_SIZE_LIMIT=10485760
|
|
87
|
+
# ASSET_CDN_URL=https://cdn.yourdomain.com
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<skills>
|
|
2
|
+
<skill>
|
|
3
|
+
<name>project-context</name>
|
|
4
|
+
<description>Project-specific context and conventions. This skill evolves with your project - update it as your architecture grows.</description>
|
|
5
|
+
<file>.github/skills/project-context/SKILL.md</file>
|
|
6
|
+
</skill>
|
|
7
|
+
</skills>
|
|
8
|
+
|
|
9
|
+
# __QUARK_PROJECT_NAME__ - Project Conventions
|
|
10
|
+
|
|
11
|
+
> Scaffolded with Quark on __QUARK_SCAFFOLD_DATE__. Package scope: `@__QUARK_SCOPE__`
|
|
12
|
+
> Also see `CLAUDE.md` at the project root for the full context reference.
|
|
13
|
+
|
|
14
|
+
## Non-Negotiable Rules
|
|
15
|
+
|
|
16
|
+
- **ESM only** - `import`/`export` everywhere. Never `require()`.
|
|
17
|
+
- **No authored TypeScript** - `.js` and `.jsx` only. Generated code may emit typed artifacts, but project code should not add `.ts` or `.tsx` sources.
|
|
18
|
+
- **Validate at every boundary** - Zod schemas on all Server Actions and API routes.
|
|
19
|
+
- **Errors** - `AppError` / `ValidationError` from `@techstream/quark-core/errors` in app/runtime code. Native `Error` is acceptable in library, bootstrap, CLI, and test code.
|
|
20
|
+
- **Logging** - `createLogger(name)` from `@techstream/quark-core` in app/runtime code. Console output is acceptable in bootstrap, CLI, and test code.
|
|
21
|
+
- **DB models** - Always add `createdAt` and `updatedAt` to every Prisma model.
|
|
22
|
+
- **Workspace imports** - Use `@__QUARK_SCOPE__/*` for local packages (`db`, `config`, `ui`, `jobs`). Never `@techstream/quark-db` etc.
|
|
23
|
+
- **Tests** - Co-located `*.test.js`, run with `node --test`.
|
|
24
|
+
|
|
25
|
+
## Import Patterns
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// Workspace packages:
|
|
29
|
+
import { prisma, user } from "@__QUARK_SCOPE__/db";
|
|
30
|
+
import { loadConfig } from "@__QUARK_SCOPE__/config";
|
|
31
|
+
import { Button, Card, Input } from "@__QUARK_SCOPE__/ui";
|
|
32
|
+
import { JOB_TYPES } from "@__QUARK_SCOPE__/jobs";
|
|
33
|
+
|
|
34
|
+
// Published runtime:
|
|
35
|
+
import { AppError, ValidationError } from "@techstream/quark-core/errors";
|
|
36
|
+
import { createLogger, getCurrentSession, createQueue, addJob } from "@techstream/quark-core";
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## UI & Design System
|
|
40
|
+
|
|
41
|
+
Components from `@__QUARK_SCOPE__/ui` - Tailwind-only, Server Component safe:
|
|
42
|
+
`Button`, `Input`, `Label`, `Textarea`, `Select`, `Checkbox`, `Badge`,
|
|
43
|
+
`Card`/`CardHeader`/`CardTitle`/`CardContent`/`CardFooter`,
|
|
44
|
+
`Table`/`TableHeader`/`TableBody`/`TableRow`/`TableHead`/`TableCell`,
|
|
45
|
+
`Skeleton`, `ErrorBanner`, `Footer`, `Navbar`/`MobileNavbar`, `RichText`,
|
|
46
|
+
`QuarkLogo` *(server)*, `Dialog` *(client)*, `Toast`/`useToast` *(client)*,
|
|
47
|
+
`ThemeProvider`/`useTheme` *(client)* - dark/light mode context.
|
|
48
|
+
|
|
49
|
+
All accept `className`. Never import from `@/components/ui/*`.
|
|
50
|
+
Inspect `apps/web/src/app/page.js` and `packages/ui/README.md` before creating bespoke public-page layout primitives.
|
|
51
|
+
|
|
52
|
+
## Standard Patterns
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
// Server Action:
|
|
56
|
+
"use server";
|
|
57
|
+
const parsed = schema.safeParse(Object.fromEntries(formData));
|
|
58
|
+
if (!parsed.success) throw new ValidationError(parsed.error.flatten());
|
|
59
|
+
const session = await getCurrentSession();
|
|
60
|
+
if (!session) throw new AppError("Unauthorized", 401);
|
|
61
|
+
|
|
62
|
+
// New env var: register in packages/config/src/validate-env.js first.
|
|
63
|
+
// New DB model: schema.prisma → pnpm db:generate → pnpm db:migrate.
|
|
64
|
+
// New job: define type in packages/jobs/src/index.js, handler in apps/worker/src/handlers/.
|
|
65
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: npm
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
|
|
8
|
+
# Split by semver update type. A single "production" group bundles patch,
|
|
9
|
+
# minor and major bumps into one PR, so a breaking change hides behind a
|
|
10
|
+
# wall of safe patches and gets rubber-stamped. Majors get their own PR.
|
|
11
|
+
groups:
|
|
12
|
+
production-majors:
|
|
13
|
+
dependency-type: production
|
|
14
|
+
update-types: ["major"]
|
|
15
|
+
development-majors:
|
|
16
|
+
dependency-type: development
|
|
17
|
+
update-types: ["major"]
|
|
18
|
+
production-minor:
|
|
19
|
+
dependency-type: production
|
|
20
|
+
update-types: ["minor"]
|
|
21
|
+
production-patch:
|
|
22
|
+
dependency-type: production
|
|
23
|
+
update-types: ["patch"]
|
|
24
|
+
development-minor:
|
|
25
|
+
dependency-type: development
|
|
26
|
+
update-types: ["minor"]
|
|
27
|
+
development-patch:
|
|
28
|
+
dependency-type: development
|
|
29
|
+
update-types: ["patch"]
|
|
30
|
+
|
|
31
|
+
open-pull-requests-limit: 10
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project-context
|
|
3
|
+
description: Project-specific context and conventions. This skill evolves with your project - update it as your architecture grows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Project Context
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
This is a Quark-based full-stack JavaScript application.
|
|
11
|
+
|
|
12
|
+
| Property | Value |
|
|
13
|
+
|---|---|
|
|
14
|
+
| **Scope** | `@__QUARK_SCOPE__` |
|
|
15
|
+
| **Framework** | Quark (scaffolded from `@techstream/quark-create-app`) |
|
|
16
|
+
| **Scaffolded** | __QUARK_SCAFFOLD_DATE__ |
|
|
17
|
+
|
|
18
|
+
## Project Structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
__QUARK_PROJECT_NAME__/
|
|
22
|
+
├── apps/
|
|
23
|
+
│ ├── web/ # Next.js (App Router, Server Actions)
|
|
24
|
+
__QUARK_OPTIONAL_APPS__├── packages/
|
|
25
|
+
│ ├── db/ # Prisma schema, client, queries
|
|
26
|
+
│ ├── config/ # Environment validation & shared config
|
|
27
|
+
__QUARK_OPTIONAL_PACKAGES__├── docker-compose.yml
|
|
28
|
+
├── .env # Local environment (git-ignored)
|
|
29
|
+
└── .env.example # Template for environment variables
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Tech Stack
|
|
33
|
+
|
|
34
|
+
| Layer | Technology |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Runtime | Node.js 22, ES Modules |
|
|
37
|
+
| Package manager | pnpm (workspaces) |
|
|
38
|
+
| Monorepo | Turborepo |
|
|
39
|
+
| Web | Next.js 16 (App Router) |
|
|
40
|
+
| Database | PostgreSQL 16 + Prisma 7 |
|
|
41
|
+
| Queue | BullMQ + Redis 7 |
|
|
42
|
+
| Auth | NextAuth v5 |
|
|
43
|
+
| Validation | Zod 4 |
|
|
44
|
+
| UI | Tailwind CSS + `@__QUARK_SCOPE__/ui` components |
|
|
45
|
+
| Email | Nodemailer |
|
|
46
|
+
| Linting | Biome |
|
|
47
|
+
| Testing | Node.js built-in test runner |
|
|
48
|
+
|
|
49
|
+
## Coding Conventions
|
|
50
|
+
|
|
51
|
+
- **ESM only** - use `import`/`export`, never `require`.
|
|
52
|
+
- **No authored TypeScript** - plain `.js` and `.jsx` files. Generated code may emit typed artifacts, but project code should not add `.ts` or `.tsx` sources.
|
|
53
|
+
- **Imports:** Use `@techstream/quark-core` for published utilities. Use `@__QUARK_SCOPE__/*` for local packages (db, config, ui, jobs).
|
|
54
|
+
- **Tests:** Co-located `*.test.js` files, run with `node --test`.
|
|
55
|
+
- **Validation:** Zod schemas for all Server Actions and API routes.
|
|
56
|
+
- **Errors:** Use `AppError` / `ValidationError` from `@techstream/quark-core/errors` in app/runtime code. Native `Error` is acceptable in library, bootstrap, CLI, and test code.
|
|
57
|
+
- **Logging:** Use `createLogger(name)` from `@techstream/quark-core` in app/runtime code. Console output is acceptable in bootstrap, CLI, and test code.
|
|
58
|
+
- **Database models:** Always include `createdAt`/`updatedAt`.
|
|
59
|
+
- **Environment:** All env vars validated in `packages/config/src/validate-env.js`.
|
|
60
|
+
- **Analytics:** Optional Umami support lives in `apps/web/src/lib/analytics/*`. The public env contract uses only `NEXT_PUBLIC_UMAMI_URL`, `NEXT_PUBLIC_UMAMI_WEBSITE_ID`, and `NEXT_PUBLIC_UMAMI_REPLAY_ENABLED`; replay uses a local rrweb recorder, and dormant helpers exist for dashboard-generated Umami Links, Pixels, and marketing-email snippets.
|
|
61
|
+
|
|
62
|
+
## Common Commands
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm dev # Start all apps in dev mode
|
|
66
|
+
pnpm build # Build everything
|
|
67
|
+
pnpm test # Run all tests
|
|
68
|
+
pnpm lint # Lint with Biome
|
|
69
|
+
pnpm db:generate # Regenerate Prisma client
|
|
70
|
+
pnpm db:push # Push schema changes
|
|
71
|
+
pnpm db:migrate # Run database migrations
|
|
72
|
+
docker compose up -d # Start infrastructure
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Key Files to Know
|
|
76
|
+
|
|
77
|
+
- `packages/db/prisma/schema.prisma` - Database schema (edit this to add models)
|
|
78
|
+
- `packages/db/src/queries.js` - Database query functions
|
|
79
|
+
- `packages/config/src/validate-env.js` - Environment variable validation
|
|
80
|
+
- `apps/web/src/app/` - Next.js App Router pages and API routes
|
|
81
|
+
- `apps/web/src/lib/auth.js` - Authentication configuration
|
|
82
|
+
- `apps/web/src/lib/seo/site-metadata.js` - `getSiteMetadata()` (root layout) and `getPageMetadata()` for per-page titles; see the `seo` skill for the page-title convention
|
|
83
|
+
- `apps/web/src/lib/analytics/umami-config.js` - Optional Umami URL and replay gating
|
|
84
|
+
- `apps/worker/src/handlers/` - Background job handlers
|
|
85
|
+
|
|
86
|
+
## Updating Quark Core
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npx @techstream/quark-create-app update # Update core infrastructure
|
|
90
|
+
pnpm update @techstream/quark-core # Or update directly
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Maintaining This Skill
|
|
96
|
+
|
|
97
|
+
> **Important:** When you make changes that affect this project's architecture,
|
|
98
|
+
> conventions, or structure - such as adding new packages, models, API patterns,
|
|
99
|
+
> environment variables, deployment targets, or team conventions - **update this
|
|
100
|
+
> skill file** to reflect those changes. This ensures future AI interactions
|
|
101
|
+
> always have accurate, up-to-date context.
|
|
102
|
+
>
|
|
103
|
+
> Examples of when to update this file:
|
|
104
|
+
> - Adding a new Prisma model or database table
|
|
105
|
+
> - Introducing a new API route pattern or middleware
|
|
106
|
+
> - Adding or removing a workspace package
|
|
107
|
+
> - Changing deployment infrastructure or CI/CD steps
|
|
108
|
+
> - Establishing new coding conventions or architectural decisions
|
|
109
|
+
> - Adding third-party integrations or services
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- "**/*.md"
|
|
8
|
+
- "docs/**"
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths-ignore:
|
|
12
|
+
- "**/*.md"
|
|
13
|
+
- "docs/**"
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: ci-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
lint:
|
|
25
|
+
name: Lint
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- uses: pnpm/action-setup@v4
|
|
31
|
+
|
|
32
|
+
- uses: actions/setup-node@v4
|
|
33
|
+
with:
|
|
34
|
+
node-version: 22
|
|
35
|
+
cache: pnpm
|
|
36
|
+
|
|
37
|
+
- run: pnpm install --frozen-lockfile
|
|
38
|
+
|
|
39
|
+
- run: pnpm lint
|
|
40
|
+
|
|
41
|
+
- run: pnpm standards
|
|
42
|
+
|
|
43
|
+
test:
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
name: Test
|
|
46
|
+
services:
|
|
47
|
+
postgres:
|
|
48
|
+
image: postgres:16-alpine
|
|
49
|
+
env:
|
|
50
|
+
POSTGRES_USER: postgres
|
|
51
|
+
POSTGRES_PASSWORD: postgres
|
|
52
|
+
POSTGRES_DB: app_test
|
|
53
|
+
ports:
|
|
54
|
+
- 5432:5432
|
|
55
|
+
options: >-
|
|
56
|
+
--health-cmd="pg_isready -U postgres"
|
|
57
|
+
--health-interval=5s
|
|
58
|
+
--health-timeout=5s
|
|
59
|
+
--health-retries=5
|
|
60
|
+
redis:
|
|
61
|
+
image: redis:7-alpine
|
|
62
|
+
ports:
|
|
63
|
+
- 6379:6379
|
|
64
|
+
options: >-
|
|
65
|
+
--health-cmd="redis-cli ping"
|
|
66
|
+
--health-interval=5s
|
|
67
|
+
--health-timeout=5s
|
|
68
|
+
--health-retries=5
|
|
69
|
+
env:
|
|
70
|
+
POSTGRES_USER: postgres
|
|
71
|
+
POSTGRES_PASSWORD: postgres
|
|
72
|
+
POSTGRES_HOST: localhost
|
|
73
|
+
POSTGRES_PORT: "5432"
|
|
74
|
+
POSTGRES_DB: app_test
|
|
75
|
+
REDIS_HOST: localhost
|
|
76
|
+
REDIS_PORT: "6379"
|
|
77
|
+
NEXTAUTH_SECRET: ci-test-secret-must-be-at-least-32-characters-long
|
|
78
|
+
NODE_ENV: test
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
|
|
82
|
+
- uses: pnpm/action-setup@v4
|
|
83
|
+
|
|
84
|
+
- uses: actions/setup-node@v4
|
|
85
|
+
with:
|
|
86
|
+
node-version: 22
|
|
87
|
+
cache: pnpm
|
|
88
|
+
|
|
89
|
+
- run: pnpm install --frozen-lockfile
|
|
90
|
+
|
|
91
|
+
- run: pnpm db:generate
|
|
92
|
+
|
|
93
|
+
- run: pnpm test
|
|
94
|
+
|
|
95
|
+
build:
|
|
96
|
+
name: Build
|
|
97
|
+
needs: [lint, test]
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/checkout@v4
|
|
102
|
+
|
|
103
|
+
- uses: pnpm/action-setup@v4
|
|
104
|
+
|
|
105
|
+
- uses: actions/setup-node@v4
|
|
106
|
+
with:
|
|
107
|
+
node-version: 22
|
|
108
|
+
cache: pnpm
|
|
109
|
+
|
|
110
|
+
- run: pnpm install --frozen-lockfile
|
|
111
|
+
|
|
112
|
+
- run: pnpm db:generate
|
|
113
|
+
|
|
114
|
+
- run: pnpm doctor:ci
|
|
115
|
+
|
|
116
|
+
- run: pnpm build
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Auto-merge Dependabot
|
|
2
|
+
|
|
3
|
+
on: pull_request
|
|
4
|
+
|
|
5
|
+
permissions:
|
|
6
|
+
contents: write
|
|
7
|
+
pull-requests: write
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
auto-merge:
|
|
11
|
+
if: github.actor == 'dependabot[bot]'
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: dependabot/fetch-metadata@v2
|
|
15
|
+
id: meta
|
|
16
|
+
|
|
17
|
+
- name: Auto-merge patch updates
|
|
18
|
+
if: steps.meta.outputs.update-type == 'version-update:semver-patch'
|
|
19
|
+
run: gh pr merge "$PR_URL" --auto --squash
|
|
20
|
+
env:
|
|
21
|
+
PR_URL: ${{ github.event.pull_request.html_url }}
|
|
22
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Install (Windows)
|
|
2
|
+
|
|
3
|
+
# Windows runners bill at 2x the Linux rate. This workflow only proves that
|
|
4
|
+
# `pnpm install` resolves the lockfile, which the Linux CI jobs already cover,
|
|
5
|
+
# so it runs on demand only rather than on every push and pull request.
|
|
6
|
+
on:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
install-windows:
|
|
14
|
+
name: Install (Windows)
|
|
15
|
+
runs-on: windows-latest
|
|
16
|
+
timeout-minutes: 10
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- uses: pnpm/action-setup@v4
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: 22
|
|
25
|
+
cache: pnpm
|
|
26
|
+
|
|
27
|
+
- run: pnpm install --frozen-lockfile
|