create-skit 0.1.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.
Files changed (195) hide show
  1. package/README.md +36 -0
  2. package/bin/create-skit.mjs +1064 -0
  3. package/lib/module-application.mjs +281 -0
  4. package/lib/module-resolver.mjs +179 -0
  5. package/modules/README.md +22 -0
  6. package/modules/ai-dx/files/AGENTS.md +116 -0
  7. package/modules/ai-dx/files/ARCHITECTURE.md +103 -0
  8. package/modules/ai-dx/module.json +14 -0
  9. package/modules/ai-dx-claude/files/CLAUDE.md +8 -0
  10. package/modules/ai-dx-claude/module.json +13 -0
  11. package/modules/ai-dx-cursor/files/.cursor/rules/auth.mdc +53 -0
  12. package/modules/ai-dx-cursor/files/.cursor/rules/database.mdc +48 -0
  13. package/modules/ai-dx-cursor/files/.cursor/rules/env.mdc +43 -0
  14. package/modules/ai-dx-cursor/files/.cursor/rules/nextjs.mdc +58 -0
  15. package/modules/ai-dx-cursor/files/.cursor/rules/project.mdc +33 -0
  16. package/modules/ai-dx-cursor/files/.cursor/rules/testing.mdc +55 -0
  17. package/modules/ai-dx-cursor/module.json +18 -0
  18. package/modules/ai-dx-gemini/files/.gemini/GEMINI.md +5 -0
  19. package/modules/ai-dx-gemini/module.json +13 -0
  20. package/modules/auth-core/module.json +8 -0
  21. package/modules/auth-github/module.json +20 -0
  22. package/modules/billing-polar/module.json +20 -0
  23. package/modules/billing-stripe/module.json +23 -0
  24. package/modules/dashboard-shell/files/src/app/globals.css +756 -0
  25. package/modules/dashboard-shell/files/src/app/settings/page.tsx +67 -0
  26. package/modules/dashboard-shell/module.json +11 -0
  27. package/modules/db-pg/module.json +21 -0
  28. package/modules/db-postgresjs/module.json +21 -0
  29. package/modules/deploy-docker/files/.dockerignore +19 -0
  30. package/modules/deploy-docker/files/Dockerfile +25 -0
  31. package/modules/deploy-docker/module.json +11 -0
  32. package/modules/email-resend/module.json +21 -0
  33. package/modules/quality-baseline/module.json +8 -0
  34. package/modules/testing-baseline/module.json +8 -0
  35. package/package.json +40 -0
  36. package/presets/README.md +12 -0
  37. package/presets/blank.json +67 -0
  38. package/presets/dashboard.json +67 -0
  39. package/templates/base-web/.env.example +17 -0
  40. package/templates/base-web/.github/workflows/ci.yml +34 -0
  41. package/templates/base-web/.husky/pre-commit +3 -0
  42. package/templates/base-web/.husky/pre-push +3 -0
  43. package/templates/base-web/.prettierignore +3 -0
  44. package/templates/base-web/README.md +42 -0
  45. package/templates/base-web/drizzle.config.ts +16 -0
  46. package/templates/base-web/eslint.config.mjs +127 -0
  47. package/templates/base-web/manifest.json +5 -0
  48. package/templates/base-web/next-env.d.ts +4 -0
  49. package/templates/base-web/next.config.ts +5 -0
  50. package/templates/base-web/package.json +75 -0
  51. package/templates/base-web/playwright.config.ts +21 -0
  52. package/templates/base-web/prettier.config.mjs +9 -0
  53. package/templates/base-web/proxy.ts +23 -0
  54. package/templates/base-web/src/app/api/auth/[...all]/route.ts +5 -0
  55. package/templates/base-web/src/app/api/billing/checkout/route.ts +26 -0
  56. package/templates/base-web/src/app/api/billing/portal/route.ts +25 -0
  57. package/templates/base-web/src/app/api/email/test/route.ts +28 -0
  58. package/templates/base-web/src/app/api/webhooks/polar/route.ts +5 -0
  59. package/templates/base-web/src/app/api/webhooks/stripe/route.ts +5 -0
  60. package/templates/base-web/src/app/billing/page.tsx +55 -0
  61. package/templates/base-web/src/app/dashboard/page.tsx +15 -0
  62. package/templates/base-web/src/app/email/page.tsx +46 -0
  63. package/templates/base-web/src/app/error.tsx +27 -0
  64. package/templates/base-web/src/app/globals.css +534 -0
  65. package/templates/base-web/src/app/layout.tsx +19 -0
  66. package/templates/base-web/src/app/llms-full.txt/route.ts +158 -0
  67. package/templates/base-web/src/app/llms.txt/route.ts +59 -0
  68. package/templates/base-web/src/app/loading.tsx +24 -0
  69. package/templates/base-web/src/app/not-found.tsx +16 -0
  70. package/templates/base-web/src/app/page.tsx +5 -0
  71. package/templates/base-web/src/app/sign-in/page.tsx +14 -0
  72. package/templates/base-web/src/app/sign-up/page.tsx +14 -0
  73. package/templates/base-web/src/components/auth/email-auth-form.test.tsx +40 -0
  74. package/templates/base-web/src/components/auth/email-auth-form.tsx +128 -0
  75. package/templates/base-web/src/components/auth/sign-out-button.tsx +29 -0
  76. package/templates/base-web/src/db/index.ts +16 -0
  77. package/templates/base-web/src/db/schema/auth.ts +4 -0
  78. package/templates/base-web/src/db/schema/index.ts +2 -0
  79. package/templates/base-web/src/db/schema/projects.ts +17 -0
  80. package/templates/base-web/src/db/seeds/index.ts +32 -0
  81. package/templates/base-web/src/lib/auth-client.ts +5 -0
  82. package/templates/base-web/src/lib/auth-session.ts +21 -0
  83. package/templates/base-web/src/lib/auth.ts +23 -0
  84. package/templates/base-web/src/lib/billing/index.ts +37 -0
  85. package/templates/base-web/src/lib/billing/providers/polar.ts +80 -0
  86. package/templates/base-web/src/lib/billing/providers/stripe.ts +77 -0
  87. package/templates/base-web/src/lib/billing/types.ts +25 -0
  88. package/templates/base-web/src/lib/email/index.ts +19 -0
  89. package/templates/base-web/src/lib/email/templates.test.ts +12 -0
  90. package/templates/base-web/src/lib/email/templates.ts +40 -0
  91. package/templates/base-web/src/lib/env.ts +83 -0
  92. package/templates/base-web/tests/e2e/home.spec.ts +8 -0
  93. package/templates/base-web/tsconfig.json +34 -0
  94. package/templates/base-web/vitest.config.ts +19 -0
  95. package/templates/blank/.env.example +16 -0
  96. package/templates/blank/.github/workflows/ci.yml +34 -0
  97. package/templates/blank/.husky/pre-commit +3 -0
  98. package/templates/blank/.husky/pre-push +3 -0
  99. package/templates/blank/.prettierignore +3 -0
  100. package/templates/blank/drizzle.config.ts +16 -0
  101. package/templates/blank/eslint.config.mjs +127 -0
  102. package/templates/blank/next-env.d.ts +4 -0
  103. package/templates/blank/next.config.ts +5 -0
  104. package/templates/blank/package.json +75 -0
  105. package/templates/blank/playwright.config.ts +21 -0
  106. package/templates/blank/prettier.config.mjs +9 -0
  107. package/templates/blank/proxy.ts +28 -0
  108. package/templates/blank/src/app/api/auth/[...all]/route.ts +5 -0
  109. package/templates/blank/src/app/api/billing/checkout/route.ts +26 -0
  110. package/templates/blank/src/app/api/billing/portal/route.ts +25 -0
  111. package/templates/blank/src/app/api/email/test/route.ts +28 -0
  112. package/templates/blank/src/app/api/webhooks/polar/route.ts +5 -0
  113. package/templates/blank/src/app/api/webhooks/stripe/route.ts +5 -0
  114. package/templates/blank/src/app/billing/page.tsx +70 -0
  115. package/templates/blank/src/app/email/page.tsx +46 -0
  116. package/templates/blank/src/app/globals.css +394 -0
  117. package/templates/blank/src/app/layout.tsx +19 -0
  118. package/templates/blank/src/app/page.tsx +23 -0
  119. package/templates/blank/src/app/sign-in/page.tsx +18 -0
  120. package/templates/blank/src/app/sign-up/page.tsx +18 -0
  121. package/templates/blank/src/components/auth/email-auth-form.test.tsx +39 -0
  122. package/templates/blank/src/components/auth/email-auth-form.tsx +109 -0
  123. package/templates/blank/src/components/auth/sign-out-button.tsx +29 -0
  124. package/templates/blank/src/db/index.ts +16 -0
  125. package/templates/blank/src/db/schema/auth.ts +4 -0
  126. package/templates/blank/src/db/schema/index.ts +2 -0
  127. package/templates/blank/src/db/schema/projects.ts +17 -0
  128. package/templates/blank/src/db/seeds/index.ts +28 -0
  129. package/templates/blank/src/lib/auth-client.ts +5 -0
  130. package/templates/blank/src/lib/auth-session.ts +11 -0
  131. package/templates/blank/src/lib/auth.ts +23 -0
  132. package/templates/blank/src/lib/billing/index.ts +37 -0
  133. package/templates/blank/src/lib/billing/providers/polar.ts +80 -0
  134. package/templates/blank/src/lib/billing/providers/stripe.ts +77 -0
  135. package/templates/blank/src/lib/billing/types.ts +25 -0
  136. package/templates/blank/src/lib/email/index.ts +19 -0
  137. package/templates/blank/src/lib/email/templates.test.ts +15 -0
  138. package/templates/blank/src/lib/email/templates.ts +40 -0
  139. package/templates/blank/src/lib/env.ts +80 -0
  140. package/templates/blank/tsconfig.json +34 -0
  141. package/templates/blank/vitest.config.ts +19 -0
  142. package/templates/dashboard/.env.example +16 -0
  143. package/templates/dashboard/.github/workflows/ci.yml +34 -0
  144. package/templates/dashboard/.husky/pre-commit +3 -0
  145. package/templates/dashboard/.husky/pre-push +3 -0
  146. package/templates/dashboard/.prettierignore +3 -0
  147. package/templates/dashboard/drizzle.config.ts +16 -0
  148. package/templates/dashboard/eslint.config.mjs +127 -0
  149. package/templates/dashboard/next-env.d.ts +4 -0
  150. package/templates/dashboard/next.config.ts +5 -0
  151. package/templates/dashboard/package.json +75 -0
  152. package/templates/dashboard/playwright.config.ts +21 -0
  153. package/templates/dashboard/prettier.config.mjs +9 -0
  154. package/templates/dashboard/proxy.ts +36 -0
  155. package/templates/dashboard/src/app/api/auth/[...all]/route.ts +5 -0
  156. package/templates/dashboard/src/app/api/billing/checkout/route.ts +26 -0
  157. package/templates/dashboard/src/app/api/billing/portal/route.ts +25 -0
  158. package/templates/dashboard/src/app/api/email/test/route.ts +28 -0
  159. package/templates/dashboard/src/app/api/webhooks/polar/route.ts +5 -0
  160. package/templates/dashboard/src/app/api/webhooks/stripe/route.ts +5 -0
  161. package/templates/dashboard/src/app/billing/layout.tsx +22 -0
  162. package/templates/dashboard/src/app/billing/page.tsx +73 -0
  163. package/templates/dashboard/src/app/dashboard/layout.tsx +22 -0
  164. package/templates/dashboard/src/app/dashboard/page.tsx +104 -0
  165. package/templates/dashboard/src/app/email/layout.tsx +22 -0
  166. package/templates/dashboard/src/app/email/page.tsx +54 -0
  167. package/templates/dashboard/src/app/globals.css +1357 -0
  168. package/templates/dashboard/src/app/layout.tsx +25 -0
  169. package/templates/dashboard/src/app/page.tsx +154 -0
  170. package/templates/dashboard/src/app/settings/layout.tsx +22 -0
  171. package/templates/dashboard/src/app/settings/page.tsx +85 -0
  172. package/templates/dashboard/src/app/sign-in/page.tsx +47 -0
  173. package/templates/dashboard/src/app/sign-up/page.tsx +47 -0
  174. package/templates/dashboard/src/components/auth/email-auth-form.test.tsx +39 -0
  175. package/templates/dashboard/src/components/auth/email-auth-form.tsx +160 -0
  176. package/templates/dashboard/src/components/auth/sign-out-button.tsx +29 -0
  177. package/templates/dashboard/src/components/dashboard/shell.tsx +158 -0
  178. package/templates/dashboard/src/db/index.ts +16 -0
  179. package/templates/dashboard/src/db/schema/auth.ts +4 -0
  180. package/templates/dashboard/src/db/schema/index.ts +2 -0
  181. package/templates/dashboard/src/db/schema/projects.ts +17 -0
  182. package/templates/dashboard/src/db/seeds/index.ts +28 -0
  183. package/templates/dashboard/src/lib/auth-client.ts +5 -0
  184. package/templates/dashboard/src/lib/auth-session.ts +11 -0
  185. package/templates/dashboard/src/lib/auth.ts +41 -0
  186. package/templates/dashboard/src/lib/billing/index.ts +37 -0
  187. package/templates/dashboard/src/lib/billing/providers/polar.ts +80 -0
  188. package/templates/dashboard/src/lib/billing/providers/stripe.ts +77 -0
  189. package/templates/dashboard/src/lib/billing/types.ts +25 -0
  190. package/templates/dashboard/src/lib/email/index.ts +19 -0
  191. package/templates/dashboard/src/lib/email/templates.test.ts +15 -0
  192. package/templates/dashboard/src/lib/email/templates.ts +40 -0
  193. package/templates/dashboard/src/lib/env.ts +88 -0
  194. package/templates/dashboard/tsconfig.json +34 -0
  195. package/templates/dashboard/vitest.config.ts +19 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "ai-dx",
3
+ "kind": "developer-experience",
4
+ "description": "Shared AI agent baseline: AGENTS.md and ARCHITECTURE.md for all tools.",
5
+ "dependsOn": ["quality-baseline"],
6
+ "conflictsWith": [],
7
+ "replaces": [],
8
+ "template": {
9
+ "copyFiles": [
10
+ "AGENTS.md",
11
+ "ARCHITECTURE.md"
12
+ ]
13
+ }
14
+ }
@@ -0,0 +1,8 @@
1
+ @AGENTS.md
2
+
3
+ ## Claude Code
4
+
5
+ - Use `/compact` when context gets long
6
+ - Workflow: explore → plan → code → verify → commit
7
+ - Run `pnpm typecheck && pnpm lint:fix` after every change set
8
+ - Prefer reading existing code before generating — patterns are consistent
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "ai-dx-claude",
3
+ "kind": "developer-experience",
4
+ "description": "Claude Code configuration: CLAUDE.md with project-specific workflow.",
5
+ "dependsOn": ["ai-dx"],
6
+ "conflictsWith": [],
7
+ "replaces": [],
8
+ "template": {
9
+ "copyFiles": [
10
+ "CLAUDE.md"
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,53 @@
1
+ ---
2
+ description: Better Auth patterns for authentication and session management
3
+ globs: src/lib/auth*, src/app/sign-*/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Authentication (Better Auth)
8
+
9
+ ## Server-side Session
10
+
11
+ ```ts
12
+ import { getSession } from "@/lib/auth-session";
13
+
14
+ const session = await getSession();
15
+ // session is { user, session } | null
16
+ if (!session) {
17
+ redirect("/sign-in");
18
+ }
19
+ ```
20
+
21
+ ## Client-side Auth
22
+
23
+ ```tsx
24
+ "use client";
25
+
26
+ import { authClient } from "@/lib/auth-client";
27
+
28
+ // Sign in
29
+ await authClient.signIn.email({ email, password });
30
+
31
+ // Sign out
32
+ await authClient.signOut();
33
+
34
+ // Get session (client hook)
35
+ const { data: session } = authClient.useSession();
36
+ ```
37
+
38
+ ## Config
39
+
40
+ - Server config: `src/lib/auth.ts` (server-only, uses Drizzle adapter)
41
+ - Client config: `src/lib/auth-client.ts`
42
+ - Auth schema: `src/db/schema/auth.ts` (auto-generated via `pnpm auth:generate`)
43
+ - API handler: `src/app/api/auth/[...all]/route.ts`
44
+
45
+ ## Route Protection
46
+
47
+ `proxy.ts` checks for session cookies and redirects unauthenticated users. Protected routes are listed in the matcher config there.
48
+
49
+ ## Adding Social Providers
50
+
51
+ 1. Add provider config in `src/lib/auth.ts`
52
+ 2. Add env vars in `src/lib/env.ts`
53
+ 3. Add UI button in the auth form component
@@ -0,0 +1,48 @@
1
+ ---
2
+ description: Drizzle ORM database patterns and migration workflow
3
+ globs: src/db/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Database (Drizzle ORM + PostgreSQL)
8
+
9
+ ## Connection
10
+
11
+ `src/db/index.ts` exports `db`. It is `server-only` — never import in client components.
12
+
13
+ ## Schema
14
+
15
+ Define tables in `src/db/schema/`, re-export from `src/db/schema/index.ts`.
16
+
17
+ ```ts
18
+ import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
19
+
20
+ export const widgets = pgTable("widgets", {
21
+ id: uuid("id").primaryKey().defaultRandom(),
22
+ name: text("name").notNull(),
23
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull()
24
+ });
25
+ ```
26
+
27
+ ## Queries
28
+
29
+ ```ts
30
+ import { db } from "@/db";
31
+ import { widgets } from "@/db/schema";
32
+ import { eq } from "drizzle-orm";
33
+
34
+ const all = await db.select().from(widgets);
35
+ const one = await db.select().from(widgets).where(eq(widgets.id, id));
36
+ await db.insert(widgets).values({ name: "New" });
37
+ ```
38
+
39
+ ## Migration Workflow
40
+
41
+ 1. Edit or create schema files
42
+ 2. `pnpm db:generate` — creates SQL migration
43
+ 3. `pnpm db:migrate` — applies to database
44
+ 4. `pnpm db:push` — alternative: push without migration files (dev only)
45
+
46
+ ## Seeds
47
+
48
+ Add seed logic in `src/db/seeds/index.ts`, run with `pnpm db:seed`.
@@ -0,0 +1,43 @@
1
+ ---
2
+ description: Environment variable validation with Zod
3
+ globs: src/lib/env.ts, .env*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Environment Variables
8
+
9
+ All env access goes through `src/lib/env.ts`. Direct `process.env` is banned by ESLint in every other file.
10
+
11
+ ## How It Works
12
+
13
+ 1. Zod schema validates every variable at runtime
14
+ 2. `readRequiredValue()` provides safe build-time defaults so `next build` succeeds without real secrets
15
+ 3. Lazy singleton — parsed once, cached
16
+ 4. Proxy export — `env.MY_VAR` reads lazily
17
+
18
+ ## Adding a New Variable
19
+
20
+ 1. Add Zod field to `envSchema`:
21
+ ```ts
22
+ MY_VAR: z.string().min(1).optional(),
23
+ ```
24
+
25
+ 2. Add to `parseEnv()`:
26
+ ```ts
27
+ MY_VAR: process.env.MY_VAR,
28
+ ```
29
+
30
+ 3. Add default to `.env.example`:
31
+ ```
32
+ MY_VAR=example_value
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```ts
38
+ import { env } from "@/lib/env";
39
+
40
+ const url = env.DATABASE_URL;
41
+ ```
42
+
43
+ Never do `process.env.DATABASE_URL` — ESLint will error.
@@ -0,0 +1,58 @@
1
+ ---
2
+ description: Next.js App Router patterns and conventions
3
+ globs: src/**/*.tsx, src/**/*.ts
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Next.js Patterns
8
+
9
+ Read bundled docs at `node_modules/next/dist/docs/` before writing Next.js code.
10
+
11
+ ## Server Components (default)
12
+
13
+ ```tsx
14
+ import { getSession } from "@/lib/auth-session";
15
+
16
+ export default async function Page() {
17
+ const session = await getSession();
18
+ return <main>{/* render with session data */}</main>;
19
+ }
20
+ ```
21
+
22
+ ## Client Components (opt-in)
23
+
24
+ Only when hooks, event handlers, or browser APIs are needed:
25
+
26
+ ```tsx
27
+ "use client";
28
+
29
+ import { useState } from "react";
30
+
31
+ export function Counter() {
32
+ const [count, setCount] = useState(0);
33
+ return <button onClick={() => setCount(count + 1)}>{count}</button>;
34
+ }
35
+ ```
36
+
37
+ ## API Routes
38
+
39
+ ```tsx
40
+ import { NextResponse } from "next/server";
41
+
42
+ export async function POST(request: Request) {
43
+ const body = await request.json();
44
+ return NextResponse.json({ ok: true });
45
+ }
46
+ ```
47
+
48
+ ## Route Protection
49
+
50
+ `proxy.ts` handles auth redirects at the edge. To protect a new route, add it to both the condition and the matcher array in that file.
51
+
52
+ ## Metadata
53
+
54
+ Use the `metadata` export in `layout.tsx` or `page.tsx`:
55
+
56
+ ```tsx
57
+ export const metadata = { title: "Page Title" };
58
+ ```
@@ -0,0 +1,33 @@
1
+ ---
2
+ description: Project-wide conventions for this Launchframe-generated app
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # Project Conventions
8
+
9
+ ## Stack
10
+
11
+ Next.js 16 · React 19 · TypeScript 5.9 (strict) · Drizzle ORM · Better Auth · Vitest · Playwright
12
+
13
+ ## Style
14
+
15
+ - Double quotes, semicolons, no trailing commas, 88-char line width (Prettier)
16
+ - `type` imports: `import { type Foo }` — enforced by ESLint
17
+ - Path alias: `@/*` maps to `./src/*`
18
+ - Import order: builtin → external → internal (`@/**`) → relative (enforced, auto-fixable)
19
+
20
+ ## Rules
21
+
22
+ - Server components by default. Only add `"use client"` when hooks or browser APIs are required.
23
+ - Keep route files (`page.tsx`) thin — delegate logic to `src/lib/`.
24
+ - All env access goes through `src/lib/env.ts`. Direct `process.env` is banned by ESLint everywhere else.
25
+ - Run `pnpm typecheck && pnpm lint:fix` after changes.
26
+
27
+ ## Where to Look
28
+
29
+ - Routes: `src/app/`
30
+ - Business logic: `src/lib/`
31
+ - Database: `src/db/`
32
+ - Tests: `src/**/*.test.{ts,tsx}` (unit), `tests/e2e/` (e2e)
33
+ - Middleware: `proxy.ts`
@@ -0,0 +1,55 @@
1
+ ---
2
+ description: Vitest unit tests and Playwright E2E test conventions
3
+ globs: src/**/*.test.*, tests/**
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Testing
8
+
9
+ ## Unit Tests (Vitest)
10
+
11
+ Location: `src/**/*.test.{ts,tsx}` — colocated next to the file they test.
12
+
13
+ ```ts
14
+ import { describe, it, expect } from "vitest";
15
+
16
+ describe("myFunction", () => {
17
+ it("returns expected value", () => {
18
+ expect(myFunction("input")).toBe("output");
19
+ });
20
+ });
21
+ ```
22
+
23
+ For React components, use `@testing-library/react`:
24
+
25
+ ```tsx
26
+ import { render, screen } from "@testing-library/react";
27
+
28
+ it("renders heading", () => {
29
+ render(<MyComponent />);
30
+ expect(screen.getByRole("heading")).toHaveTextContent("Title");
31
+ });
32
+ ```
33
+
34
+ Run: `pnpm test` (single run) or `pnpm test:watch` (watch mode).
35
+
36
+ ## E2E Tests (Playwright)
37
+
38
+ Location: `tests/e2e/*.spec.ts`
39
+
40
+ ```ts
41
+ import { test, expect } from "@playwright/test";
42
+
43
+ test("home page loads", async ({ page }) => {
44
+ await page.goto("/");
45
+ await expect(page.getByRole("heading")).toBeVisible();
46
+ });
47
+ ```
48
+
49
+ Run: `pnpm test:e2e` (headless) or `pnpm test:e2e:headed` (with browser).
50
+
51
+ Playwright auto-starts the dev server via `playwright.config.ts`.
52
+
53
+ ## Pre-commit
54
+
55
+ The Husky pre-commit hook runs `pnpm lint-staged && pnpm typecheck`. Tests run on pre-push.
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "ai-dx-cursor",
3
+ "kind": "developer-experience",
4
+ "description": "Cursor IDE rules: modular .mdc files auto-activated by file pattern.",
5
+ "dependsOn": ["ai-dx"],
6
+ "conflictsWith": [],
7
+ "replaces": [],
8
+ "template": {
9
+ "copyFiles": [
10
+ ".cursor/rules/project.mdc",
11
+ ".cursor/rules/nextjs.mdc",
12
+ ".cursor/rules/database.mdc",
13
+ ".cursor/rules/auth.mdc",
14
+ ".cursor/rules/testing.mdc",
15
+ ".cursor/rules/env.mdc"
16
+ ]
17
+ }
18
+ }
@@ -0,0 +1,5 @@
1
+ # Gemini Code Assist
2
+
3
+ Check for the presence of `AGENTS.md` in the project root for full project conventions, tech stack, commands, and code patterns.
4
+
5
+ There is also an `ARCHITECTURE.md` with directory structure and request flow documentation.
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "ai-dx-gemini",
3
+ "kind": "developer-experience",
4
+ "description": "Gemini Code Assist configuration: .gemini/GEMINI.md pointing to shared AGENTS.md.",
5
+ "dependsOn": ["ai-dx"],
6
+ "conflictsWith": [],
7
+ "replaces": [],
8
+ "template": {
9
+ "copyFiles": [
10
+ ".gemini/GEMINI.md"
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "auth-core",
3
+ "kind": "auth",
4
+ "description": "Better Auth baseline with protected routes and auth pages.",
5
+ "dependsOn": ["quality-baseline", "testing-baseline"],
6
+ "conflictsWith": [],
7
+ "replaces": []
8
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "auth-github",
3
+ "kind": "auth",
4
+ "description": "GitHub OAuth provider for Better Auth.",
5
+ "dependsOn": ["auth-core"],
6
+ "conflictsWith": [],
7
+ "replaces": [],
8
+ "template": {
9
+ "tokenReplacements": {
10
+ "__AUTH_PROVIDER_ENV_EXAMPLE__": "GITHUB_CLIENT_ID=github_oauth_client_id\nGITHUB_CLIENT_SECRET=github_oauth_client_secret",
11
+ "__AUTH_PROVIDER_ENV_SCHEMA__": " GITHUB_CLIENT_ID: z.string().min(1).optional(),\n GITHUB_CLIENT_SECRET: z.string().min(1).optional(),",
12
+ "__AUTH_PROVIDER_ENV_VALUES__": " GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,\n GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,",
13
+ "__AUTH_SOCIAL_PROVIDERS_BLOCK__": ",\n socialProviders: {\n github: {\n clientId: env.GITHUB_CLIENT_ID ?? \"\",\n clientSecret: env.GITHUB_CLIENT_SECRET ?? \"\"\n }\n }",
14
+ "__AUTH_SOCIAL_BUTTON_HANDLER__": "\n async function handleGithubSignIn() {\n setIsPending(true);\n setError(null);\n\n try {\n const result = await authClient.signIn.social({\n provider: \"github\",\n callbackURL: \"/dashboard\"\n });\n\n if (result.error) {\n setError(result.error.message ?? \"GitHub sign-in failed.\");\n }\n } catch {\n setError(\"GitHub sign-in failed.\");\n } finally {\n setIsPending(false);\n }\n }\n",
15
+ "__AUTH_SOCIAL_BUTTON__": "\n <div className=\"auth-separator\" aria-hidden=\"true\">\n <span>or continue with</span>\n </div>\n\n <button\n type=\"button\"\n className=\"auth-social-button\"\n onClick={() => {\n void handleGithubSignIn();\n }}\n disabled={isPending}\n >\n {isPending ? \"Working...\" : \"Continue with GitHub\"}\n </button>",
16
+ "__AUTH_SOCIAL_TEST_ASSERTION__": "\n expect(screen.getByRole(\"button\", { name: /continue with github/i })).toBeTruthy();",
17
+ "__AUTH_LLMS_EXTRA__": ", GitHub OAuth"
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "billing-polar",
3
+ "kind": "billing",
4
+ "description": "Polar billing provider integration.",
5
+ "dependsOn": ["auth-core"],
6
+ "conflictsWith": [],
7
+ "replaces": [],
8
+ "template": {
9
+ "billingProviders": ["polar"],
10
+ "billing": {
11
+ "imports": [
12
+ "import { PolarBillingProvider } from \"./providers/polar\";"
13
+ ],
14
+ "factories": [
15
+ " polar: () => new PolarBillingProvider(),"
16
+ ],
17
+ "polarWebhookRouteBody": " const provider = getBillingProvider(\"polar\");\n const rawBody = await request.text();\n\n await provider.handleWebhook({\n headers: request.headers,\n rawBody\n });\n\n return Response.json({ received: true });"
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "billing-stripe",
3
+ "kind": "billing",
4
+ "description": "Stripe billing provider integration.",
5
+ "dependsOn": ["auth-core"],
6
+ "conflictsWith": [],
7
+ "replaces": [],
8
+ "template": {
9
+ "billingProviders": ["stripe"],
10
+ "packageDependencies": [
11
+ " \"stripe\": \"18.5.0\","
12
+ ],
13
+ "billing": {
14
+ "imports": [
15
+ "import { StripeBillingProvider } from \"./providers/stripe\";"
16
+ ],
17
+ "factories": [
18
+ " stripe: () => new StripeBillingProvider(),"
19
+ ],
20
+ "stripeWebhookRouteBody": " const provider = getBillingProvider(\"stripe\");\n const rawBody = await request.text();\n\n await provider.handleWebhook({\n headers: request.headers,\n rawBody\n });\n\n return Response.json({ received: true });"
21
+ }
22
+ }
23
+ }