create-vexcms 0.0.20 → 0.1.0-alpha.3

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 (157) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +98 -80
  3. package/dist/index.js +974 -639
  4. package/dist/index.mjs +30976 -0
  5. package/package.json +35 -15
  6. package/templates/base-nextjs/README.md +59 -203
  7. package/templates/base-nextjs/_env.example +7 -9
  8. package/templates/base-nextjs/_gitignore +41 -1
  9. package/templates/base-nextjs/convex/_generated/api.d.ts +6 -62
  10. package/templates/base-nextjs/convex/_generated/server.d.ts +19 -0
  11. package/templates/base-nextjs/convex/_generated/server.js +8 -0
  12. package/templates/base-nextjs/convex/auth/api.ts +49 -3
  13. package/templates/base-nextjs/convex/auth/db.ts +42 -300
  14. package/templates/base-nextjs/convex/auth/index.ts +11 -7
  15. package/templates/base-nextjs/convex/auth/options.ts +5 -29
  16. package/templates/base-nextjs/convex/auth/plugins/index.ts +15 -5
  17. package/templates/base-nextjs/convex/auth/sessions.ts +9 -15
  18. package/templates/base-nextjs/convex/http.ts +18 -3
  19. package/templates/base-nextjs/convex/schema.ts +104 -2
  20. package/templates/base-nextjs/convex/tsconfig.json +2 -2
  21. package/templates/base-nextjs/convex/vex/firstUser.ts +10 -84
  22. package/templates/base-nextjs/convex/vex/globals.ts +19 -82
  23. package/templates/base-nextjs/convex/vex/media.ts +19 -246
  24. package/templates/base-nextjs/convex/vex.schema.ts +138 -0
  25. package/templates/base-nextjs/convex/vex.ts +19 -0
  26. package/templates/base-nextjs/convex.json +6 -0
  27. package/templates/base-nextjs/eslint.config.mjs +1 -21
  28. package/templates/base-nextjs/next.config.ts +10 -0
  29. package/templates/base-nextjs/package.json +46 -48
  30. package/templates/base-nextjs/src/app/(frontend)/@auth/(...)auth/[pathname]/view.tsx +17 -5
  31. package/templates/base-nextjs/src/app/(frontend)/auth/[pathname]/view.tsx +2 -4
  32. package/templates/base-nextjs/src/app/(frontend)/layout.tsx +12 -2
  33. package/templates/base-nextjs/src/app/(frontend)/page.tsx +2 -113
  34. package/templates/base-nextjs/src/app/(vexcms)/admin/[[...path]]/page.tsx +40 -0
  35. package/templates/base-nextjs/src/app/(vexcms)/admin/clientProviders.tsx +22 -0
  36. package/templates/base-nextjs/src/app/(vexcms)/admin/layout.tsx +19 -0
  37. package/templates/base-nextjs/src/app/globals.css +240 -104
  38. package/templates/base-nextjs/src/app/layout.tsx +23 -13
  39. package/templates/base-nextjs/src/app/unauthorized/page.tsx +24 -0
  40. package/templates/base-nextjs/src/auth/access.ts +46 -0
  41. package/templates/base-nextjs/src/auth/client.tsx +17 -5
  42. package/templates/base-nextjs/src/auth/hasPermission.ts +39 -0
  43. package/templates/base-nextjs/src/auth/serverUtils.ts +15 -25
  44. package/templates/base-nextjs/src/components/WelcomePage.tsx +116 -0
  45. package/templates/base-nextjs/src/components/component-example.tsx +56 -464
  46. package/templates/base-nextjs/src/components/providers/auth.tsx +13 -0
  47. package/templates/base-nextjs/src/components/providers/client.tsx +6 -1
  48. package/templates/base-nextjs/src/components/providers/convex.tsx +53 -21
  49. package/templates/base-nextjs/src/components/providers/server.tsx +10 -7
  50. package/templates/{marketing-site → base-nextjs}/src/components/ui/accordion.tsx +30 -32
  51. package/templates/base-nextjs/src/components/ui/badge.tsx +10 -13
  52. package/templates/base-nextjs/src/components/ui/input.tsx +35 -5
  53. package/templates/base-nextjs/src/context/AuthContext.tsx +29 -0
  54. package/templates/base-nextjs/src/db/constants/auth.ts +0 -1
  55. package/templates/base-nextjs/src/db/constants/index.ts +22 -35
  56. package/templates/base-nextjs/src/lib/utils.ts +0 -12
  57. package/templates/base-nextjs/src/proxy.ts +97 -12
  58. package/templates/base-nextjs/src/vex.config.ts +35 -0
  59. package/templates/base-nextjs/src/vex.types.ts +293 -0
  60. package/templates/base-nextjs/src/vexcms/collections/images.ts +15 -0
  61. package/templates/base-nextjs/src/vexcms/collections/index.ts +2 -1
  62. package/templates/base-nextjs/src/vexcms/collections/users.ts +7 -35
  63. package/templates/base-nextjs/tsconfig.json +3 -0
  64. package/templates/marketing-site/convex/_generated/api.d.ts +81 -0
  65. package/templates/marketing-site/convex/_generated/api.js +23 -0
  66. package/templates/marketing-site/convex/_generated/dataModel.d.ts +60 -0
  67. package/templates/marketing-site/convex/_generated/server.d.ts +162 -0
  68. package/templates/marketing-site/convex/_generated/server.js +101 -0
  69. package/templates/marketing-site/convex/footers.ts +11 -7
  70. package/templates/marketing-site/convex/headers.ts +15 -5
  71. package/templates/marketing-site/convex/pages.ts +20 -35
  72. package/templates/marketing-site/convex/schema.ts +119 -0
  73. package/templates/marketing-site/convex/seed.ts +582 -35
  74. package/templates/marketing-site/convex/siteSettings.ts +19 -5
  75. package/templates/marketing-site/convex/theme.ts +55 -61
  76. package/templates/marketing-site/convex/vex.schema.ts +355 -0
  77. package/templates/marketing-site/src/app/(frontend)/PageContent.tsx +27 -160
  78. package/templates/marketing-site/src/app/(frontend)/[slug]/page.tsx +6 -9
  79. package/templates/marketing-site/src/app/(frontend)/layout.tsx +4 -2
  80. package/templates/marketing-site/src/app/(frontend)/page.tsx +2 -5
  81. package/templates/marketing-site/src/components/SiteFooter.tsx +6 -3
  82. package/templates/marketing-site/src/components/SiteHeader.tsx +6 -3
  83. package/templates/marketing-site/src/components/ThemeLive.tsx +59 -0
  84. package/templates/marketing-site/src/components/ThemeStyle.tsx +45 -89
  85. package/templates/marketing-site/src/components/motion-primitives/animated-group.tsx +44 -120
  86. package/templates/marketing-site/src/components/motion-primitives/reveal.module.css +32 -0
  87. package/templates/marketing-site/src/components/motion-primitives/text-effect.tsx +41 -267
  88. package/templates/marketing-site/src/lib/metadata.ts +51 -72
  89. package/templates/marketing-site/src/vex.config.ts +35 -0
  90. package/templates/marketing-site/src/vex.types.ts +634 -0
  91. package/templates/marketing-site/src/vexcms/api.ts +23 -0
  92. package/templates/marketing-site/src/vexcms/blocks/CTA/config.ts +3 -3
  93. package/templates/marketing-site/src/vexcms/blocks/CTA/index.tsx +2 -2
  94. package/templates/marketing-site/src/vexcms/blocks/FAQ/config.ts +4 -4
  95. package/templates/marketing-site/src/vexcms/blocks/FAQ/index.tsx +2 -2
  96. package/templates/marketing-site/src/vexcms/blocks/Features/config.ts +4 -8
  97. package/templates/marketing-site/src/vexcms/blocks/Features/index.tsx +2 -2
  98. package/templates/marketing-site/src/vexcms/blocks/Footer/config.ts +7 -11
  99. package/templates/marketing-site/src/vexcms/blocks/Footer/index.tsx +1 -1
  100. package/templates/marketing-site/src/vexcms/blocks/Header/config.ts +9 -9
  101. package/templates/marketing-site/src/vexcms/blocks/Header/index.tsx +4 -5
  102. package/templates/marketing-site/src/vexcms/blocks/Hero/config.ts +3 -4
  103. package/templates/marketing-site/src/vexcms/blocks/Hero/index.tsx +12 -55
  104. package/templates/marketing-site/src/vexcms/blocks/HowItWorks/config.ts +4 -9
  105. package/templates/marketing-site/src/vexcms/blocks/HowItWorks/index.tsx +3 -6
  106. package/templates/marketing-site/src/vexcms/blocks/Roadmap/config.ts +28 -68
  107. package/templates/marketing-site/src/vexcms/blocks/Roadmap/index.tsx +13 -43
  108. package/templates/marketing-site/src/vexcms/blocks/config.ts +7 -22
  109. package/templates/marketing-site/src/vexcms/blocks/constants.ts +2 -3
  110. package/templates/marketing-site/src/vexcms/blocks/index.ts +9 -8
  111. package/templates/marketing-site/src/vexcms/collections/footers.ts +1 -1
  112. package/templates/marketing-site/src/vexcms/collections/headers.ts +1 -1
  113. package/templates/marketing-site/src/vexcms/collections/index.ts +2 -1
  114. package/templates/marketing-site/src/vexcms/collections/pages.ts +12 -21
  115. package/templates/marketing-site/src/vexcms/collections/themeColors.ts +118 -0
  116. package/templates/marketing-site/src/vexcms/collections/themes.ts +29 -111
  117. package/templates/marketing-site/src/vexcms/globals/index.ts +1 -1
  118. package/templates/marketing-site/src/vexcms/globals/siteSettings.ts +43 -27
  119. package/templates/base-nextjs/convex/auth/adapter/index.ts +0 -230
  120. package/templates/base-nextjs/convex/auth/adapter/utils.ts +0 -547
  121. package/templates/base-nextjs/convex/auth/config.ts +0 -10
  122. package/templates/base-nextjs/convex/vex/auth.ts +0 -38
  123. package/templates/base-nextjs/convex/vex/collections.ts +0 -333
  124. package/templates/base-nextjs/convex/vex/helpers.ts +0 -33
  125. package/templates/base-nextjs/convex/vex/impersonation.ts +0 -51
  126. package/templates/base-nextjs/convex/vex/migrate.ts +0 -74
  127. package/templates/base-nextjs/convex/vex/model/collections.ts +0 -196
  128. package/templates/base-nextjs/convex/vex/model/media.ts +0 -87
  129. package/templates/base-nextjs/convex/vex/model/versions.ts +0 -254
  130. package/templates/base-nextjs/convex/vex/previewSnapshot.ts +0 -53
  131. package/templates/base-nextjs/convex/vex/versions.ts +0 -648
  132. package/templates/base-nextjs/src/app/admin/AdminLayoutWrapper.tsx +0 -33
  133. package/templates/base-nextjs/src/app/admin/AdminPageWrapper.tsx +0 -38
  134. package/templates/base-nextjs/src/app/admin/RichTextFieldWithMedia.tsx +0 -101
  135. package/templates/base-nextjs/src/app/admin/[[...path]]/page.tsx +0 -15
  136. package/templates/base-nextjs/src/app/admin/layout.tsx +0 -51
  137. package/templates/base-nextjs/src/app/favicon.ico +0 -0
  138. package/templates/base-nextjs/src/components/providers/theme.tsx +0 -11
  139. package/templates/base-nextjs/src/components/ui/theme-toggle.tsx +0 -67
  140. package/templates/base-nextjs/src/db/types.ts +0 -6
  141. package/templates/base-nextjs/src/vexcms/access.ts +0 -44
  142. package/templates/base-nextjs/src/vexcms/auth.ts +0 -4
  143. package/templates/base-nextjs/src/vexcms/collections/media.ts +0 -15
  144. package/templates/base-nextjs/vex.config.ts +0 -25
  145. package/templates/marketing-site/public/favicons/favicon.ico +0 -0
  146. package/templates/marketing-site/src/app/(frontend)/preview/[slug]/PreviewPageContent.tsx +0 -55
  147. package/templates/marketing-site/src/app/(frontend)/preview/[slug]/page.tsx +0 -27
  148. package/templates/marketing-site/src/app/(frontend)/preview/layout.tsx +0 -18
  149. package/templates/marketing-site/src/app/admin/AdminLayoutWrapper.tsx +0 -71
  150. package/templates/marketing-site/src/components/ThemeInjector.tsx +0 -128
  151. package/templates/marketing-site/src/components/admin/IconPickerField.tsx +0 -134
  152. package/templates/marketing-site/src/components/admin/ThemeImport.tsx +0 -174
  153. package/templates/marketing-site/src/components/admin/ThemeImportField.tsx +0 -33
  154. package/templates/marketing-site/src/db/constants/index.ts +0 -52
  155. package/templates/marketing-site/src/lib/colorConvert.ts +0 -171
  156. package/templates/marketing-site/src/vexcms/access.ts +0 -36
  157. package/templates/marketing-site/vex.config.ts +0 -32
package/package.json CHANGED
@@ -1,6 +1,24 @@
1
1
  {
2
2
  "name": "create-vexcms",
3
- "version": "0.0.20",
3
+ "version": "0.1.0-alpha.3",
4
+ "description": "Scaffold a new VexCMS project",
5
+ "keywords": [
6
+ "cms",
7
+ "headless-cms",
8
+ "convex",
9
+ "typescript",
10
+ "create",
11
+ "scaffold"
12
+ ],
13
+ "license": "Apache-2.0",
14
+ "author": "Isaiah Anyimi",
15
+ "homepage": "https://docs.vexcms.dev",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/ianyimi/vex.git",
19
+ "directory": "packages/create-vexcms"
20
+ },
21
+ "sideEffects": false,
4
22
  "type": "module",
5
23
  "bin": {
6
24
  "create-vexcms": "./dist/index.js"
@@ -10,24 +28,26 @@
10
28
  "templates"
11
29
  ],
12
30
  "publishConfig": {
13
- "access": "public"
31
+ "access": "public",
32
+ "tag": "alpha"
14
33
  },
15
34
  "dependencies": {
16
- "chalk": "^5.3.0",
17
- "commander": "^12.0.0",
18
- "execa": "^9.5.2",
19
- "fs-extra": "^11.2.0",
20
- "@inquirer/prompts": "^7.2.0",
21
- "ora": "^8.1.0",
22
- "sort-package-json": "^2.10.0",
23
- "validate-npm-package-name": "^5.0.0"
35
+ "chalk": "5.3.0",
36
+ "commander": "12.1.0",
37
+ "execa": "9.6.1",
38
+ "fs-extra": "11.3.6",
39
+ "@inquirer/prompts": "7.10.1",
40
+ "ora": "8.1.0",
41
+ "sort-package-json": "2.10.0",
42
+ "validate-npm-package-name": "5.0.0",
43
+ "yaml": "2.9.0"
24
44
  },
25
45
  "devDependencies": {
26
- "@types/fs-extra": "^11.0.4",
27
- "@types/validate-npm-package-name": "^4.0.2",
28
- "tsup": "^8.5.0",
29
- "typescript": "^5.9.3",
30
- "vitest": "^4.0.0"
46
+ "@types/fs-extra": "11.0.4",
47
+ "@types/validate-npm-package-name": "4.0.2",
48
+ "tsup": "8.5.1",
49
+ "typescript": "6.0.3",
50
+ "vitest": "4.1.10"
31
51
  },
32
52
  "scripts": {
33
53
  "build": "tsup src/index.ts --format esm --dts",
@@ -1,173 +1,65 @@
1
- # Next.js + Better Auth + Convex + shadcn/ui Template
1
+ # {{PROJECT_NAME}}
2
2
 
3
- A modern, production-ready SaaS template built with:
4
-
5
- - **[Next.js](https://nextjs.org)** - The React framework for production with App Router
6
- - **[Better Auth](https://www.better-auth.com/)** - Modern authentication with email/password and OAuth providers
7
- - **[Convex](https://convex.dev/)** - Real-time database and backend
8
- - **[shadcn/ui](https://ui.shadcn.com/)** - Beautifully designed components built on Radix UI
9
- - **[Tailwind CSS](https://tailwindcss.com/)** - Utility-first CSS framework
3
+ A VexCMS project built with Next.js, Better Auth, and Convex.
10
4
 
11
5
  ## Getting Started
12
6
 
13
- ### 1. Prerequisites
14
-
15
- - Node.js 18+ and npm/pnpm/yarn installed
16
- - A Convex account (free at [convex.dev](https://convex.dev))
17
-
18
- ### 2. Clone and Install
7
+ ### 1. Install dependencies
19
8
 
20
9
  ```bash
21
- # Clone this template
22
- git clone <your-repo-url>
23
- cd <your-project-name>
24
-
25
- # Install dependencies
26
- npm install
27
- # or
28
10
  pnpm install
29
- # or
30
- yarn install
31
11
  ```
32
12
 
33
- ### 3. Environment Setup
34
-
35
- Copy the example environment file:
36
-
37
- ```bash
38
- cp .env.example .env
39
- ```
40
-
41
- ### 4. Generate Better Auth Secret
42
-
43
- Generate a secure secret for Better Auth:
44
-
45
- ```bash
46
- npm run secret:create
47
- # or
48
- pnpm secret:create
49
- # or
50
- yarn secret:create
51
- ```
52
-
53
- This will generate a random 32-character hex string and copy it to your clipboard.
54
-
55
- ### 5. Configure Convex
56
-
57
- #### Set up Convex project
13
+ ### 2. Start Convex
58
14
 
59
15
  ```bash
60
16
  npx convex dev
61
17
  ```
62
18
 
63
- This will:
64
-
65
- - Create a new Convex project (or link to an existing one)
66
- - Generate your `CONVEX_URL` and `NEXT_PUBLIC_CONVEX_URL`
67
- - Start the Convex development server
68
-
69
- #### Add environment variables to Convex
70
-
71
- You need to add two critical environment variables to your Convex deployment via the [Convex Dashboard](https://dashboard.convex.dev):
19
+ On first run this creates (or links) a Convex project and prints your
20
+ deployment's URL and site URL.
72
21
 
73
- 1. **BETTER_AUTH_SECRET**: Paste the secret you generated in step 4
74
- 2. **SITE_URL**: Set to your application URL
75
- - Development: `http://localhost:3000` (or whatever port your dev server uses)
76
- - Production: Your production domain (e.g., `https://yourdomain.com`)
22
+ ### 3. Fill in your environment variables
77
23
 
78
- To add these in the Convex Dashboard:
79
-
80
- 1. Go to your project at [dashboard.convex.dev](https://dashboard.convex.dev)
81
- 2. Navigate to "Settings" → "Environment Variables"
82
- 3. Add both `BETTER_AUTH_SECRET` and `SITE_URL`
83
-
84
- ### 6. Update Your .env File
85
-
86
- Update your `.env` file with the values from Convex setup:
24
+ `.env.local` already has a generated `BETTER_AUTH_SECRET` and a
25
+ `http://localhost:3010` `SITE_URL`/`NEXT_PUBLIC_SITE_URL` pair, so the app
26
+ builds and typechecks immediately. Replace the placeholder Convex URLs with the
27
+ real ones `npx convex dev` printed:
87
28
 
88
29
  ```env
89
- NODE_ENV=development
90
-
91
- # From Convex setup
92
- CONVEX_URL=https://your-deployment.convex.cloud
93
30
  NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud
94
- CONVEX_SITE_URL=https://your-deployment.convex.site
95
31
  NEXT_PUBLIC_CONVEX_SITE_URL=https://your-deployment.convex.site
96
-
97
- # Better Auth (same secret you added to Convex Dashboard)
98
- BETTER_AUTH_SECRET=your-generated-secret-here
99
- NEXT_PUBLIC_SITE_URL=http://localhost:3000
100
32
  ```
101
33
 
102
- ### 7. Start Development
34
+ Better Auth runs inside your Convex deployment, not in the Next.js server —
35
+ it does **not** read `.env.local`. Set the same two values on the
36
+ deployment itself:
103
37
 
104
38
  ```bash
105
- # Terminal 1: Run Convex dev server
106
- npx convex dev
107
-
108
- # Terminal 2: Run the application
109
- npm run dev
110
- # or
111
- pnpm dev
112
- # or
113
- yarn dev
39
+ npx convex env set SITE_URL http://localhost:3010
40
+ npx convex env set BETTER_AUTH_SECRET <the BETTER_AUTH_SECRET value from .env.local>
114
41
  ```
115
42
 
116
- Visit `http://localhost:3000` to see your application running.
43
+ Skipping this step is the most common cause of a `403` on your first sign-in
44
+ attempt.
117
45
 
118
- ## Authentication Setup
119
-
120
- This project uses Better Auth for authentication.
121
-
122
- <!-- {{OAUTH_SETUP_GUIDE}} -->
46
+ ### 4. Run the dev servers
123
47
 
124
- ## Customizing Authentication
125
-
126
- ### Adding OAuth Providers
127
-
128
- To add or modify OAuth providers:
129
-
130
- 1. **Update Better Auth configuration** in `convex/auth/index.ts`:
48
+ ```bash
49
+ # Terminal 1
50
+ pnpm vex:dev
131
51
 
132
- ```typescript
133
- export const createAuth = (ctx: GenericActionCtx<DataModel>) => {
134
- return betterAuth({
135
- socialProviders: {
136
- google: {
137
- clientId: process.env.GOOGLE_CLIENT_ID!,
138
- clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
139
- redirectURI: `${process.env.SITE_URL}/api/auth/callback/google`,
140
- },
141
- // Add more providers
142
- github: {
143
- clientId: process.env.GITHUB_CLIENT_ID!,
144
- clientSecret: process.env.GITHUB_CLIENT_SECRET!,
145
- },
146
- },
147
- // ... rest of config
148
- })
149
- }
52
+ # Terminal 2
53
+ pnpm dev
150
54
  ```
151
55
 
152
- 2. **Add credentials to Convex Dashboard** as environment variables
153
-
154
- 3. **Consult the Better Auth documentation** for provider-specific configuration:
155
- - [Better Auth Providers](https://www.better-auth.com/docs/authentication/social-login)
156
-
157
- ### Customizing User Schema
158
-
159
- To add custom fields to your user model:
56
+ ### 5. Create your admin account
160
57
 
161
- 1. Update the `user.additionalFields` in `convex/auth/index.ts`
162
- 2. Update your Convex schema accordingly
163
- 3. See [Better Auth User Management](https://www.better-auth.com/docs/concepts/user-management) for details
58
+ Visit `http://localhost:3010`, click "Create Admin Account", and sign up. The
59
+ first user to sign up on a fresh project is automatically promoted to admin —
60
+ see `convex/vex/firstUser.ts`. From there, "Go to Admin Panel" opens `/admin`.
164
61
 
165
- ### Email/Password Configuration
166
-
167
- The template has email/password authentication enabled by default. To customize:
168
-
169
- - [Better Auth Email/Password Docs](https://www.better-auth.com/docs/authentication/email-password)
170
- - [Email Verification Setup](https://www.better-auth.com/docs/authentication/email-verification)
62
+ <!-- {{OAUTH_SETUP_GUIDE}} -->
171
63
 
172
64
  ## Project Structure
173
65
 
@@ -175,82 +67,46 @@ The template has email/password authentication enabled by default. To customize:
175
67
  .
176
68
  ├── src/
177
69
  │ ├── app/ # Next.js App Router
178
- │ │ ├── (frontend)/ # Frontend routes group
179
- │ │ ├── api/ # API routes
180
- │ │ └── layout.tsx # Root layout
181
- │ ├── auth/ # Authentication components
182
- │ ├── components/ # React components
183
- │ ├── lib/ # Utilities and helpers
184
- │ └── env.mjs # Typed environment variables
185
- ├── convex/ # Convex backend
186
- │ ├── auth/ # Better Auth integration
187
- │ ├── schema.ts # Database schema
188
- │ └── *.ts # Convex functions (queries, mutations, actions)
189
- ├── public/ # Static assets
190
- └── .env # Environment variables (not committed)
70
+ │ │ ├── (frontend)/ # Public site routes
71
+ │ │ ├── (vexcms)/admin/ # Admin panel routes
72
+ │ │ └── layout.tsx # Root layout
73
+ │ ├── auth/ # Auth client + server helpers, access control
74
+ │ ├── components/ # React components
75
+ │ ├── vexcms/collections/ # Collection definitions
76
+ │ ├── vex.config.ts # VexCMS config
77
+ │ └── env.mjs # Typed environment variables
78
+ ├── convex/ # Convex backend
79
+ │ ├── auth/ # Better Auth config + plugins
80
+ │ ├── vex/ # Bootstrap, media, globals endpoints
81
+ │ └── schema.ts # Database schema
82
+ └── .env.local # Environment variables (not committed)
191
83
  ```
192
84
 
193
- ## Development Scripts
85
+ ## Scripts
194
86
 
195
87
  ```bash
196
- npm run dev # Start development server
197
- npm run build # Build for production
198
- npm run start # Start production server
199
- npm run lint # Lint code
200
- npm run typecheck # Type check without emitting
201
- npm run format # Format code with Prettier
202
- npm run format:check # Check code formatting
203
- npm run secret:create # Generate a Better Auth secret
88
+ pnpm dev # Start the Next.js dev server
89
+ pnpm vex:dev # Start VexCMS's schema watcher + convex dev
90
+ pnpm vex:generate # Regenerate the Convex schema and types once
91
+ pnpm build # Build for production
92
+ pnpm typecheck # Type check without emitting
93
+ pnpm lint # Lint
94
+ pnpm format # Format with Prettier
95
+ pnpm secret:create # Generate a Better Auth secret
204
96
  ```
205
97
 
206
- ## Documentation Resources
207
-
208
- ### Core Technologies
98
+ ## Documentation
209
99
 
100
+ - **VexCMS**: [docs.vexcms.dev](https://docs.vexcms.dev)
210
101
  - **Next.js**: [nextjs.org/docs](https://nextjs.org/docs)
211
102
  - **Better Auth**: [better-auth.com/docs](https://www.better-auth.com/docs)
212
103
  - **Convex**: [docs.convex.dev](https://docs.convex.dev)
213
- - **shadcn/ui**: [ui.shadcn.com](https://ui.shadcn.com)
214
- - **Tailwind CSS**: [tailwindcss.com/docs](https://tailwindcss.com/docs)
215
-
216
- ### Integration Guides
217
-
218
- - **Better Auth + Convex**: [better-auth.com/docs/integrations/convex](https://www.better-auth.com/docs/integrations/convex)
219
- - **Better Auth + Next.js**: [better-auth.com/docs/integrations/nextjs](https://www.better-auth.com/docs/integrations/nextjs)
220
104
 
221
105
  ## Deployment
222
106
 
223
- ### Deploy to Production
224
-
225
- 1. **Deploy Convex Backend**:
226
-
227
- ```bash
228
- npx convex deploy
229
- ```
230
-
231
- 2. **Update Convex environment variables** in production:
232
- - Set `SITE_URL` to your production domain
233
- - Keep `BETTER_AUTH_SECRET` the same (or rotate it)
234
-
235
- 3. **Deploy your application** to your hosting provider (Vercel recommended):
236
-
237
- For Vercel:
238
-
239
- ```bash
240
- npm install -g vercel
241
- vercel
242
- ```
243
-
244
- Or connect your GitHub repository to Vercel for automatic deployments.
245
-
246
- 4. **Update environment variables** in your hosting provider with production values:
247
- - `NEXT_PUBLIC_CONVEX_URL`
248
- - `NEXT_PUBLIC_CONVEX_SITE_URL`
249
- - `NEXT_PUBLIC_SITE_URL`
250
- - `BETTER_AUTH_SECRET`
251
-
252
- See [Next.js Deployment](https://nextjs.org/docs/app/building-your-application/deploying) and [Convex Production Deployment](https://docs.convex.dev/production/hosting) for detailed deployment instructions.
253
-
254
- ## License
255
-
256
- MIT
107
+ 1. `npx convex deploy`
108
+ 2. In the Convex Dashboard, set `SITE_URL` to your production domain (keep
109
+ `BETTER_AUTH_SECRET` the same, or rotate it and update both places).
110
+ 3. Deploy the Next.js app (e.g. Vercel) with `NEXT_PUBLIC_CONVEX_URL`,
111
+ `NEXT_PUBLIC_CONVEX_SITE_URL`, `NEXT_PUBLIC_SITE_URL`, and
112
+ `BETTER_AUTH_SECRET` set to their production values.
@@ -1,18 +1,16 @@
1
- # Since the ".env" file is gitignored, you can use the ".env.example" file to
2
- # build a new ".env" file when you clone the repo. Keep this file up-to-date
3
- # when you add new variables to `.env`.
1
+ # Since the ".env.local" file is gitignored, use this file to build a new one
2
+ # when you clone the repo. Keep it up to date when you add new variables to
3
+ # `.env.local`.
4
4
 
5
- # This file will be committed to version control, so make sure not to have any
6
- # secrets in it. If you are cloning this repo, create a copy of this file named
7
- # ".env" and populate it with your secrets.
5
+ # This file is committed to version control — never put secrets in it.
8
6
 
9
- # When adding additional environment variables, the schema in "/src/env.js"
10
- # should be updated accordingly.
7
+ # When adding new environment variables, update the schema in "src/env.mjs".
11
8
 
12
9
  NEXT_PUBLIC_CONVEX_URL=""
13
10
  NEXT_PUBLIC_CONVEX_SITE_URL=""
14
11
 
15
- NEXT_PUBLIC_SITE_URL="http://localhost:3000"
12
+ NEXT_PUBLIC_SITE_URL="http://localhost:3010"
13
+ SITE_URL="http://localhost:3010"
16
14
  BETTER_AUTH_SECRET=""
17
15
 
18
16
  # {{ENV_OAUTH_VARS}}
@@ -1,2 +1,42 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
1
2
 
2
- .env.local
3
+ # dependencies
4
+ /node_modules
5
+ /.pnp
6
+ .pnp.*
7
+ .yarn/*
8
+ !.yarn/patches
9
+ !.yarn/plugins
10
+ !.yarn/releases
11
+ !.yarn/versions
12
+
13
+ # testing
14
+ /coverage
15
+
16
+ # next.js
17
+ /.next/
18
+ /out/
19
+
20
+ # production
21
+ /build
22
+
23
+ # misc
24
+ .DS_Store
25
+ *.pem
26
+
27
+ # debug
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+ .pnpm-debug.log*
32
+
33
+ # env files
34
+ .env
35
+ .env.*
36
+
37
+ # vercel
38
+ .vercel
39
+
40
+ # typescript
41
+ *.tsbuildinfo
42
+ next-env.d.ts
@@ -8,45 +8,17 @@
8
8
  * @module
9
9
  */
10
10
 
11
- import type * as auth_adapter_index from "../auth/adapter/index.js";
12
- import type * as auth_adapter_utils from "../auth/adapter/utils.js";
13
11
  import type * as auth_api from "../auth/api.js";
14
- import type * as auth_config from "../auth/config.js";
15
12
  import type * as auth_db from "../auth/db.js";
16
13
  import type * as auth_index from "../auth/index.js";
17
14
  import type * as auth_options from "../auth/options.js";
18
15
  import type * as auth_plugins_index from "../auth/plugins/index.js";
19
16
  import type * as auth_sessions from "../auth/sessions.js";
20
17
  import type * as http from "../http.js";
21
- import type * as vex_api_articles from "../vex/api/articles.js";
22
- import type * as vex_api_categories from "../vex/api/categories.js";
23
- import type * as vex_api_footers from "../vex/api/footers.js";
24
- import type * as vex_api_headers from "../vex/api/headers.js";
25
- import type * as vex_api_index from "../vex/api/index.js";
26
- import type * as vex_api_media from "../vex/api/media.js";
27
- import type * as vex_api_pages from "../vex/api/pages.js";
28
- import type * as vex_api_posts from "../vex/api/posts.js";
29
- import type * as vex_api_themes from "../vex/api/themes.js";
30
- import type * as vex_api_user from "../vex/api/user.js";
31
- import type * as vex_auth from "../vex/auth.js";
32
- import type * as vex_collections from "../vex/collections.js";
33
- import type * as vex_impersonation from "../vex/impersonation.js";
18
+ import type * as vex from "../vex.js";
19
+ import type * as vex_firstUser from "../vex/firstUser.js";
20
+ import type * as vex_globals from "../vex/globals.js";
34
21
  import type * as vex_media from "../vex/media.js";
35
- import type * as vex_migrate from "../vex/migrate.js";
36
- import type * as vex_model_api_articles from "../vex/model/api/articles.js";
37
- import type * as vex_model_api_categories from "../vex/model/api/categories.js";
38
- import type * as vex_model_api_footers from "../vex/model/api/footers.js";
39
- import type * as vex_model_api_headers from "../vex/model/api/headers.js";
40
- import type * as vex_model_api_media from "../vex/model/api/media.js";
41
- import type * as vex_model_api_pages from "../vex/model/api/pages.js";
42
- import type * as vex_model_api_posts from "../vex/model/api/posts.js";
43
- import type * as vex_model_api_themes from "../vex/model/api/themes.js";
44
- import type * as vex_model_api_user from "../vex/model/api/user.js";
45
- import type * as vex_model_collections from "../vex/model/collections.js";
46
- import type * as vex_model_media from "../vex/model/media.js";
47
- import type * as vex_model_versions from "../vex/model/versions.js";
48
- import type * as vex_previewSnapshot from "../vex/previewSnapshot.js";
49
- import type * as vex_versions from "../vex/versions.js";
50
22
 
51
23
  import type {
52
24
  ApiFromModules,
@@ -55,45 +27,17 @@ import type {
55
27
  } from "convex/server";
56
28
 
57
29
  declare const fullApi: ApiFromModules<{
58
- "auth/adapter/index": typeof auth_adapter_index;
59
- "auth/adapter/utils": typeof auth_adapter_utils;
60
30
  "auth/api": typeof auth_api;
61
- "auth/config": typeof auth_config;
62
31
  "auth/db": typeof auth_db;
63
32
  "auth/index": typeof auth_index;
64
33
  "auth/options": typeof auth_options;
65
34
  "auth/plugins/index": typeof auth_plugins_index;
66
35
  "auth/sessions": typeof auth_sessions;
67
36
  http: typeof http;
68
- "vex/api/articles": typeof vex_api_articles;
69
- "vex/api/categories": typeof vex_api_categories;
70
- "vex/api/footers": typeof vex_api_footers;
71
- "vex/api/headers": typeof vex_api_headers;
72
- "vex/api/index": typeof vex_api_index;
73
- "vex/api/media": typeof vex_api_media;
74
- "vex/api/pages": typeof vex_api_pages;
75
- "vex/api/posts": typeof vex_api_posts;
76
- "vex/api/themes": typeof vex_api_themes;
77
- "vex/api/user": typeof vex_api_user;
78
- "vex/auth": typeof vex_auth;
79
- "vex/collections": typeof vex_collections;
80
- "vex/impersonation": typeof vex_impersonation;
37
+ vex: typeof vex;
38
+ "vex/firstUser": typeof vex_firstUser;
39
+ "vex/globals": typeof vex_globals;
81
40
  "vex/media": typeof vex_media;
82
- "vex/migrate": typeof vex_migrate;
83
- "vex/model/api/articles": typeof vex_model_api_articles;
84
- "vex/model/api/categories": typeof vex_model_api_categories;
85
- "vex/model/api/footers": typeof vex_model_api_footers;
86
- "vex/model/api/headers": typeof vex_model_api_headers;
87
- "vex/model/api/media": typeof vex_model_api_media;
88
- "vex/model/api/pages": typeof vex_model_api_pages;
89
- "vex/model/api/posts": typeof vex_model_api_posts;
90
- "vex/model/api/themes": typeof vex_model_api_themes;
91
- "vex/model/api/user": typeof vex_model_api_user;
92
- "vex/model/collections": typeof vex_model_collections;
93
- "vex/model/media": typeof vex_model_media;
94
- "vex/model/versions": typeof vex_model_versions;
95
- "vex/previewSnapshot": typeof vex_previewSnapshot;
96
- "vex/versions": typeof vex_versions;
97
41
  }>;
98
42
 
99
43
  /**
@@ -21,6 +21,17 @@ import {
21
21
  } from "convex/server";
22
22
  import type { DataModel } from "./dataModel.js";
23
23
 
24
+ /**
25
+ * Typesafe environment variables.
26
+ *
27
+ * This includes platform-provided env vars and any variables declared in
28
+ * `convex.config.ts`.
29
+ */
30
+ type Env = {
31
+ readonly CONVEX_CLOUD_URL: string;
32
+ readonly CONVEX_SITE_URL: string;
33
+ };
34
+
24
35
  /**
25
36
  * Define a query in this Convex app's public API.
26
37
  *
@@ -95,6 +106,14 @@ export declare const internalAction: ActionBuilder<DataModel, "internal">;
95
106
  */
96
107
  export declare const httpAction: HttpActionBuilder;
97
108
 
109
+ /**
110
+ * Typesafe environment variables.
111
+ *
112
+ * This includes platform-provided env vars and any variables declared in
113
+ * `convex.config.ts`.
114
+ */
115
+ export declare const env: Env;
116
+
98
117
  /**
99
118
  * A set of services for use within Convex query functions.
100
119
  *
@@ -91,3 +91,11 @@ export const internalAction = internalActionGeneric;
91
91
  * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
92
92
  */
93
93
  export const httpAction = httpActionGeneric;
94
+
95
+ /**
96
+ * Typesafe environment variables.
97
+ *
98
+ * This includes platform-provided env vars and any variables declared in
99
+ * `convex.config.ts`.
100
+ */
101
+ export const env = process.env;
@@ -1,8 +1,54 @@
1
- import { query } from "../_generated/server"
1
+ import { get } from "@vexcms/core/server";
2
+ import { v } from "convex/values";
3
+
4
+ import {
5
+ type OrganizationID,
6
+ type SessionID,
7
+ TABLE_SLUG_ORGANIZATIONS,
8
+ TABLE_SLUG_SESSIONS,
9
+ TABLE_SLUG_USERS,
10
+ type UserID,
11
+ } from "~/db/constants";
12
+
13
+ import { query } from "../_generated/server";
2
14
 
3
15
  export const identifyCurrentUser = query({
4
16
  args: {},
5
17
  handler: async (ctx) => {
6
- return ctx.auth.getUserIdentity()
18
+ return ctx.auth.getUserIdentity();
19
+ },
20
+ });
21
+
22
+ export const getUserOrg = query({
23
+ args: {
24
+ noOrgs: v.optional(v.boolean()),
25
+ },
26
+ handler: async (ctx, args) => {
27
+ const empty = { user: null, organization: undefined };
28
+ const identity = await ctx.auth.getUserIdentity();
29
+ if (!identity) {
30
+ return empty;
31
+ }
32
+ const session = await get({
33
+ ctx,
34
+ id: identity.sessionId as SessionID,
35
+ collection: TABLE_SLUG_SESSIONS,
36
+ });
37
+ if (!session) {
38
+ return empty;
39
+ }
40
+ const user = await get({ ctx, id: identity.subject as UserID, collection: TABLE_SLUG_USERS });
41
+ if (!user) {
42
+ return empty;
43
+ }
44
+ if (!session.activeOrganizationId || args.noOrgs) {
45
+ return { user, organization: undefined };
46
+ }
47
+ const organization = await get({
48
+ ctx,
49
+ id: session.activeOrganizationId as OrganizationID,
50
+ collection: TABLE_SLUG_ORGANIZATIONS,
51
+ });
52
+ return { user, organization: organization ?? undefined };
7
53
  },
8
- })
54
+ });