create-better-t-stack 2.36.3 → 2.37.0-canary.6846bd90

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 (112) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.d.ts +11 -5
  3. package/dist/index.js +1 -1
  4. package/dist/{src-CN1zi2A-.js → src-ByxWjVSi.js} +331 -241
  5. package/package.json +1 -1
  6. package/templates/addons/ruler/.ruler/bts.md.hbs +2 -2
  7. package/templates/api/orpc/native/utils/orpc.ts.hbs +2 -2
  8. package/templates/api/orpc/server/base/src/lib/context.ts.hbs +10 -10
  9. package/templates/api/orpc/server/base/src/lib/orpc.ts.hbs +1 -1
  10. package/templates/api/orpc/server/next/src/app/rpc/[...all]/route.ts.hbs +2 -2
  11. package/templates/api/orpc/web/nuxt/app/plugins/orpc.ts.hbs +1 -1
  12. package/templates/api/orpc/web/react/base/src/utils/orpc.ts.hbs +1 -1
  13. package/templates/api/orpc/web/solid/src/utils/orpc.ts.hbs +1 -1
  14. package/templates/api/orpc/web/svelte/src/lib/orpc.ts.hbs +1 -1
  15. package/templates/api/trpc/native/utils/trpc.ts.hbs +2 -2
  16. package/templates/api/trpc/server/base/src/lib/context.ts.hbs +10 -10
  17. package/templates/api/trpc/server/base/src/lib/trpc.ts.hbs +1 -1
  18. package/templates/api/trpc/web/react/base/src/utils/trpc.ts.hbs +2 -2
  19. package/templates/auth/clerk/convex/backend/convex/auth.config.ts.hbs +12 -0
  20. package/templates/auth/clerk/convex/backend/convex/privateData.ts.hbs +16 -0
  21. package/templates/auth/clerk/convex/native/base/app/(auth)/_layout.tsx.hbs +12 -0
  22. package/templates/auth/clerk/convex/native/base/app/(auth)/sign-in.tsx.hbs +67 -0
  23. package/templates/auth/clerk/convex/native/base/app/(auth)/sign-out.tsx.hbs +110 -0
  24. package/templates/auth/clerk/convex/native/base/components/sign-out-button.tsx.hbs +27 -0
  25. package/templates/auth/clerk/convex/web/react/next/src/app/dashboard/page.tsx.hbs +29 -0
  26. package/templates/auth/clerk/convex/web/react/next/src/middleware.ts.hbs +12 -0
  27. package/templates/auth/clerk/convex/web/react/react-router/src/routes/dashboard.tsx.hbs +32 -0
  28. package/templates/auth/clerk/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs +37 -0
  29. package/templates/auth/clerk/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs +37 -0
  30. package/templates/auth/clerk/convex/web/react/tanstack-start/src/server.ts.hbs +18 -0
  31. package/templates/backend/convex/packages/backend/package.json.hbs +1 -0
  32. package/templates/backend/server/elysia/src/index.ts.hbs +3 -3
  33. package/templates/backend/server/express/src/index.ts.hbs +6 -6
  34. package/templates/backend/server/fastify/src/index.ts.hbs +4 -4
  35. package/templates/backend/server/hono/src/index.ts.hbs +4 -4
  36. package/templates/backend/server/server-base/src/routers/index.ts.hbs +4 -4
  37. package/templates/deploy/alchemy/alchemy.run.ts.hbs +3 -18
  38. package/templates/frontend/native/nativewind/app/(drawer)/index.tsx.hbs +35 -3
  39. package/templates/frontend/native/nativewind/app/_layout.tsx.hbs +28 -0
  40. package/templates/frontend/native/nativewind/package.json.hbs +1 -0
  41. package/templates/frontend/native/unistyles/app/(drawer)/index.tsx.hbs +32 -0
  42. package/templates/frontend/native/unistyles/app/_layout.tsx.hbs +35 -0
  43. package/templates/frontend/native/unistyles/package.json.hbs +1 -0
  44. package/templates/frontend/nuxt/app/components/Header.vue.hbs +3 -3
  45. package/templates/frontend/react/next/src/app/layout.tsx.hbs +23 -15
  46. package/templates/frontend/react/next/src/components/providers.tsx.hbs +12 -0
  47. package/templates/frontend/react/react-router/src/root.tsx.hbs +28 -1
  48. package/templates/frontend/react/tanstack-router/src/main.tsx.hbs +19 -1
  49. package/templates/frontend/react/tanstack-start/src/router.tsx.hbs +8 -4
  50. package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +52 -5
  51. package/templates/frontend/react/web-base/src/components/header.tsx.hbs +3 -3
  52. package/templates/frontend/solid/src/components/header.tsx.hbs +3 -3
  53. package/templates/frontend/svelte/src/components/Header.svelte.hbs +3 -3
  54. package/templates/deploy/alchemy/wrangler.jsonc.hbs +0 -11
  55. /package/templates/auth/{native → better-auth/native}/native-base/lib/auth-client.ts.hbs +0 -0
  56. /package/templates/auth/{native → better-auth/native}/nativewind/app/(drawer)/index.tsx.hbs +0 -0
  57. /package/templates/auth/{native → better-auth/native}/nativewind/components/sign-in.tsx.hbs +0 -0
  58. /package/templates/auth/{native → better-auth/native}/nativewind/components/sign-up.tsx.hbs +0 -0
  59. /package/templates/auth/{native → better-auth/native}/unistyles/app/(drawer)/index.tsx.hbs +0 -0
  60. /package/templates/auth/{native → better-auth/native}/unistyles/components/sign-in.tsx.hbs +0 -0
  61. /package/templates/auth/{native → better-auth/native}/unistyles/components/sign-up.tsx.hbs +0 -0
  62. /package/templates/auth/{server → better-auth/server}/base/src/lib/auth.ts.hbs +0 -0
  63. /package/templates/auth/{server → better-auth/server}/db/drizzle/mysql/src/db/schema/auth.ts +0 -0
  64. /package/templates/auth/{server → better-auth/server}/db/drizzle/postgres/src/db/schema/auth.ts +0 -0
  65. /package/templates/auth/{server → better-auth/server}/db/drizzle/sqlite/src/db/schema/auth.ts +0 -0
  66. /package/templates/auth/{server → better-auth/server}/db/mongoose/mongodb/src/db/models/auth.model.ts +0 -0
  67. /package/templates/auth/{server → better-auth/server}/db/prisma/mongodb/prisma/schema/auth.prisma +0 -0
  68. /package/templates/auth/{server → better-auth/server}/db/prisma/mysql/prisma/schema/auth.prisma +0 -0
  69. /package/templates/auth/{server → better-auth/server}/db/prisma/postgres/prisma/schema/auth.prisma +0 -0
  70. /package/templates/auth/{server → better-auth/server}/db/prisma/sqlite/prisma/schema/auth.prisma +0 -0
  71. /package/templates/auth/{server → better-auth/server}/next/src/app/api/auth/[...all]/route.ts +0 -0
  72. /package/templates/auth/{web → better-auth/web}/nuxt/app/components/SignInForm.vue +0 -0
  73. /package/templates/auth/{web → better-auth/web}/nuxt/app/components/SignUpForm.vue +0 -0
  74. /package/templates/auth/{web → better-auth/web}/nuxt/app/components/UserMenu.vue +0 -0
  75. /package/templates/auth/{web → better-auth/web}/nuxt/app/middleware/auth.ts +0 -0
  76. /package/templates/auth/{web → better-auth/web}/nuxt/app/pages/dashboard.vue.hbs +0 -0
  77. /package/templates/auth/{web → better-auth/web}/nuxt/app/pages/login.vue +0 -0
  78. /package/templates/auth/{web → better-auth/web}/nuxt/app/plugins/auth-client.ts +0 -0
  79. /package/templates/auth/{web → better-auth/web}/react/base/src/lib/auth-client.ts.hbs +0 -0
  80. /package/templates/auth/{web → better-auth/web}/react/next/src/app/dashboard/page.tsx.hbs +0 -0
  81. /package/templates/auth/{web → better-auth/web}/react/next/src/app/login/page.tsx +0 -0
  82. /package/templates/auth/{web → better-auth/web}/react/next/src/components/sign-in-form.tsx +0 -0
  83. /package/templates/auth/{web → better-auth/web}/react/next/src/components/sign-up-form.tsx +0 -0
  84. /package/templates/auth/{web → better-auth/web}/react/next/src/components/theme-provider.tsx +0 -0
  85. /package/templates/auth/{web → better-auth/web}/react/next/src/components/user-menu.tsx +0 -0
  86. /package/templates/auth/{web → better-auth/web}/react/react-router/src/components/sign-in-form.tsx +0 -0
  87. /package/templates/auth/{web → better-auth/web}/react/react-router/src/components/sign-up-form.tsx +0 -0
  88. /package/templates/auth/{web → better-auth/web}/react/react-router/src/components/user-menu.tsx +0 -0
  89. /package/templates/auth/{web → better-auth/web}/react/react-router/src/routes/dashboard.tsx.hbs +0 -0
  90. /package/templates/auth/{web → better-auth/web}/react/react-router/src/routes/login.tsx +0 -0
  91. /package/templates/auth/{web → better-auth/web}/react/tanstack-router/src/components/sign-in-form.tsx +0 -0
  92. /package/templates/auth/{web → better-auth/web}/react/tanstack-router/src/components/sign-up-form.tsx +0 -0
  93. /package/templates/auth/{web → better-auth/web}/react/tanstack-router/src/components/user-menu.tsx +0 -0
  94. /package/templates/auth/{web → better-auth/web}/react/tanstack-router/src/routes/dashboard.tsx.hbs +0 -0
  95. /package/templates/auth/{web → better-auth/web}/react/tanstack-router/src/routes/login.tsx +0 -0
  96. /package/templates/auth/{web → better-auth/web}/react/tanstack-start/src/components/sign-in-form.tsx +0 -0
  97. /package/templates/auth/{web → better-auth/web}/react/tanstack-start/src/components/sign-up-form.tsx +0 -0
  98. /package/templates/auth/{web → better-auth/web}/react/tanstack-start/src/components/user-menu.tsx +0 -0
  99. /package/templates/auth/{web → better-auth/web}/react/tanstack-start/src/routes/dashboard.tsx.hbs +0 -0
  100. /package/templates/auth/{web → better-auth/web}/react/tanstack-start/src/routes/login.tsx +0 -0
  101. /package/templates/auth/{web → better-auth/web}/solid/src/components/sign-in-form.tsx +0 -0
  102. /package/templates/auth/{web → better-auth/web}/solid/src/components/sign-up-form.tsx +0 -0
  103. /package/templates/auth/{web → better-auth/web}/solid/src/components/user-menu.tsx.hbs +0 -0
  104. /package/templates/auth/{web → better-auth/web}/solid/src/lib/auth-client.ts +0 -0
  105. /package/templates/auth/{web → better-auth/web}/solid/src/routes/dashboard.tsx.hbs +0 -0
  106. /package/templates/auth/{web → better-auth/web}/solid/src/routes/login.tsx +0 -0
  107. /package/templates/auth/{web → better-auth/web}/svelte/src/components/SignInForm.svelte +0 -0
  108. /package/templates/auth/{web → better-auth/web}/svelte/src/components/SignUpForm.svelte +0 -0
  109. /package/templates/auth/{web → better-auth/web}/svelte/src/components/UserMenu.svelte +0 -0
  110. /package/templates/auth/{web → better-auth/web}/svelte/src/lib/auth-client.ts +0 -0
  111. /package/templates/auth/{web → better-auth/web}/svelte/src/routes/dashboard/+page.svelte.hbs +0 -0
  112. /package/templates/auth/{web → better-auth/web}/svelte/src/routes/login/+page.svelte +0 -0
@@ -0,0 +1,37 @@
1
+ import { SignInButton, UserButton, useUser } from "@clerk/clerk-react";
2
+ import { api } from "@{{projectName}}/backend/convex/_generated/api";
3
+ import { createFileRoute } from "@tanstack/react-router";
4
+ import {
5
+ Authenticated,
6
+ AuthLoading,
7
+ Unauthenticated,
8
+ useQuery,
9
+ } from "convex/react";
10
+
11
+ export const Route = createFileRoute("/dashboard")({
12
+ component: RouteComponent,
13
+ });
14
+
15
+ function RouteComponent() {
16
+ const privateData = useQuery(api.privateData.get);
17
+ const user = useUser()
18
+
19
+ return (
20
+ <>
21
+ <Authenticated>
22
+ <div>
23
+ <h1>Dashboard</h1>
24
+ <p>Welcome {user.user?.fullName}</p>
25
+ <p>privateData: {privateData?.message}</p>
26
+ <UserButton />
27
+ </div>
28
+ </Authenticated>
29
+ <Unauthenticated>
30
+ <SignInButton />
31
+ </Unauthenticated>
32
+ <AuthLoading>
33
+ <div>Loading...</div>
34
+ </AuthLoading>
35
+ </>
36
+ );
37
+ }
@@ -0,0 +1,37 @@
1
+ import { SignInButton, UserButton, useUser } from "@clerk/tanstack-react-start";
2
+ import { api } from "@{{projectName}}/backend/convex/_generated/api";
3
+ import { createFileRoute } from "@tanstack/react-router";
4
+ import {
5
+ Authenticated,
6
+ AuthLoading,
7
+ Unauthenticated,
8
+ useQuery,
9
+ } from "convex/react";
10
+
11
+ export const Route = createFileRoute("/dashboard")({
12
+ component: RouteComponent,
13
+ });
14
+
15
+ function RouteComponent() {
16
+ const privateData = useQuery(api.privateData.get);
17
+ const user = useUser();
18
+
19
+ return (
20
+ <>
21
+ <Authenticated>
22
+ <div>
23
+ <h1>Dashboard</h1>
24
+ <p>Welcome {user.user?.fullName}</p>
25
+ <p>privateData: {privateData?.message}</p>
26
+ <UserButton />
27
+ </div>
28
+ </Authenticated>
29
+ <Unauthenticated>
30
+ <SignInButton />
31
+ </Unauthenticated>
32
+ <AuthLoading>
33
+ <div>Loading...</div>
34
+ </AuthLoading>
35
+ </>
36
+ );
37
+ }
@@ -0,0 +1,18 @@
1
+ import { createClerkHandler } from "@clerk/tanstack-react-start/server";
2
+ import {
3
+ createStartHandler,
4
+ defaultStreamHandler,
5
+ defineHandlerCallback,
6
+ } from "@tanstack/react-start/server";
7
+ import { createRouter } from "./router";
8
+
9
+ const handlerFactory = createClerkHandler(
10
+ createStartHandler({
11
+ createRouter,
12
+ }),
13
+ );
14
+
15
+ export default defineHandlerCallback(async (event) => {
16
+ const startHandler = await handlerFactory(defaultStreamHandler);
17
+ return startHandler(event);
18
+ });
@@ -9,6 +9,7 @@
9
9
  "license": "ISC",
10
10
  "description": "",
11
11
  "devDependencies": {
12
+ "@types/node": "^24.3.0",
12
13
  "typescript": "^5.9.2"
13
14
  },
14
15
  "dependencies": {
@@ -14,7 +14,7 @@ import { RPCHandler } from "@orpc/server/fetch";
14
14
  import { appRouter } from "./routers";
15
15
  import { createContext } from "./lib/context";
16
16
  {{/if}}
17
- {{#if auth}}
17
+ {{#if (eq auth "better-auth")}}
18
18
  import { auth } from "./lib/auth";
19
19
  {{/if}}
20
20
 
@@ -31,13 +31,13 @@ const app = new Elysia()
31
31
  cors({
32
32
  origin: process.env.CORS_ORIGIN || "",
33
33
  methods: ["GET", "POST", "OPTIONS"],
34
- {{#if auth}}
34
+ {{#if (eq auth "better-auth")}}
35
35
  allowedHeaders: ["Content-Type", "Authorization"],
36
36
  credentials: true,
37
37
  {{/if}}
38
38
  }),
39
39
  )
40
- {{#if auth}}
40
+ {{#if (eq auth "better-auth")}}
41
41
  .all("/api/auth/*", async (context) => {
42
42
  const { request } = context;
43
43
  if (["POST", "GET"].includes(request.method)) {
@@ -7,7 +7,7 @@ import { appRouter } from "./routers/index";
7
7
  {{#if (eq api "orpc")}}
8
8
  import { RPCHandler } from "@orpc/server/node";
9
9
  import { appRouter } from "./routers";
10
- {{#if auth}}
10
+ {{#if (eq auth "better-auth")}}
11
11
  import { createContext } from "./lib/context";
12
12
  {{/if}}
13
13
  {{/if}}
@@ -17,7 +17,7 @@ import express from "express";
17
17
  import { streamText, type UIMessage, convertToModelMessages } from "ai";
18
18
  import { google } from "@ai-sdk/google";
19
19
  {{/if}}
20
- {{#if auth}}
20
+ {{#if (eq auth "better-auth")}}
21
21
  import { auth } from "./lib/auth";
22
22
  import { toNodeHandler } from "better-auth/node";
23
23
  {{/if}}
@@ -28,14 +28,14 @@ app.use(
28
28
  cors({
29
29
  origin: process.env.CORS_ORIGIN || "",
30
30
  methods: ["GET", "POST", "OPTIONS"],
31
- {{#if auth}}
31
+ {{#if (eq auth "better-auth")}}
32
32
  allowedHeaders: ["Content-Type", "Authorization"],
33
33
  credentials: true,
34
34
  {{/if}}
35
35
  })
36
36
  );
37
37
 
38
- {{#if auth}}
38
+ {{#if (eq auth "better-auth")}}
39
39
  app.all("/api/auth{/*path}", toNodeHandler(auth));
40
40
  {{/if}}
41
41
 
@@ -54,7 +54,7 @@ const handler = new RPCHandler(appRouter);
54
54
  app.use("/rpc{*path}", async (req, res, next) => {
55
55
  const { matched } = await handler.handle(req, res, {
56
56
  prefix: "/rpc",
57
- {{#if auth}}
57
+ {{#if (eq auth "better-auth")}}
58
58
  context: await createContext({ req }),
59
59
  {{else}}
60
60
  context: {},
@@ -85,4 +85,4 @@ app.get("/", (_req, res) => {
85
85
  const port = process.env.PORT || 3000;
86
86
  app.listen(port, () => {
87
87
  console.log(`Server is running on port ${port}`);
88
- });
88
+ });
@@ -13,7 +13,7 @@ import { RPCHandler } from "@orpc/server/node";
13
13
  import { CORSPlugin } from "@orpc/server/plugins";
14
14
  import { appRouter } from "./routers/index";
15
15
  import { createServer } from "node:http";
16
- {{#if auth}}
16
+ {{#if (eq auth "better-auth")}}
17
17
  import { createContext } from "./lib/context";
18
18
  {{/if}}
19
19
  {{/if}}
@@ -23,7 +23,7 @@ import { streamText, type UIMessage, convertToModelMessages } from "ai";
23
23
  import { google } from "@ai-sdk/google";
24
24
  {{/if}}
25
25
 
26
- {{#if auth}}
26
+ {{#if (eq auth "better-auth")}}
27
27
  import { auth } from "./lib/auth";
28
28
  {{/if}}
29
29
 
@@ -77,7 +77,7 @@ const fastify = Fastify({
77
77
 
78
78
  fastify.register(fastifyCors, baseCorsConfig);
79
79
 
80
- {{#if auth}}
80
+ {{#if (eq auth "better-auth")}}
81
81
  fastify.route({
82
82
  method: ["GET", "POST"],
83
83
  url: "/api/auth/*",
@@ -149,4 +149,4 @@ fastify.listen({ port: 3000 }, (err) => {
149
149
  process.exit(1);
150
150
  }
151
151
  console.log("Server running on port 3000");
152
- });
152
+ });
@@ -14,7 +14,7 @@ import { trpcServer } from "@hono/trpc-server";
14
14
  import { createContext } from "./lib/context";
15
15
  import { appRouter } from "./routers/index";
16
16
  {{/if}}
17
- {{#if auth}}
17
+ {{#if (eq auth "better-auth")}}
18
18
  import { auth } from "./lib/auth";
19
19
  {{/if}}
20
20
  import { Hono } from "hono";
@@ -42,14 +42,14 @@ app.use(
42
42
  origin: env.CORS_ORIGIN || "",
43
43
  {{/if}}
44
44
  allowMethods: ["GET", "POST", "OPTIONS"],
45
- {{#if auth}}
45
+ {{#if (eq auth "better-auth")}}
46
46
  allowHeaders: ["Content-Type", "Authorization"],
47
47
  credentials: true,
48
48
  {{/if}}
49
49
  })
50
50
  );
51
51
 
52
- {{#if auth}}
52
+ {{#if (eq auth "better-auth")}}
53
53
  app.on(["POST", "GET"], "/api/auth/**", (c) => auth.handler(c.req.raw));
54
54
  {{/if}}
55
55
 
@@ -133,4 +133,4 @@ export default app;
133
133
  {{#if (eq runtime "workers")}}
134
134
  export default app;
135
135
  {{/if}}
136
- {{/if}}
136
+ {{/if}}
@@ -1,5 +1,5 @@
1
1
  {{#if (eq api "orpc")}}
2
- import { {{#if auth}}protectedProcedure, {{/if}}publicProcedure } from "../lib/orpc";
2
+ import { {{#if (eq auth "better-auth")}}protectedProcedure, {{/if}}publicProcedure } from "../lib/orpc";
3
3
  import type { RouterClient } from "@orpc/server";
4
4
  {{#if (includes examples "todo")}}
5
5
  import { todoRouter } from "./todo";
@@ -9,7 +9,7 @@ export const appRouter = {
9
9
  healthCheck: publicProcedure.handler(() => {
10
10
  return "OK";
11
11
  }),
12
- {{#if auth}}
12
+ {{#if (eq auth "better-auth")}}
13
13
  privateData: protectedProcedure.handler(({ context }) => {
14
14
  return {
15
15
  message: "This is private",
@@ -25,7 +25,7 @@ export type AppRouter = typeof appRouter;
25
25
  export type AppRouterClient = RouterClient<typeof appRouter>;
26
26
  {{else if (eq api "trpc")}}
27
27
  import {
28
- {{#if auth}}protectedProcedure, {{/if}}publicProcedure,
28
+ {{#if (eq auth "better-auth")}}protectedProcedure, {{/if}}publicProcedure,
29
29
  router,
30
30
  } from "../lib/trpc";
31
31
  {{#if (includes examples "todo")}}
@@ -36,7 +36,7 @@ export const appRouter = router({
36
36
  healthCheck: publicProcedure.query(() => {
37
37
  return "OK";
38
38
  }),
39
- {{#if auth}}
39
+ {{#if (eq auth "better-auth")}}
40
40
  privateData: protectedProcedure.query(({ ctx }) => {
41
41
  return {
42
42
  message: "This is private",
@@ -17,7 +17,7 @@ import { Vite } from "alchemy/cloudflare";
17
17
  {{/if}}
18
18
  {{/if}}
19
19
  {{#if (eq serverDeploy "alchemy")}}
20
- import { Worker, WranglerJson } from "alchemy/cloudflare";
20
+ import { Worker } from "alchemy/cloudflare";
21
21
  {{#if (eq dbSetup "d1")}}
22
22
  import { D1Database } from "alchemy/cloudflare";
23
23
  {{/if}}
@@ -44,7 +44,6 @@ await Exec("db-generate", {
44
44
  });
45
45
 
46
46
  const db = await D1Database("database", {
47
- name: `${app.name}-${app.stage}-db`,
48
47
  migrationsDir: "apps/server/src/db/migrations",
49
48
  });
50
49
  {{/if}}
@@ -53,7 +52,6 @@ const db = await D1Database("database", {
53
52
  {{#if (includes frontend "next")}}
54
53
  export const web = await Next("web", {
55
54
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
56
- name: `${app.name}-${app.stage}-web`,
57
55
  bindings: {
58
56
  {{#if (eq backend "convex")}}
59
57
  NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL || "",
@@ -68,7 +66,6 @@ export const web = await Next("web", {
68
66
  {{else if (includes frontend "nuxt")}}
69
67
  export const web = await Nuxt("web", {
70
68
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
71
- name: `${app.name}-${app.stage}-web`,
72
69
  bindings: {
73
70
  {{#if (eq backend "convex")}}
74
71
  NUXT_PUBLIC_CONVEX_URL: process.env.NUXT_PUBLIC_CONVEX_URL || "",
@@ -83,7 +80,6 @@ export const web = await Nuxt("web", {
83
80
  {{else if (includes frontend "svelte")}}
84
81
  export const web = await SvelteKit("web", {
85
82
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
86
- name: `${app.name}-${app.stage}-web`,
87
83
  bindings: {
88
84
  {{#if (eq backend "convex")}}
89
85
  PUBLIC_CONVEX_URL: process.env.PUBLIC_CONVEX_URL || "",
@@ -98,7 +94,6 @@ export const web = await SvelteKit("web", {
98
94
  {{else if (includes frontend "tanstack-start")}}
99
95
  export const web = await TanStackStart("web", {
100
96
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
101
- name: `${app.name}-${app.stage}-web`,
102
97
  bindings: {
103
98
  {{#if (eq backend "convex")}}
104
99
  VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
@@ -113,7 +108,6 @@ export const web = await TanStackStart("web", {
113
108
  {{else if (includes frontend "tanstack-router")}}
114
109
  export const web = await Vite("web", {
115
110
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
116
- name: `${app.name}-${app.stage}-web`,
117
111
  assets: "dist",
118
112
  bindings: {
119
113
  {{#if (eq backend "convex")}}
@@ -129,7 +123,6 @@ export const web = await Vite("web", {
129
123
  {{else if (includes frontend "react-router")}}
130
124
  export const web = await ReactRouter("web", {
131
125
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
132
- name: `${app.name}-${app.stage}-web`,
133
126
  bindings: {
134
127
  {{#if (eq backend "convex")}}
135
128
  VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
@@ -144,7 +137,6 @@ export const web = await ReactRouter("web", {
144
137
  {{else if (includes frontend "solid")}}
145
138
  export const web = await Vite("web", {
146
139
  {{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
147
- name: `${app.name}-${app.stage}-web`,
148
140
  assets: "dist",
149
141
  bindings: {
150
142
  {{#if (eq backend "convex")}}
@@ -163,7 +155,6 @@ export const web = await Vite("web", {
163
155
  {{#if (eq serverDeploy "alchemy")}}
164
156
  export const server = await Worker("server", {
165
157
  {{#if (eq webDeploy "alchemy")}}cwd: "apps/server",{{/if}}
166
- name: `${app.name}-${app.stage}`,
167
158
  entrypoint: "src/index.ts",
168
159
  compatibility: "node",
169
160
  bindings: {
@@ -173,7 +164,7 @@ export const server = await Worker("server", {
173
164
  DATABASE_URL: alchemy.secret(process.env.DATABASE_URL),
174
165
  {{/if}}
175
166
  CORS_ORIGIN: process.env.CORS_ORIGIN || "",
176
- {{#if auth}}
167
+ {{#if (eq auth "better-auth")}}
177
168
  BETTER_AUTH_SECRET: alchemy.secret(process.env.BETTER_AUTH_SECRET),
178
169
  BETTER_AUTH_URL: process.env.BETTER_AUTH_URL || "",
179
170
  {{/if}}
@@ -188,14 +179,8 @@ export const server = await Worker("server", {
188
179
  port: 3000,
189
180
  },
190
181
  });
191
-
192
- await WranglerJson("wrangler", {
193
- worker: server,
194
- });
195
182
  {{/if}}
196
183
 
197
-
198
-
199
184
  {{#if (and (eq webDeploy "alchemy") (eq serverDeploy "alchemy"))}}
200
185
  console.log(`Web -> ${web.url}`);
201
186
  console.log(`Server -> ${server.url}`);
@@ -205,4 +190,4 @@ console.log(`Web -> ${web.url}`);
205
190
  console.log(`Server -> ${server.url}`);
206
191
  {{/if}}
207
192
 
208
- await app.finalize();
193
+ await app.finalize();
@@ -9,9 +9,17 @@ import { useQuery } from "@tanstack/react-query";
9
9
  import { trpc } from "@/utils/trpc";
10
10
  {{/if}}
11
11
  {{#if (eq backend "convex")}}
12
+ {{#if (eq auth "clerk")}}
13
+ import { Link } from "expo-router";
14
+ import { Authenticated, AuthLoading, Unauthenticated, useQuery } from "convex/react";
15
+ import { api } from "@{{ projectName }}/backend/convex/_generated/api";
16
+ import { useUser } from "@clerk/clerk-expo";
17
+ import { SignOutButton } from "@/components/sign-out-button";
18
+ {{else}}
12
19
  import { useQuery } from "convex/react";
13
20
  import { api } from "@{{ projectName }}/backend/convex/_generated/api";
14
21
  {{/if}}
22
+ {{/if}}
15
23
 
16
24
  export default function Home() {
17
25
  {{#if (eq api "orpc")}}
@@ -21,21 +29,27 @@ export default function Home() {
21
29
  const healthCheck = useQuery(trpc.healthCheck.queryOptions());
22
30
  {{/if}}
23
31
  {{#if (eq backend "convex")}}
32
+ {{#if (eq auth "clerk")}}
33
+ const { user } = useUser();
24
34
  const healthCheck = useQuery(api.healthCheck.get);
35
+ const privateData = useQuery(api.privateData.get);
36
+ {{else}}
37
+ const healthCheck = useQuery(api.healthCheck.get);
38
+ {{/if}}
25
39
  {{/if}}
26
40
 
27
41
  return (
28
42
  <Container>
29
43
  <ScrollView showsVerticalScrollIndicator={false} className="flex-1">
30
44
  <Text className="font-mono text-foreground text-3xl font-bold mb-4">
31
- BETTER T STACK
32
- </Text>
45
+ BETTER T STACK
46
+ </Text>
33
47
  <View className="bg-card border border-border rounded-xl p-6 mb-6 shadow-sm">
34
48
  {{#if (eq backend "convex")}}
35
49
  <View className="flex-row items-center gap-3">
36
50
  <View
37
51
  className={`h-3 w-3 rounded-full ${
38
- healthCheck ? "bg-green-500" : "bg-orange-500"
52
+ healthCheck ? "bg-green-500" : "bg-orange-500"
39
53
  }`}
40
54
  />
41
55
  <View className="flex-1">
@@ -89,6 +103,24 @@ export default function Home() {
89
103
  {{/unless}}
90
104
  {{/if}}
91
105
  </View>
106
+ {{#if (and (eq backend "convex") (eq auth "clerk"))}}
107
+ <Authenticated>
108
+ <Text>Hello {user?.emailAddresses[0].emailAddress}</Text>
109
+ <Text>Private Data: {privateData?.message}</Text>
110
+ <SignOutButton />
111
+ </Authenticated>
112
+ <Unauthenticated>
113
+ <Link href="/(auth)/sign-in">
114
+ <Text>Sign in</Text>
115
+ </Link>
116
+ <Link href="/(auth)/sign-up">
117
+ <Text>Sign up</Text>
118
+ </Link>
119
+ </Unauthenticated>
120
+ <AuthLoading>
121
+ <Text>Loading...</Text>
122
+ </AuthLoading>
123
+ {{/if}}
92
124
  </ScrollView>
93
125
  </Container>
94
126
  );
@@ -3,6 +3,11 @@ import "@/polyfills";
3
3
  {{/if}}
4
4
  {{#if (eq backend "convex")}}
5
5
  import { ConvexProvider, ConvexReactClient } from "convex/react";
6
+ {{#if (eq auth "clerk")}}
7
+ import { ClerkProvider, useAuth } from "@clerk/clerk-expo";
8
+ import { ConvexProviderWithClerk } from "convex/react-clerk";
9
+ import { tokenCache } from "@clerk/clerk-expo/token-cache";
10
+ {{/if}}
6
11
  {{else}}
7
12
  {{#unless (eq api "none")}}
8
13
  import { QueryClientProvider } from "@tanstack/react-query";
@@ -72,6 +77,28 @@ export default function RootLayout() {
72
77
  }
73
78
  return (
74
79
  {{#if (eq backend "convex")}}
80
+ {{#if (eq auth "clerk")}}
81
+ <ClerkProvider
82
+ tokenCache={tokenCache}
83
+ publishableKey={process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY}
84
+ >
85
+ <ConvexProviderWithClerk client={convex} useAuth={useAuth}>
86
+ <ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
87
+ <StatusBar style={isDarkColorScheme ? "light" : "dark"} />
88
+ <GestureHandlerRootView style=\{{ flex: 1 }}>
89
+ <Stack>
90
+ <Stack.Screen name="(drawer)" options=\{{ headerShown: false }} />
91
+ <Stack.Screen name="(auth)" options=\{{ headerShown: false }} />
92
+ <Stack.Screen
93
+ name="modal"
94
+ options=\{{ title: "Modal", presentation: "modal" }}
95
+ />
96
+ </Stack>
97
+ </GestureHandlerRootView>
98
+ </ThemeProvider>
99
+ </ConvexProviderWithClerk>
100
+ </ClerkProvider>
101
+ {{else}}
75
102
  <ConvexProvider client={convex}>
76
103
  <ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
77
104
  <StatusBar style={isDarkColorScheme ? "light" : "dark"} />
@@ -86,6 +113,7 @@ export default function RootLayout() {
86
113
  </GestureHandlerRootView>
87
114
  </ThemeProvider>
88
115
  </ConvexProvider>
116
+ {{/if}}
89
117
  {{else}}
90
118
  {{#unless (eq api "none")}}
91
119
  <QueryClientProvider client={queryClient}>
@@ -22,6 +22,7 @@
22
22
  {{/if}}
23
23
  "expo": "^53.0.4",
24
24
  "expo-constants": "~17.1.4",
25
+ "expo-crypto": "~14.1.5",
25
26
  "expo-linking": "~7.1.4",
26
27
  "expo-navigation-bar": "~4.2.3",
27
28
  "expo-router": "~5.0.3",
@@ -11,9 +11,17 @@ import { useQuery } from "@tanstack/react-query";
11
11
  import { trpc } from "@/utils/trpc";
12
12
  {{/if}}
13
13
  {{#if (eq backend "convex")}}
14
+ {{#if (eq auth "clerk")}}
15
+ import { Link } from "expo-router";
16
+ import { Authenticated, AuthLoading, Unauthenticated, useQuery } from "convex/react";
17
+ import { api } from "@{{ projectName }}/backend/convex/_generated/api";
18
+ import { useUser } from "@clerk/clerk-expo";
19
+ import { SignOutButton } from "@/components/sign-out-button";
20
+ {{else}}
14
21
  import { useQuery } from "convex/react";
15
22
  import { api } from "@{{ projectName }}/backend/convex/_generated/api";
16
23
  {{/if}}
24
+ {{/if}}
17
25
 
18
26
  export default function Home() {
19
27
  {{#if (eq api "orpc")}}
@@ -23,7 +31,13 @@ export default function Home() {
23
31
  const healthCheck = useQuery(trpc.healthCheck.queryOptions());
24
32
  {{/if}}
25
33
  {{#if (eq backend "convex")}}
34
+ {{#if (eq auth "clerk")}}
35
+ const { user } = useUser();
26
36
  const healthCheck = useQuery(api.healthCheck.get);
37
+ const privateData = useQuery(api.privateData.get);
38
+ {{else}}
39
+ const healthCheck = useQuery(api.healthCheck.get);
40
+ {{/if}}
27
41
  {{/if}}
28
42
 
29
43
  return (
@@ -105,6 +119,24 @@ export default function Home() {
105
119
  {{/unless}}
106
120
  {{/if}}
107
121
  </View>
122
+ {{#if (and (eq backend "convex") (eq auth "clerk"))}}
123
+ <Authenticated>
124
+ <Text>Hello {user?.emailAddresses[0].emailAddress}</Text>
125
+ <Text>Private Data: {privateData?.message}</Text>
126
+ <SignOutButton />
127
+ </Authenticated>
128
+ <Unauthenticated>
129
+ <Link href="/(auth)/sign-in">
130
+ <Text>Sign in</Text>
131
+ </Link>
132
+ <Link href="/(auth)/sign-up">
133
+ <Text>Sign up</Text>
134
+ </Link>
135
+ </Unauthenticated>
136
+ <AuthLoading>
137
+ <Text>Loading...</Text>
138
+ </AuthLoading>
139
+ {{/if}}
108
140
  </ScrollView>
109
141
  </Container>
110
142
  );
@@ -9,6 +9,11 @@ import { queryClient } from "@/utils/orpc";
9
9
  {{/if}}
10
10
  {{#if (eq backend "convex")}}
11
11
  import { ConvexProvider, ConvexReactClient } from "convex/react";
12
+ {{#if (eq auth "clerk")}}
13
+ import { ClerkProvider, useAuth } from "@clerk/clerk-expo";
14
+ import { ConvexProviderWithClerk } from "convex/react-clerk";
15
+ import { tokenCache } from "@clerk/clerk-expo/token-cache";
16
+ {{/if}}
12
17
  {{else}}
13
18
  {{#unless (eq api "none")}}
14
19
  import { QueryClientProvider } from "@tanstack/react-query";
@@ -34,6 +39,35 @@ export default function RootLayout() {
34
39
 
35
40
  return (
36
41
  {{#if (eq backend "convex")}}
42
+ {{#if (eq auth "clerk")}}
43
+ <ClerkProvider
44
+ tokenCache={tokenCache}
45
+ publishableKey={process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY}
46
+ >
47
+ <ConvexProviderWithClerk client={convex} useAuth={useAuth}>
48
+ <GestureHandlerRootView style=\{{ flex: 1 }}>
49
+ <Stack
50
+ screenOptions=\{{
51
+ headerStyle: {
52
+ backgroundColor: theme.colors.background,
53
+ },
54
+ headerTitleStyle: {
55
+ color: theme.colors.foreground,
56
+ },
57
+ headerTintColor: theme.colors.foreground,
58
+ }}
59
+ >
60
+ <Stack.Screen name="(drawer)" options=\{{ headerShown: false }} />
61
+ <Stack.Screen name="(auth)" options=\{{ headerShown: false }} />
62
+ <Stack.Screen
63
+ name="modal"
64
+ options=\{{ title: "Modal", presentation: "modal" }}
65
+ />
66
+ </Stack>
67
+ </GestureHandlerRootView>
68
+ </ConvexProviderWithClerk>
69
+ </ClerkProvider>
70
+ {{else}}
37
71
  <ConvexProvider client={convex}>
38
72
  <GestureHandlerRootView style=\{{ flex: 1 }}>
39
73
  <Stack
@@ -55,6 +89,7 @@ export default function RootLayout() {
55
89
  </Stack>
56
90
  </GestureHandlerRootView>
57
91
  </ConvexProvider>
92
+ {{/if}}
58
93
  {{else}}
59
94
  {{#unless (eq api "none")}}
60
95
  <QueryClientProvider client={queryClient}>
@@ -21,6 +21,7 @@
21
21
  "babel-plugin-react-compiler": "^19.1.0-rc.2",
22
22
  "expo": "^53.0.17",
23
23
  "expo-constants": "~17.1.7",
24
+ "expo-crypto": "~14.1.5",
24
25
  "expo-linking": "~7.1.7",
25
26
  "expo-router": "~5.1.3",
26
27
  "expo-secure-store": "~14.2.3",
@@ -1,12 +1,12 @@
1
1
  <script setup lang="ts">
2
2
  import ModeToggle from './ModeToggle.vue'
3
- {{#if auth}}
3
+ {{#if (eq auth "better-auth")}}
4
4
  import UserMenu from './UserMenu.vue'
5
5
  {{/if}}
6
6
 
7
7
  const links = [
8
8
  { to: "/", label: "Home" },
9
- {{#if auth}}
9
+ {{#if (or (eq auth "better-auth") (eq auth "clerk"))}}
10
10
  { to: "/dashboard", label: "Dashboard" },
11
11
  {{/if}}
12
12
  {{#if (includes examples "todo")}}
@@ -34,7 +34,7 @@ const links = [
34
34
  </nav>
35
35
  <div class="flex items-center gap-2">
36
36
  <ModeToggle />
37
- {{#if auth}}
37
+ {{#if (eq auth "better-auth")}}
38
38
  <UserMenu />
39
39
  {{/if}}
40
40
  </div>