@alfredmouelle/create-stack 0.1.1 → 0.2.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 (127) hide show
  1. package/README.md +41 -18
  2. package/_stack/apps/next-base/.turbo/turbo-typecheck.log +1 -0
  3. package/_stack/apps/next-base/.vscode/settings.json +35 -0
  4. package/_stack/apps/next-base/.zed/settings.json +45 -0
  5. package/_stack/apps/next-base/src/components/ui/spinner.tsx +1 -1
  6. package/_stack/apps/next-base/src/emails/components/components.tsx +2 -2
  7. package/_stack/apps/next-base/src/emails/components/context.tsx +1 -1
  8. package/_stack/apps/next-base/src/emails/components/theme.ts +6 -7
  9. package/_stack/apps/next-base/src/env.ts +2 -3
  10. package/_stack/apps/next-base/src/lib/date.ts +1 -1
  11. package/_stack/apps/next-base/src/server/auth/guards.ts +1 -1
  12. package/_stack/apps/next-base/src/server/better-auth/config.ts +1 -1
  13. package/_stack/apps/next-base/src/server/better-auth/server.ts +2 -2
  14. package/_stack/apps/next-base/src/server/db/schemas/index.ts +1 -1
  15. package/_stack/apps/next-base/src/server/db/seed.ts +2 -2
  16. package/_stack/apps/next-base/src/server/email/adapters/resend/index.ts +3 -3
  17. package/_stack/apps/next-base/src/server/email/core/address.ts +3 -3
  18. package/_stack/apps/next-base/src/server/email/core/port.ts +13 -20
  19. package/_stack/apps/next-base/src/server/email/core/render.ts +2 -2
  20. package/_stack/apps/next-base/src/server/email/factory.ts +7 -9
  21. package/_stack/apps/next-base/src/server/email/index.ts +1 -1
  22. package/_stack/apps/next-base/src/trpc/react.tsx +2 -2
  23. package/_stack/apps/next-base/src/trpc/server.ts +1 -1
  24. package/_stack/apps/tanstack-base/.turbo/turbo-typecheck.log +1 -0
  25. package/_stack/apps/tanstack-base/.vscode/settings.json +35 -0
  26. package/_stack/apps/tanstack-base/.zed/settings.json +45 -0
  27. package/_stack/apps/tanstack-base/src/components/form/text-field.tsx +1 -1
  28. package/_stack/apps/tanstack-base/src/components/ui/spinner.tsx +1 -1
  29. package/_stack/apps/tanstack-base/src/emails/components/components.tsx +2 -2
  30. package/_stack/apps/tanstack-base/src/emails/components/context.tsx +1 -1
  31. package/_stack/apps/tanstack-base/src/emails/components/theme.ts +6 -7
  32. package/_stack/apps/tanstack-base/src/env.ts +2 -6
  33. package/_stack/apps/tanstack-base/src/lib/date.ts +1 -1
  34. package/_stack/apps/tanstack-base/src/routes/__root.tsx +1 -1
  35. package/_stack/apps/tanstack-base/src/routes/_authed.tsx +1 -4
  36. package/_stack/apps/tanstack-base/src/routes/api/auth/$.ts +1 -1
  37. package/_stack/apps/tanstack-base/src/routes/api.trpc.$.tsx +1 -2
  38. package/_stack/apps/tanstack-base/src/server/better-auth/config.ts +1 -1
  39. package/_stack/apps/tanstack-base/src/server/better-auth/session.ts +6 -7
  40. package/_stack/apps/tanstack-base/src/server/db/schemas/index.ts +1 -1
  41. package/_stack/apps/tanstack-base/src/server/db/seed.ts +2 -2
  42. package/_stack/apps/tanstack-base/src/server/email/adapters/resend/index.ts +3 -3
  43. package/_stack/apps/tanstack-base/src/server/email/core/address.ts +3 -3
  44. package/_stack/apps/tanstack-base/src/server/email/core/port.ts +12 -22
  45. package/_stack/apps/tanstack-base/src/server/email/core/render.ts +1 -1
  46. package/_stack/apps/tanstack-base/src/server/email/factory.ts +7 -8
  47. package/_stack/apps/tanstack-base/src/server/email/index.ts +1 -1
  48. package/_stack/packages/analytics/package.json +26 -0
  49. package/_stack/packages/analytics/src/adapters/noop/index.ts +12 -0
  50. package/_stack/packages/analytics/src/adapters/plausible/config.ts +10 -0
  51. package/_stack/packages/analytics/src/adapters/plausible/index.ts +94 -0
  52. package/_stack/packages/analytics/src/adapters/posthog/config.ts +7 -0
  53. package/_stack/packages/analytics/src/adapters/posthog/index.ts +50 -0
  54. package/_stack/packages/analytics/src/core/port.ts +30 -0
  55. package/_stack/packages/analytics/src/index.ts +17 -0
  56. package/_stack/packages/cache/package.json +25 -0
  57. package/_stack/packages/cache/src/adapters/memory/index.ts +51 -0
  58. package/_stack/packages/cache/src/adapters/redis/config.ts +8 -0
  59. package/_stack/packages/cache/src/adapters/redis/index.ts +73 -0
  60. package/_stack/packages/cache/src/core/port.ts +29 -0
  61. package/_stack/packages/cache/src/core/wrap.ts +20 -0
  62. package/_stack/packages/cache/src/index.ts +12 -0
  63. package/_stack/packages/error-tracking/package.json +25 -0
  64. package/_stack/packages/error-tracking/src/adapters/console/index.ts +43 -0
  65. package/_stack/packages/error-tracking/src/adapters/sentry/config.ts +8 -0
  66. package/_stack/packages/error-tracking/src/adapters/sentry/index.ts +72 -0
  67. package/_stack/packages/error-tracking/src/core/port.ts +39 -0
  68. package/_stack/packages/error-tracking/src/index.ts +14 -0
  69. package/_stack/packages/http/package.json +20 -0
  70. package/_stack/packages/http/src/api.ts +373 -0
  71. package/_stack/packages/http/src/index.ts +14 -0
  72. package/_stack/packages/http/src/responses.ts +25 -0
  73. package/_stack/packages/http/src/types.ts +9 -0
  74. package/_stack/packages/jobs/package.json +27 -0
  75. package/_stack/packages/jobs/src/adapters/inngest/config.ts +8 -0
  76. package/_stack/packages/jobs/src/adapters/inngest/index.ts +93 -0
  77. package/_stack/packages/jobs/src/adapters/memory/index.ts +31 -0
  78. package/_stack/packages/jobs/src/adapters/trigger/config.ts +8 -0
  79. package/_stack/packages/jobs/src/adapters/trigger/index.ts +85 -0
  80. package/_stack/packages/jobs/src/core/port.ts +37 -0
  81. package/_stack/packages/jobs/src/index.ts +23 -0
  82. package/_stack/packages/logger/package.json +25 -0
  83. package/_stack/packages/logger/src/adapters/console/config.ts +7 -0
  84. package/_stack/packages/logger/src/adapters/console/index.ts +69 -0
  85. package/_stack/packages/logger/src/adapters/pino/index.ts +54 -0
  86. package/_stack/packages/logger/src/core/port.ts +21 -0
  87. package/_stack/packages/logger/src/index.ts +12 -0
  88. package/_stack/packages/mailer/src/adapters/brevo/index.ts +3 -3
  89. package/_stack/packages/mailer/src/adapters/resend/index.ts +3 -3
  90. package/_stack/packages/mailer/src/adapters/ses/config.ts +3 -3
  91. package/_stack/packages/mailer/src/adapters/ses/index.ts +4 -5
  92. package/_stack/packages/storage/package.json +27 -0
  93. package/_stack/packages/storage/src/adapters/gcs/config.ts +8 -0
  94. package/_stack/packages/storage/src/adapters/gcs/index.ts +111 -0
  95. package/_stack/packages/storage/src/adapters/local/config.ts +8 -0
  96. package/_stack/packages/storage/src/adapters/local/index.ts +78 -0
  97. package/_stack/packages/storage/src/adapters/r2/config.ts +8 -0
  98. package/_stack/packages/storage/src/adapters/r2/index.ts +39 -0
  99. package/_stack/packages/storage/src/adapters/s3/config.ts +11 -0
  100. package/_stack/packages/storage/src/adapters/s3/index.ts +143 -0
  101. package/_stack/packages/storage/src/core/port.ts +41 -0
  102. package/_stack/packages/storage/src/index.ts +21 -0
  103. package/index.mjs +89 -55
  104. package/lib/build.mjs +21 -11
  105. package/lib/capabilities.mjs +375 -0
  106. package/lib/env.mjs +26 -6
  107. package/lib/foundations.mjs +35 -0
  108. package/lib/identity.mjs +4 -5
  109. package/lib/mailer.mjs +9 -13
  110. package/lib/paths.mjs +15 -0
  111. package/lib/scaffold.mjs +12 -11
  112. package/lib/strip.mjs +9 -24
  113. package/lib/util.mjs +8 -9
  114. package/package.json +1 -1
  115. package/_stack/packages/mailer/capability.json +0 -28
  116. package/_stack/patterns/README.md +0 -58
  117. package/_stack/patterns/_baseline/env.ts +0 -31
  118. package/_stack/patterns/_baseline/tsconfig.json +0 -27
  119. package/_stack/patterns/better-auth/pattern.json +0 -73
  120. package/_stack/patterns/better-auth-next/pattern.json +0 -76
  121. package/_stack/patterns/data-table/pattern.json +0 -43
  122. package/_stack/patterns/drizzle/pattern.json +0 -61
  123. package/_stack/patterns/trpc/pattern.json +0 -61
  124. package/_stack/patterns/trpc-next/pattern.json +0 -64
  125. package/lib/manifests.mjs +0 -61
  126. /package/{_stack/patterns/_baseline → templates}/README-author.md +0 -0
  127. /package/{_stack/patterns/_baseline → templates}/biome.jsonc +0 -0
package/lib/strip.mjs CHANGED
@@ -1,43 +1,28 @@
1
- // Step A3 reverse-strip the foundations the user did NOT select.
2
- // Whole-directory deletes (robust against orphans) + the few code "seams"
3
- // that need surgery (trpc/auth wiring) via shipped reduced variants.
1
+ // Strip unselected foundations: whole-dir deletes + code-seam variants (trpc/auth).
4
2
 
5
- import { dirname } from 'node:path'
6
- import { fileURLToPath } from 'node:url'
7
- import { foundationManifest } from './manifests.mjs'
3
+ import { FOUNDATIONS, foundationDeps, foundationScripts } from './foundations.mjs'
4
+ import { TEMPLATES } from './paths.mjs'
8
5
  import { copy, editFile, join, remove } from './util.mjs'
9
6
 
10
- const here = dirname(fileURLToPath(import.meta.url))
11
- const tpl = (rel) => join(here, '..', 'templates', rel)
7
+ const tpl = (rel) => join(TEMPLATES, rel)
12
8
 
13
9
  const ALWAYS_KEEP = new Set(['valibot'])
14
10
 
15
- const manifestDeps = (m) => [...(m?.deps ?? []), ...(m?.devDeps ?? [])]
16
-
17
- /** Logical foundations always present in a base app. */
18
- export const FOUNDATIONS = ['drizzle', 'trpc', 'better-auth', 'data-table']
19
-
20
- /**
21
- * Strip the unselected foundations from the fork.
22
- * @returns {{ removeDeps: string[], removeScripts: string[] }}
23
- */
24
- export function stripFoundations({ projectDir, framework, kept, keptMailer, patterns }) {
11
+ /** @returns {{ removeDeps: string[], removeScripts: string[] }} */
12
+ export function stripFoundations({ projectDir, framework, kept, keptMailer }) {
25
13
  const next = framework === 'next'
26
14
  const src = (p) => join(projectDir, 'src', p)
27
15
  const dropped = FOUNDATIONS.filter((f) => !kept.has(f))
28
16
 
29
17
  // Dep diff: remove a dropped foundation's deps unless a kept one still needs it.
30
- const keptDeps = new Set(
31
- [...kept].flatMap((f) => manifestDeps(patterns[foundationManifest(f, framework)])),
32
- )
18
+ const keptDeps = new Set([...kept].flatMap((f) => foundationDeps(f, framework)))
33
19
  const removeDeps = new Set()
34
20
  const removeScripts = new Set()
35
21
  for (const f of dropped) {
36
- const m = patterns[foundationManifest(f, framework)]
37
- for (const d of manifestDeps(m)) {
22
+ for (const d of foundationDeps(f, framework)) {
38
23
  if (!keptDeps.has(d) && !ALWAYS_KEEP.has(d)) removeDeps.add(d)
39
24
  }
40
- for (const s of Object.keys(m?.scripts ?? {})) removeScripts.add(s)
25
+ for (const s of foundationScripts(f)) removeScripts.add(s)
41
26
  }
42
27
 
43
28
  // --- data-table ---
package/lib/util.mjs CHANGED
@@ -1,5 +1,4 @@
1
- // Small fs / exec / package.json helpers shared by the CLI modules.
2
- // No external deps — keep the CLI lean and instantly runnable.
1
+ // fs / exec / package.json helpers shared by the CLI. No external deps.
3
2
 
4
3
  import { spawnSync } from 'node:child_process'
5
4
  import {
@@ -22,18 +21,18 @@ export const exists = (p) => existsSync(p)
22
21
  export const readJSON = (p) => JSON.parse(read(p))
23
22
  export const writeJSON = (p, obj) => write(p, `${JSON.stringify(obj, null, 2)}\n`)
24
23
 
25
- /** Remove a file or directory if it exists (recursive, never throws on absent). */
24
+ /** Remove file/dir if present (recursive, never throws on absent). */
26
25
  export const remove = (p) => {
27
26
  if (existsSync(p)) rmSync(p, { recursive: true, force: true })
28
27
  }
29
28
 
30
- /** Copy a file or directory tree. */
29
+ /** Copy a file/dir tree. */
31
30
  export const copy = (from, to) => {
32
31
  mkdirSync(dirname(to), { recursive: true })
33
32
  cpSync(from, to, { recursive: true })
34
33
  }
35
34
 
36
- /** Edit a file in place via a (content) => content transform. No-op if absent. */
35
+ /** Edit a file in place via (content) => content. No-op if absent. */
37
36
  export const editFile = (p, fn) => {
38
37
  if (!existsSync(p)) return false
39
38
  const next = fn(read(p))
@@ -41,20 +40,20 @@ export const editFile = (p, fn) => {
41
40
  return true
42
41
  }
43
42
 
44
- /** Is a directory empty (or absent)? Ignores common noise files. */
43
+ /** Dir empty (or absent)? Ignores noise files. */
45
44
  export const isDirEmpty = (p) => {
46
45
  if (!existsSync(p)) return true
47
46
  const noise = new Set(['.git', '.DS_Store'])
48
47
  return readdirSync(p).every((f) => noise.has(f))
49
48
  }
50
49
 
51
- /** Run a command, inheriting stdio. Returns true on exit 0. */
50
+ /** Run a command (inherits stdio). True on exit 0. */
52
51
  export const run = (cmd, args, opts = {}) => {
53
52
  const res = spawnSync(cmd, args, { stdio: 'inherit', ...opts })
54
53
  return res.status === 0
55
54
  }
56
55
 
57
- /** Run a command capturing stdout (trimmed). Returns '' on failure. */
56
+ /** Run a command, capturing trimmed stdout. '' on failure. */
58
57
  export const runCapture = (cmd, args, opts = {}) => {
59
58
  const res = spawnSync(cmd, args, { encoding: 'utf8', ...opts })
60
59
  return res.status === 0 ? (res.stdout || '').trim() : ''
@@ -62,7 +61,7 @@ export const runCapture = (cmd, args, opts = {}) => {
62
61
 
63
62
  export { join }
64
63
 
65
- // --- package.json helpers (operate on a parsed object, mutate in place) ---
64
+ // --- package.json helpers (mutate parsed object in place) ---
66
65
 
67
66
  export const pkgRemoveDeps = (pkg, names) => {
68
67
  for (const field of ['dependencies', 'devDependencies']) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfredmouelle/create-stack",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "Interactive, deterministic installer for the personal reference stack — forks a base app (Next.js / TanStack Start) and strips it to your selection.",
6
6
  "author": {
@@ -1,28 +0,0 @@
1
- {
2
- "$schema": "../../capability.schema.json",
3
- "name": "mailer",
4
- "description": "Transactional email. Bodies are always React Email components, rendered to HTML + plain text.",
5
- "port": "src/core/port.ts",
6
- "factory": "src/factory.ts",
7
- "defaultAdapter": "resend",
8
- "adapters": {
9
- "resend": {
10
- "deps": ["resend"],
11
- "env": ["RESEND_API_KEY"],
12
- "files": ["src/adapters/resend"]
13
- },
14
- "brevo": {
15
- "deps": ["@getbrevo/brevo"],
16
- "env": ["BREVO_API_KEY"],
17
- "files": ["src/adapters/brevo"]
18
- },
19
- "ses": {
20
- "deps": ["@aws-sdk/client-sesv2"],
21
- "env": ["AWS_REGION", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
22
- "files": ["src/adapters/ses"]
23
- }
24
- },
25
- "sharedDeps": ["valibot", "@react-email/render"],
26
- "peerDeps": ["react", "react-dom"],
27
- "sharedFiles": ["src/core", "src/factory.ts", "src/index.ts"]
28
- }
@@ -1,58 +0,0 @@
1
- # Patterns
2
-
3
- Foundational, framework-coupled **patterns** the `bootstrap` skill vendors into a
4
- freshly scaffolded app — the counterpart to `packages/` (swappable capabilities).
5
-
6
- A *capability* is a provider behind a port (mailer, storage, …), swappable by
7
- changing one line. A *pattern* is a foundation you don't swap but always set up
8
- the same way: tRPC wiring, the better-auth instance, the Drizzle client. They are
9
- **framework-coupled** (currently `tanstack-start`, mirrored from the reference
10
- base apps) and depend on each other.
11
-
12
- **The code lives in the base apps, not here.** `patterns/` is a pure *manifest
13
- layer*: each `pattern.json` describes a foundation (how to detect it, its deps,
14
- env, framework, dependencies) and lists the files that make it up — by pointing
15
- **into the base apps** (`apps/tanstack-base`, `apps/next-base`), the single source
16
- of truth. No code is duplicated.
17
-
18
- Each pattern is `<name>/pattern.json` (see `../pattern.schema.json`).
19
- `_baseline/` is special: real always-applied config files (Biome, tsconfig, env
20
- skeleton, the `# Author` README footer) that a standalone fork needs but the base
21
- apps don't carry on their own (they inherit the monorepo's Biome).
22
-
23
- ## How the skills use these
24
-
25
- The manifests drive two flows:
26
-
27
- - **bootstrap — create mode** (empty folder): fork a base app, then *strip* every
28
- foundation/capability the user didn't pick, using each manifest's `files`/`deps`/
29
- `env` to know its exact footprint.
30
- - **bootstrap — existing project / add-capability**: match each manifest's `detect`
31
- against the project → the opt-in set, then *vendor* the listed files (copied from
32
- the base apps) + deps + env, wire `integratesWith` when both sides are opt-in, and
33
- pull required `capabilities`. A pattern not referenced is never pulled.
34
-
35
- ## Available patterns
36
-
37
- - **drizzle** — Drizzle ORM + drizzle-kit (Postgres). Client, schema barrel,
38
- cursor pagination, seed harness.
39
- - **better-auth** — better-auth v1 with the Drizzle adapter. Email+password,
40
- verification, optional Google OAuth, rate limiting, auth tables, client +
41
- session helpers, route guard. `dependsOn` drizzle; needs the mailer + email-kit
42
- capabilities.
43
- - **trpc** — tRPC v11 + TanStack React Query. Context, procedure tiers, error
44
- formatter, client + SSR caller, fetch handler. `dependsOn` drizzle,
45
- `integratesWith` better-auth.
46
- - **data-table** — headless tables with TanStack Table (table + skeleton
47
- primitives, DataTable, InfiniteDataTable, SortableHeader). `framework: agnostic`
48
- — works in both Next and TanStack Start.
49
-
50
- Next.js variants (App Router) of the framework-coupled patterns:
51
-
52
- - **better-auth-next** — better-auth with `next/headers` session, `toNextJsHandler`
53
- catch-all, server-component guards (`requireAuth`).
54
- - **trpc-next** — tRPC with the classic `api.x.useQuery` hooks (createTRPCReact) +
55
- RSC hydration. `integratesWith` better-auth-next.
56
-
57
- bootstrap picks the variant matching the project's framework: `trpc`/`better-auth`
58
- for TanStack Start, `trpc-next`/`better-auth-next` for Next.
@@ -1,31 +0,0 @@
1
- import { createEnv } from '@t3-oss/env-core';
2
- import * as v from 'valibot';
3
-
4
- /** Makes a var required only in production (optional in dev/test). */
5
- export const requiredInProduction = <T extends v.GenericSchema>(schema: T) =>
6
- process.env.NODE_ENV === 'production' ? schema : v.optional(schema);
7
-
8
- /**
9
- * Typed environment. Start minimal — patterns (drizzle, better-auth, …) and
10
- * capabilities (add-capability) extend the `server` block and `runtimeEnv` with
11
- * the keys they need.
12
- */
13
- export const env = createEnv({
14
- shared: {
15
- NODE_ENV: v.optional(
16
- v.picklist(['development', 'test', 'production']),
17
- 'development',
18
- ),
19
- },
20
-
21
- server: {
22
- // Extended by patterns/capabilities (DATABASE_URL, BETTER_AUTH_SECRET, …).
23
- },
24
-
25
- runtimeEnv: {
26
- NODE_ENV: process.env.NODE_ENV,
27
- },
28
-
29
- skipValidation: !!process.env.SKIP_ENV_VALIDATION,
30
- emptyStringAsUndefined: true,
31
- });
@@ -1,27 +0,0 @@
1
- {
2
- "include": ["**/*.ts", "**/*.tsx"],
3
- "compilerOptions": {
4
- "target": "ES2022",
5
- "jsx": "react-jsx",
6
- "module": "ESNext",
7
- "paths": {
8
- "~/*": ["./src/*"]
9
- },
10
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
11
- "types": ["vite/client"],
12
-
13
- /* Bundler mode */
14
- "moduleResolution": "bundler",
15
- "allowImportingTsExtensions": true,
16
- "verbatimModuleSyntax": true,
17
- "noEmit": true,
18
-
19
- /* Linting */
20
- "skipLibCheck": true,
21
- "strict": true,
22
- "noUnusedLocals": true,
23
- "noUnusedParameters": true,
24
- "noFallthroughCasesInSwitch": true,
25
- "noUncheckedSideEffectImports": true
26
- }
27
- }
@@ -1,73 +0,0 @@
1
- {
2
- "$schema": "../../pattern.schema.json",
3
- "name": "better-auth",
4
- "description": "better-auth v1 with the Drizzle adapter (Postgres). Email+password, email verification, optional Google OAuth, rate limiting and TanStack Start cookies. Ships auth tables, server/client instances, session helpers and a route guard.",
5
- "framework": "tanstack-start",
6
- "detect": {
7
- "deps": [
8
- "better-auth"
9
- ],
10
- "files": []
11
- },
12
- "dependsOn": [
13
- "drizzle"
14
- ],
15
- "integratesWith": [
16
- "trpc"
17
- ],
18
- "capabilities": [
19
- "mailer",
20
- "email-kit"
21
- ],
22
- "deps": [
23
- "better-auth"
24
- ],
25
- "env": [
26
- "BETTER_AUTH_URL",
27
- "BETTER_AUTH_SECRET",
28
- "BETTER_AUTH_GOOGLE_CLIENT_ID",
29
- "BETTER_AUTH_GOOGLE_CLIENT_SECRET"
30
- ],
31
- "files": [
32
- {
33
- "from": "apps/tanstack-base/src/server/better-auth/config.ts",
34
- "to": "<srcRoot>/server/better-auth/config.ts"
35
- },
36
- {
37
- "from": "apps/tanstack-base/src/server/better-auth/client.ts",
38
- "to": "<srcRoot>/server/better-auth/client.ts"
39
- },
40
- {
41
- "from": "apps/tanstack-base/src/server/better-auth/session.ts",
42
- "to": "<srcRoot>/server/better-auth/session.ts"
43
- },
44
- {
45
- "from": "apps/tanstack-base/src/server/better-auth/emails.tsx",
46
- "to": "<srcRoot>/server/better-auth/emails.tsx"
47
- },
48
- {
49
- "from": "apps/tanstack-base/src/server/better-auth/index.ts",
50
- "to": "<srcRoot>/server/better-auth/index.ts"
51
- },
52
- {
53
- "from": "apps/tanstack-base/src/server/db/schemas/auth.schema.ts",
54
- "to": "<srcRoot>/server/db/schemas/auth.schema.ts"
55
- },
56
- {
57
- "from": "apps/tanstack-base/src/routes/api/auth/$.ts",
58
- "to": "<srcRoot>/routes/api/auth/$.ts"
59
- },
60
- {
61
- "from": "apps/tanstack-base/src/routes/_authed.tsx",
62
- "to": "<srcRoot>/routes/_authed.tsx"
63
- }
64
- ],
65
- "wiring": [
66
- "Append `export * from './auth.schema'` to <srcRoot>/server/db/schemas/index.ts (created by the drizzle pattern).",
67
- "emails.tsx imports ~/server/email (mailer capability) and ~/emails/{reset-password,verify-email} (email-kit). Ensure both capabilities are added; create the two templates if missing."
68
- ],
69
- "notes": [
70
- "Auth tables (user/session/account/verification) live in auth.schema.ts; better-auth manages them via the Drizzle adapter. Add custom user columns via `additionalFields` in config.ts mirrored in auth.schema.ts.",
71
- "BETTER_AUTH_SECRET is read implicitly from env by better-auth; the rest are validated in env.ts."
72
- ]
73
- }
@@ -1,76 +0,0 @@
1
- {
2
- "$schema": "../../pattern.schema.json",
3
- "name": "better-auth-next",
4
- "description": "better-auth v1 for Next.js App Router with the Drizzle adapter. Email+password + verification, optional Google OAuth, session via next/headers (react cache), toNextJsHandler catch-all route, and server-component guards. The Next counterpart of the `better-auth` pattern.",
5
- "framework": "next",
6
- "detect": {
7
- "deps": [
8
- "better-auth"
9
- ],
10
- "files": [
11
- "src/app/api/auth/[...all]/route.ts"
12
- ]
13
- },
14
- "dependsOn": [
15
- "drizzle"
16
- ],
17
- "integratesWith": [
18
- "trpc-next"
19
- ],
20
- "capabilities": [
21
- "mailer",
22
- "email-kit"
23
- ],
24
- "deps": [
25
- "better-auth"
26
- ],
27
- "env": [
28
- "BETTER_AUTH_URL",
29
- "BETTER_AUTH_SECRET",
30
- "BETTER_AUTH_GOOGLE_CLIENT_ID",
31
- "BETTER_AUTH_GOOGLE_CLIENT_SECRET"
32
- ],
33
- "files": [
34
- {
35
- "from": "apps/next-base/src/server/better-auth/config.ts",
36
- "to": "<srcRoot>/server/better-auth/config.ts"
37
- },
38
- {
39
- "from": "apps/next-base/src/server/better-auth/client.ts",
40
- "to": "<srcRoot>/server/better-auth/client.ts"
41
- },
42
- {
43
- "from": "apps/next-base/src/server/better-auth/server.ts",
44
- "to": "<srcRoot>/server/better-auth/server.ts"
45
- },
46
- {
47
- "from": "apps/next-base/src/server/better-auth/emails.tsx",
48
- "to": "<srcRoot>/server/better-auth/emails.tsx"
49
- },
50
- {
51
- "from": "apps/next-base/src/server/better-auth/index.ts",
52
- "to": "<srcRoot>/server/better-auth/index.ts"
53
- },
54
- {
55
- "from": "apps/next-base/src/server/auth/guards.ts",
56
- "to": "<srcRoot>/server/auth/guards.ts"
57
- },
58
- {
59
- "from": "apps/next-base/src/server/db/schemas/auth.schema.ts",
60
- "to": "<srcRoot>/server/db/schemas/auth.schema.ts"
61
- },
62
- {
63
- "from": "apps/next-base/src/app/api/auth/[...all]/route.ts",
64
- "to": "<srcRoot>/app/api/auth/[...all]/route.ts"
65
- }
66
- ],
67
- "wiring": [
68
- "Append `export * from './auth.schema'` to <srcRoot>/server/db/schemas/index.ts (created by the drizzle pattern).",
69
- "emails.tsx imports ~/server/email (mailer) and ~/emails/{reset-password,verify-email} (email-kit) — add both capabilities and the two templates.",
70
- "Auth pages live in app/auth/* (server pages) with forms in app/auth/_components/* ('use client', shadcn Form + react-hook-form + valibot)."
71
- ],
72
- "notes": [
73
- "No tanstackStartCookies — cookies are handled by toNextJsHandler. getSession uses next/headers + react cache (server.ts). Protect Server Components/pages with requireAuth() from server/auth/guards.",
74
- "Add custom user columns via `additionalFields` in config.ts mirrored in auth.schema.ts."
75
- ]
76
- }
@@ -1,43 +0,0 @@
1
- {
2
- "$schema": "../../pattern.schema.json",
3
- "name": "data-table",
4
- "description": "Headless data tables with TanStack Table: shadcn table + skeleton primitives, a DataTable (loading + empty states), an InfiniteDataTable and a SortableHeader.",
5
- "framework": "agnostic",
6
- "detect": {
7
- "deps": [
8
- "@tanstack/react-table"
9
- ],
10
- "files": []
11
- },
12
- "dependsOn": [],
13
- "deps": [
14
- "@tanstack/react-table"
15
- ],
16
- "env": [],
17
- "files": [
18
- {
19
- "from": "apps/tanstack-base/src/components/ui/table.tsx",
20
- "to": "<srcRoot>/components/ui/table.tsx"
21
- },
22
- {
23
- "from": "apps/tanstack-base/src/components/ui/skeleton.tsx",
24
- "to": "<srcRoot>/components/ui/skeleton.tsx"
25
- },
26
- {
27
- "from": "apps/tanstack-base/src/components/data-table.tsx",
28
- "to": "<srcRoot>/components/data-table.tsx"
29
- },
30
- {
31
- "from": "apps/tanstack-base/src/components/infinite-data-table.tsx",
32
- "to": "<srcRoot>/components/infinite-data-table.tsx"
33
- },
34
- {
35
- "from": "apps/tanstack-base/src/components/sortable-header.tsx",
36
- "to": "<srcRoot>/components/sortable-header.tsx"
37
- }
38
- ],
39
- "notes": [
40
- "Pure React + TanStack Table — works in both Next App Router and TanStack Start. Needs shadcn (cn util + Button); the table/skeleton primitives are vendored here.",
41
- "On Next.js, the component that builds the table (calls useReactTable) must be a client component ('use client')."
42
- ]
43
- }
@@ -1,61 +0,0 @@
1
- {
2
- "$schema": "../../pattern.schema.json",
3
- "name": "drizzle",
4
- "description": "Drizzle ORM + drizzle-kit (Postgres / node-postgres). DB client, schema barrel, cursor (keyset) pagination helpers and a seed harness.",
5
- "framework": "tanstack-start",
6
- "detect": {
7
- "deps": [
8
- "drizzle-orm"
9
- ],
10
- "files": [
11
- "drizzle.config.ts"
12
- ]
13
- },
14
- "dependsOn": [],
15
- "deps": [
16
- "drizzle-orm",
17
- "pg"
18
- ],
19
- "devDeps": [
20
- "drizzle-kit",
21
- "dotenv",
22
- "tsx",
23
- "@types/pg",
24
- "@faker-js/faker"
25
- ],
26
- "env": [
27
- "DATABASE_URL"
28
- ],
29
- "scripts": {
30
- "db:generate": "drizzle-kit generate",
31
- "db:migrate": "drizzle-kit migrate",
32
- "db:push": "drizzle-kit push",
33
- "db:studio": "drizzle-kit studio",
34
- "db:seed": "tsx src/server/db/seed.ts"
35
- },
36
- "files": [
37
- {
38
- "from": "apps/tanstack-base/drizzle.config.ts",
39
- "to": "drizzle.config.ts"
40
- },
41
- {
42
- "from": "apps/tanstack-base/src/server/db/index.ts",
43
- "to": "<srcRoot>/server/db/index.ts"
44
- },
45
- {
46
- "from": "apps/tanstack-base/src/server/db/keyset.ts",
47
- "to": "<srcRoot>/server/db/keyset.ts"
48
- },
49
- {
50
- "from": "apps/tanstack-base/src/server/db/seed.ts",
51
- "to": "<srcRoot>/server/db/seed.ts"
52
- },
53
- {
54
- "from": "apps/tanstack-base/src/server/db/schemas/index.ts",
55
- "to": "<srcRoot>/server/db/schemas/index.ts"
56
- }
57
- ],
58
- "notes": [
59
- "drizzle.config.ts globs ./src/server/db/schemas/*.schema.ts — adjust the path if the project's source root is not ./src."
60
- ]
61
- }
@@ -1,61 +0,0 @@
1
- {
2
- "$schema": "../../pattern.schema.json",
3
- "name": "trpc",
4
- "description": "tRPC v11 + TanStack React Query. Context with session injection, public/protected procedures, valibot error formatter, batch-stream client, SSR caller and a fetch route handler.",
5
- "framework": "tanstack-start",
6
- "detect": {
7
- "deps": [
8
- "@trpc/server"
9
- ],
10
- "files": []
11
- },
12
- "dependsOn": [
13
- "drizzle"
14
- ],
15
- "integratesWith": [
16
- "better-auth"
17
- ],
18
- "deps": [
19
- "@trpc/server",
20
- "@trpc/client",
21
- "@trpc/tanstack-react-query",
22
- "@tanstack/react-query",
23
- "superjson",
24
- "valibot"
25
- ],
26
- "env": [],
27
- "files": [
28
- {
29
- "from": "apps/tanstack-base/src/server/api/trpc.ts",
30
- "to": "<srcRoot>/server/api/trpc.ts"
31
- },
32
- {
33
- "from": "apps/tanstack-base/src/server/api/root.ts",
34
- "to": "<srcRoot>/server/api/root.ts"
35
- },
36
- {
37
- "from": "apps/tanstack-base/src/server/api/routers/health.router.ts",
38
- "to": "<srcRoot>/server/api/routers/health.router.ts"
39
- },
40
- {
41
- "from": "apps/tanstack-base/src/routes/api.trpc.$.tsx",
42
- "to": "<srcRoot>/routes/api.trpc.$.tsx"
43
- },
44
- {
45
- "from": "apps/tanstack-base/src/trpc/react.tsx",
46
- "to": "<srcRoot>/trpc/react.tsx"
47
- },
48
- {
49
- "from": "apps/tanstack-base/src/trpc/query-client.ts",
50
- "to": "<srcRoot>/trpc/query-client.ts"
51
- },
52
- {
53
- "from": "apps/tanstack-base/src/trpc/server.ts",
54
- "to": "<srcRoot>/trpc/server.ts"
55
- }
56
- ],
57
- "notes": [
58
- "trpc.ts integrates with better-auth: it imports `auth` and injects `session` into the context. If the better-auth pattern is NOT opt-in, strip those imports, the `session` from the context, and protectedProcedure — keep publicProcedure + the timing middleware.",
59
- "Wire TRPCReactProvider + createQueryClient into the app's root route, and getServerHelpers for SSR preloading (see tanstack-base's router for the exact root wiring)."
60
- ]
61
- }
@@ -1,64 +0,0 @@
1
- {
2
- "$schema": "../../pattern.schema.json",
3
- "name": "trpc-next",
4
- "description": "tRPC v11 for Next.js App Router — the classic `api.x.useQuery` / `useMutation` hooks (createTRPCReact) plus RSC hydration (createHydrationHelpers). The Next counterpart of the `trpc` pattern.",
5
- "framework": "next",
6
- "detect": {
7
- "deps": [
8
- "@trpc/react-query"
9
- ],
10
- "files": []
11
- },
12
- "dependsOn": [
13
- "drizzle"
14
- ],
15
- "integratesWith": [
16
- "better-auth-next"
17
- ],
18
- "deps": [
19
- "@trpc/server",
20
- "@trpc/client",
21
- "@trpc/react-query",
22
- "@tanstack/react-query",
23
- "superjson",
24
- "valibot"
25
- ],
26
- "env": [],
27
- "files": [
28
- {
29
- "from": "apps/next-base/src/server/api/trpc.ts",
30
- "to": "<srcRoot>/server/api/trpc.ts"
31
- },
32
- {
33
- "from": "apps/next-base/src/server/api/root.ts",
34
- "to": "<srcRoot>/server/api/root.ts"
35
- },
36
- {
37
- "from": "apps/next-base/src/server/api/routers/health.router.ts",
38
- "to": "<srcRoot>/server/api/routers/health.router.ts"
39
- },
40
- {
41
- "from": "apps/next-base/src/trpc/react.tsx",
42
- "to": "<srcRoot>/trpc/react.tsx"
43
- },
44
- {
45
- "from": "apps/next-base/src/trpc/query-client.ts",
46
- "to": "<srcRoot>/trpc/query-client.ts"
47
- },
48
- {
49
- "from": "apps/next-base/src/trpc/server.ts",
50
- "to": "<srcRoot>/trpc/server.ts"
51
- },
52
- {
53
- "from": "apps/next-base/src/app/api/trpc/[trpc]/route.ts",
54
- "to": "<srcRoot>/app/api/trpc/[trpc]/route.ts"
55
- }
56
- ],
57
- "wiring": [
58
- "Wrap the app in <TRPCReactProvider> in app/layout.tsx (it's a client component)."
59
- ],
60
- "notes": [
61
- "Client usage: `api.<router>.<proc>.useQuery()` / `.useMutation()` from ~/trpc/react. RSC usage: `import { api, HydrateClient } from '~/trpc/server'` for prefetch + hydrate.",
62
- "trpc.ts context calls better-auth getSession; if better-auth-next is NOT opt-in, strip the auth import, `session` from the context, and protectedProcedure."
63
- ]
64
- }