create-vexcms 0.0.19 → 0.1.0-alpha.2

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 (154) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +93 -83
  3. package/dist/index.js +246 -81
  4. package/dist/index.mjs +30976 -0
  5. package/package.json +35 -15
  6. package/templates/base-nextjs/README.md +53 -205
  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/vex/firstUser.ts +10 -84
  21. package/templates/base-nextjs/convex/vex/globals.ts +19 -82
  22. package/templates/base-nextjs/convex/vex/media.ts +19 -246
  23. package/templates/base-nextjs/convex/vex.schema.ts +138 -0
  24. package/templates/base-nextjs/convex/vex.ts +19 -0
  25. package/templates/base-nextjs/convex.json +6 -0
  26. package/templates/base-nextjs/eslint.config.mjs +1 -21
  27. package/templates/base-nextjs/next.config.ts +10 -0
  28. package/templates/base-nextjs/package.json +47 -48
  29. package/templates/base-nextjs/src/app/(frontend)/@auth/(...)auth/[pathname]/view.tsx +17 -5
  30. package/templates/base-nextjs/src/app/(frontend)/auth/[pathname]/view.tsx +2 -4
  31. package/templates/base-nextjs/src/app/(frontend)/layout.tsx +12 -2
  32. package/templates/base-nextjs/src/app/(frontend)/page.tsx +2 -113
  33. package/templates/base-nextjs/src/app/(vexcms)/admin/[[...path]]/page.tsx +40 -0
  34. package/templates/base-nextjs/src/app/(vexcms)/admin/clientProviders.tsx +22 -0
  35. package/templates/base-nextjs/src/app/(vexcms)/admin/layout.tsx +19 -0
  36. package/templates/base-nextjs/src/app/globals.css +240 -104
  37. package/templates/base-nextjs/src/app/layout.tsx +23 -13
  38. package/templates/base-nextjs/src/app/unauthorized/page.tsx +24 -0
  39. package/templates/base-nextjs/src/auth/access.ts +46 -0
  40. package/templates/base-nextjs/src/auth/client.tsx +17 -5
  41. package/templates/base-nextjs/src/auth/hasPermission.ts +39 -0
  42. package/templates/base-nextjs/src/auth/serverUtils.ts +15 -22
  43. package/templates/base-nextjs/src/components/WelcomePage.tsx +116 -0
  44. package/templates/base-nextjs/src/components/component-example.tsx +56 -464
  45. package/templates/base-nextjs/src/components/providers/auth.tsx +13 -0
  46. package/templates/base-nextjs/src/components/providers/client.tsx +6 -1
  47. package/templates/base-nextjs/src/components/providers/convex.tsx +53 -21
  48. package/templates/base-nextjs/src/components/providers/server.tsx +10 -7
  49. package/templates/{marketing-site → base-nextjs}/src/components/ui/accordion.tsx +30 -32
  50. package/templates/base-nextjs/src/components/ui/badge.tsx +10 -13
  51. package/templates/base-nextjs/src/components/ui/input.tsx +35 -5
  52. package/templates/base-nextjs/src/context/AuthContext.tsx +29 -0
  53. package/templates/base-nextjs/src/db/constants/auth.ts +0 -1
  54. package/templates/base-nextjs/src/db/constants/index.ts +22 -35
  55. package/templates/base-nextjs/src/lib/utils.ts +0 -12
  56. package/templates/base-nextjs/src/proxy.ts +98 -11
  57. package/templates/base-nextjs/src/vex.config.ts +35 -0
  58. package/templates/base-nextjs/src/vex.types.ts +293 -0
  59. package/templates/base-nextjs/src/vexcms/collections/images.ts +15 -0
  60. package/templates/base-nextjs/src/vexcms/collections/index.ts +2 -1
  61. package/templates/base-nextjs/src/vexcms/collections/users.ts +7 -35
  62. package/templates/base-nextjs/tsconfig.json +3 -0
  63. package/templates/marketing-site/convex/_generated/api.d.ts +81 -0
  64. package/templates/marketing-site/convex/_generated/api.js +23 -0
  65. package/templates/marketing-site/convex/_generated/dataModel.d.ts +60 -0
  66. package/templates/marketing-site/convex/_generated/server.d.ts +162 -0
  67. package/templates/marketing-site/convex/_generated/server.js +101 -0
  68. package/templates/marketing-site/convex/footers.ts +11 -7
  69. package/templates/marketing-site/convex/headers.ts +15 -5
  70. package/templates/marketing-site/convex/pages.ts +20 -35
  71. package/templates/marketing-site/convex/schema.ts +119 -0
  72. package/templates/marketing-site/convex/seed.ts +582 -35
  73. package/templates/marketing-site/convex/siteSettings.ts +19 -5
  74. package/templates/marketing-site/convex/theme.ts +55 -61
  75. package/templates/marketing-site/convex/vex.schema.ts +355 -0
  76. package/templates/marketing-site/src/app/(frontend)/PageContent.tsx +27 -160
  77. package/templates/marketing-site/src/app/(frontend)/[slug]/page.tsx +6 -9
  78. package/templates/marketing-site/src/app/(frontend)/layout.tsx +4 -2
  79. package/templates/marketing-site/src/app/(frontend)/page.tsx +2 -5
  80. package/templates/marketing-site/src/components/SiteFooter.tsx +6 -3
  81. package/templates/marketing-site/src/components/SiteHeader.tsx +6 -3
  82. package/templates/marketing-site/src/components/ThemeLive.tsx +59 -0
  83. package/templates/marketing-site/src/components/ThemeStyle.tsx +45 -89
  84. package/templates/marketing-site/src/components/motion-primitives/animated-group.tsx +2 -2
  85. package/templates/marketing-site/src/lib/metadata.ts +51 -72
  86. package/templates/marketing-site/src/vex.config.ts +35 -0
  87. package/templates/marketing-site/src/vex.types.ts +634 -0
  88. package/templates/marketing-site/src/vexcms/api.ts +23 -0
  89. package/templates/marketing-site/src/vexcms/blocks/CTA/config.ts +3 -3
  90. package/templates/marketing-site/src/vexcms/blocks/CTA/index.tsx +2 -2
  91. package/templates/marketing-site/src/vexcms/blocks/FAQ/config.ts +4 -4
  92. package/templates/marketing-site/src/vexcms/blocks/FAQ/index.tsx +2 -2
  93. package/templates/marketing-site/src/vexcms/blocks/Features/config.ts +4 -8
  94. package/templates/marketing-site/src/vexcms/blocks/Features/index.tsx +2 -2
  95. package/templates/marketing-site/src/vexcms/blocks/Footer/config.ts +7 -11
  96. package/templates/marketing-site/src/vexcms/blocks/Footer/index.tsx +1 -1
  97. package/templates/marketing-site/src/vexcms/blocks/Header/config.ts +9 -9
  98. package/templates/marketing-site/src/vexcms/blocks/Header/index.tsx +4 -5
  99. package/templates/marketing-site/src/vexcms/blocks/Hero/config.ts +3 -4
  100. package/templates/marketing-site/src/vexcms/blocks/Hero/index.tsx +10 -19
  101. package/templates/marketing-site/src/vexcms/blocks/HowItWorks/config.ts +4 -9
  102. package/templates/marketing-site/src/vexcms/blocks/HowItWorks/index.tsx +3 -6
  103. package/templates/marketing-site/src/vexcms/blocks/Roadmap/config.ts +28 -68
  104. package/templates/marketing-site/src/vexcms/blocks/Roadmap/index.tsx +13 -43
  105. package/templates/marketing-site/src/vexcms/blocks/config.ts +7 -22
  106. package/templates/marketing-site/src/vexcms/blocks/constants.ts +2 -3
  107. package/templates/marketing-site/src/vexcms/blocks/index.ts +9 -8
  108. package/templates/marketing-site/src/vexcms/collections/footers.ts +1 -1
  109. package/templates/marketing-site/src/vexcms/collections/headers.ts +1 -1
  110. package/templates/marketing-site/src/vexcms/collections/index.ts +2 -1
  111. package/templates/marketing-site/src/vexcms/collections/pages.ts +12 -21
  112. package/templates/marketing-site/src/vexcms/collections/themeColors.ts +118 -0
  113. package/templates/marketing-site/src/vexcms/collections/themes.ts +29 -111
  114. package/templates/marketing-site/src/vexcms/globals/index.ts +1 -1
  115. package/templates/marketing-site/src/vexcms/globals/siteSettings.ts +43 -27
  116. package/templates/base-nextjs/convex/auth/adapter/index.ts +0 -230
  117. package/templates/base-nextjs/convex/auth/adapter/utils.ts +0 -547
  118. package/templates/base-nextjs/convex/auth/config.ts +0 -10
  119. package/templates/base-nextjs/convex/vex/auth.ts +0 -38
  120. package/templates/base-nextjs/convex/vex/collections.ts +0 -321
  121. package/templates/base-nextjs/convex/vex/helpers.ts +0 -33
  122. package/templates/base-nextjs/convex/vex/impersonation.ts +0 -51
  123. package/templates/base-nextjs/convex/vex/migrate.ts +0 -74
  124. package/templates/base-nextjs/convex/vex/model/collections.ts +0 -196
  125. package/templates/base-nextjs/convex/vex/model/media.ts +0 -87
  126. package/templates/base-nextjs/convex/vex/model/versions.ts +0 -254
  127. package/templates/base-nextjs/convex/vex/previewSnapshot.ts +0 -53
  128. package/templates/base-nextjs/convex/vex/versions.ts +0 -648
  129. package/templates/base-nextjs/src/app/admin/AdminLayoutWrapper.tsx +0 -33
  130. package/templates/base-nextjs/src/app/admin/AdminPageWrapper.tsx +0 -38
  131. package/templates/base-nextjs/src/app/admin/RichTextFieldWithMedia.tsx +0 -101
  132. package/templates/base-nextjs/src/app/admin/[[...path]]/page.tsx +0 -15
  133. package/templates/base-nextjs/src/app/admin/layout.tsx +0 -51
  134. package/templates/base-nextjs/src/app/favicon.ico +0 -0
  135. package/templates/base-nextjs/src/components/providers/theme.tsx +0 -11
  136. package/templates/base-nextjs/src/components/ui/theme-toggle.tsx +0 -67
  137. package/templates/base-nextjs/src/db/types.ts +0 -6
  138. package/templates/base-nextjs/src/vexcms/access.ts +0 -44
  139. package/templates/base-nextjs/src/vexcms/auth.ts +0 -4
  140. package/templates/base-nextjs/src/vexcms/collections/media.ts +0 -15
  141. package/templates/base-nextjs/vex.config.ts +0 -25
  142. package/templates/marketing-site/public/favicons/favicon.ico +0 -0
  143. package/templates/marketing-site/src/app/(frontend)/preview/[slug]/PreviewPageContent.tsx +0 -55
  144. package/templates/marketing-site/src/app/(frontend)/preview/[slug]/page.tsx +0 -27
  145. package/templates/marketing-site/src/app/(frontend)/preview/layout.tsx +0 -18
  146. package/templates/marketing-site/src/app/admin/AdminLayoutWrapper.tsx +0 -71
  147. package/templates/marketing-site/src/components/ThemeInjector.tsx +0 -128
  148. package/templates/marketing-site/src/components/admin/IconPickerField.tsx +0 -134
  149. package/templates/marketing-site/src/components/admin/ThemeImport.tsx +0 -174
  150. package/templates/marketing-site/src/components/admin/ThemeImportField.tsx +0 -33
  151. package/templates/marketing-site/src/db/constants/index.ts +0 -52
  152. package/templates/marketing-site/src/lib/colorConvert.ts +0 -171
  153. package/templates/marketing-site/src/vexcms/access.ts +0 -36
  154. package/templates/marketing-site/vex.config.ts +0 -32
@@ -0,0 +1,634 @@
1
+ // ⚠️ AUTO-GENERATED BY VEX CMS — DO NOT EDIT ⚠️
2
+ // Run 'vex dev' or 'vex generate' to update this file.
3
+
4
+ /* eslint-disable perfectionist/sort-union-types */
5
+ /* eslint-disable perfectionist/sort-interfaces */
6
+ /* eslint-disable perfectionist/sort-modules */
7
+
8
+ import type { Id } from "@convex/_generated/dataModel"
9
+ import type { VexDocument, VexDocumentGlobal } from "@vexcms/core"
10
+
11
+ export interface UserDocument extends VexDocument {
12
+ _id: Id<"user">
13
+ name: string
14
+ email: string
15
+ emailVerified: boolean
16
+ image?: string
17
+ createdAt: number
18
+ updatedAt: number
19
+ role?: string
20
+ banned?: boolean
21
+ banReason?: string
22
+ banExpires?: number
23
+ isAnonymous?: boolean
24
+ userId?: string
25
+ roles: string[]
26
+ }
27
+ export type HeroBlock = {
28
+ blockType: "hero"
29
+ blockName?: string
30
+ id: string
31
+ badgeText?: string
32
+ badgeLink?: string
33
+ heading: string
34
+ subheading?: string
35
+ primaryCtaLabel: string
36
+ primaryCtaHref: string
37
+ secondaryCtaLabel?: string
38
+ secondaryCtaHref?: string
39
+ }
40
+
41
+ export type FeaturesBlock = {
42
+ blockType: "features"
43
+ blockName?: string
44
+ id: string
45
+ heading: string
46
+ subheading?: string
47
+ features: {
48
+ title: string
49
+ description: string
50
+ /**
51
+ * Lucide icon name
52
+ */
53
+ icon?: string
54
+ }[]
55
+ }
56
+
57
+ export type HowItWorksBlock = {
58
+ blockType: "how_it_works"
59
+ blockName?: string
60
+ id: string
61
+ heading: string
62
+ subheading?: string
63
+ steps: {
64
+ /**
65
+ * Lucide icon name
66
+ */
67
+ icon?: string
68
+ title: string
69
+ description: string
70
+ }[]
71
+ }
72
+
73
+ export type RoadmapBlock = {
74
+ blockType: "roadmap"
75
+ blockName?: string
76
+ id: string
77
+ heading: string
78
+ subheading?: string
79
+ items: {
80
+ feature: string
81
+ description?: string
82
+ status: string[]
83
+ }[]
84
+ }
85
+
86
+ export type CtaBlock = {
87
+ blockType: "cta"
88
+ blockName?: string
89
+ id: string
90
+ heading: string
91
+ subheading?: string
92
+ actions?: {
93
+ label: string
94
+ href: string
95
+ }[]
96
+ }
97
+
98
+ export type FaqBlock = {
99
+ blockType: "faq"
100
+ blockName?: string
101
+ id: string
102
+ heading: string
103
+ subheading?: string
104
+ supportLink?: string
105
+ items: {
106
+ question: string
107
+ answer: string
108
+ }[]
109
+ }
110
+
111
+ export type PageBlock =
112
+ HeroBlock | FeaturesBlock | HowItWorksBlock | RoadmapBlock | CtaBlock | FaqBlock
113
+
114
+ export interface PagesDocument extends VexDocument {
115
+ _id: Id<"pages">
116
+ title: string
117
+ /**
118
+ * URL-friendly page path
119
+ */
120
+ slug: string
121
+ blocks?: PageBlock[]
122
+ /**
123
+ * Custom <title> tag. Falls back to page title if empty.
124
+ */
125
+ metaTitle?: string
126
+ /**
127
+ * Custom meta description for search results.
128
+ */
129
+ metaDescription?: string
130
+ ogImage?: Id<"images">[]
131
+ }
132
+ export type HeaderBlock = {
133
+ blockType: "header"
134
+ blockName?: string
135
+ id: string
136
+ logoText?: string
137
+ logoImage?: Id<"images">[]
138
+ logoHref?: string
139
+ menuItems?: {
140
+ label: string
141
+ href: string
142
+ }[]
143
+ actionButtons?: {
144
+ label: string
145
+ href: string
146
+ variant?: string[]
147
+ }[]
148
+ }
149
+
150
+ export interface HeadersDocument extends VexDocument {
151
+ _id: Id<"headers">
152
+ name: string
153
+ content?: HeaderBlock[]
154
+ }
155
+ export type FooterBlock = {
156
+ blockType: "footer"
157
+ blockName?: string
158
+ id: string
159
+ logoText?: string
160
+ logoImage?: Id<"images">[]
161
+ copyright?: string
162
+ links?: {
163
+ label: string
164
+ href: string
165
+ }[]
166
+ socialLinks?: {
167
+ platform: string
168
+ href: string
169
+ /**
170
+ * Lucide icon name
171
+ */
172
+ icon?: string
173
+ }[]
174
+ }
175
+
176
+ export interface FootersDocument extends VexDocument {
177
+ _id: Id<"footers">
178
+ name: string
179
+ content?: FooterBlock[]
180
+ }
181
+
182
+ export interface Theme extends VexDocument {
183
+ _id: Id<"themes">
184
+ /**
185
+ * Internal identifier for this theme. Used for idempotent lookups and admin
186
+ * display.
187
+ */
188
+ name: string
189
+ /**
190
+ * CSS font-family stack applied to --font-sans. The first available font wins, so
191
+ * a stack naming an unloaded font degrades rather than breaking.
192
+ */
193
+ fontFamily?: string
194
+ /**
195
+ * Applied to the --radius custom property. Any CSS length.
196
+ */
197
+ radius?: string
198
+ /**
199
+ * Tokens emitted under :root.
200
+ */
201
+ light?: {
202
+ background?: string
203
+ foreground?: string
204
+ card?: string
205
+ cardForeground?: string
206
+ popover?: string
207
+ popoverForeground?: string
208
+ primary?: string
209
+ primaryForeground?: string
210
+ secondary?: string
211
+ secondaryForeground?: string
212
+ muted?: string
213
+ mutedForeground?: string
214
+ accent?: string
215
+ accentForeground?: string
216
+ destructive?: string
217
+ destructiveForeground?: string
218
+ border?: string
219
+ input?: string
220
+ ring?: string
221
+ chart1?: string
222
+ chart2?: string
223
+ chart3?: string
224
+ chart4?: string
225
+ chart5?: string
226
+ sidebar?: string
227
+ sidebarForeground?: string
228
+ sidebarPrimary?: string
229
+ sidebarPrimaryForeground?: string
230
+ sidebarAccent?: string
231
+ sidebarAccentForeground?: string
232
+ sidebarBorder?: string
233
+ sidebarRing?: string
234
+ }
235
+ /**
236
+ * Tokens emitted under .dark.
237
+ */
238
+ dark?: {
239
+ background?: string
240
+ foreground?: string
241
+ card?: string
242
+ cardForeground?: string
243
+ popover?: string
244
+ popoverForeground?: string
245
+ primary?: string
246
+ primaryForeground?: string
247
+ secondary?: string
248
+ secondaryForeground?: string
249
+ muted?: string
250
+ mutedForeground?: string
251
+ accent?: string
252
+ accentForeground?: string
253
+ destructive?: string
254
+ destructiveForeground?: string
255
+ border?: string
256
+ input?: string
257
+ ring?: string
258
+ chart1?: string
259
+ chart2?: string
260
+ chart3?: string
261
+ chart4?: string
262
+ chart5?: string
263
+ sidebar?: string
264
+ sidebarForeground?: string
265
+ sidebarPrimary?: string
266
+ sidebarPrimaryForeground?: string
267
+ sidebarAccent?: string
268
+ sidebarAccentForeground?: string
269
+ sidebarBorder?: string
270
+ sidebarRing?: string
271
+ }
272
+ }
273
+
274
+ export interface SessionDocument extends VexDocument {
275
+ _id: Id<"session">
276
+ expiresAt: number
277
+ token: string
278
+ createdAt: number
279
+ updatedAt: number
280
+ ipAddress?: string
281
+ userAgent?: string
282
+ userId: string
283
+ impersonatedBy?: string
284
+ activeOrganizationId?: string
285
+ }
286
+
287
+ export interface AccountDocument extends VexDocument {
288
+ _id: Id<"account">
289
+ accountId: string
290
+ providerId: string
291
+ userId: string
292
+ accessToken?: string
293
+ refreshToken?: string
294
+ idToken?: string
295
+ accessTokenExpiresAt?: number
296
+ refreshTokenExpiresAt?: number
297
+ scope?: string
298
+ password?: string
299
+ createdAt: number
300
+ updatedAt: number
301
+ }
302
+
303
+ export interface VerificationDocument extends VexDocument {
304
+ _id: Id<"verification">
305
+ identifier: string
306
+ value: string
307
+ expiresAt: number
308
+ createdAt: number
309
+ updatedAt: number
310
+ }
311
+
312
+ export interface ApikeyDocument extends VexDocument {
313
+ _id: Id<"apikey">
314
+ configId: string
315
+ name?: string
316
+ start?: string
317
+ referenceId: string
318
+ prefix?: string
319
+ key: string
320
+ refillInterval?: number
321
+ refillAmount?: number
322
+ lastRefillAt?: number
323
+ enabled?: boolean
324
+ rateLimitEnabled?: boolean
325
+ rateLimitTimeWindow?: number
326
+ rateLimitMax?: number
327
+ requestCount?: number
328
+ remaining?: number
329
+ lastRequest?: number
330
+ expiresAt?: number
331
+ createdAt: number
332
+ updatedAt: number
333
+ permissions?: string
334
+ metadata?: string
335
+ }
336
+
337
+ export interface JwksDocument extends VexDocument {
338
+ _id: Id<"jwks">
339
+ publicKey: string
340
+ privateKey: string
341
+ createdAt: number
342
+ expiresAt?: number
343
+ }
344
+
345
+ export interface OrganizationDocument extends VexDocument {
346
+ _id: Id<"organization">
347
+ name: string
348
+ slug: string
349
+ logo?: string
350
+ createdAt: number
351
+ metadata?: string
352
+ }
353
+
354
+ export interface MemberDocument extends VexDocument {
355
+ _id: Id<"member">
356
+ organizationId: string
357
+ userId: string
358
+ role: string
359
+ createdAt: number
360
+ }
361
+
362
+ export interface InvitationDocument extends VexDocument {
363
+ _id: Id<"invitation">
364
+ organizationId: string
365
+ email: string
366
+ role?: string
367
+ status: string
368
+ expiresAt: number
369
+ createdAt: number
370
+ inviterId: string
371
+ }
372
+
373
+ export interface Image extends VexDocument {
374
+ _id: Id<"images">
375
+ filename: string
376
+ alt: string
377
+ mimeType: string
378
+ size: number
379
+ storageId: string
380
+ deleted?: boolean
381
+ src: string
382
+ width?: number
383
+ height?: number
384
+ }
385
+
386
+ export interface SiteSettingsGlobal extends VexDocumentGlobal<"siteSettings"> {
387
+ /**
388
+ * Used as fallback for logo text, page titles, and meta tags.
389
+ */
390
+ name: string
391
+ description?: string
392
+ /**
393
+ * The theme applied to the public site.
394
+ */
395
+ activeTheme?: Id<"themes">[]
396
+ /**
397
+ * Optional. Leave empty and the admin panel uses the Active Theme.
398
+ */
399
+ adminTheme?: Id<"themes">[]
400
+ /**
401
+ * Site favicon image
402
+ */
403
+ favicon?: Id<"images">[]
404
+ /**
405
+ * Default <title> tag for the site
406
+ */
407
+ metaTitle?: string
408
+ /**
409
+ * Default meta description for SEO
410
+ */
411
+ metaDescription?: string
412
+ /**
413
+ * Default Open Graph image for social sharing
414
+ */
415
+ ogImage?: Id<"images">[]
416
+ /**
417
+ * @handle for Twitter cards
418
+ */
419
+ twitterHandle?: string
420
+ /**
421
+ * GA4 measurement ID (G-XXXXXXXXXX)
422
+ */
423
+ googleAnalyticsId?: string
424
+ }
425
+
426
+ export type CollectionSlug =
427
+ | "user"
428
+ | "pages"
429
+ | "headers"
430
+ | "footers"
431
+ | "themes"
432
+ | "session"
433
+ | "account"
434
+ | "verification"
435
+ | "apikey"
436
+ | "jwks"
437
+ | "organization"
438
+ | "member"
439
+ | "invitation"
440
+ | "images"
441
+
442
+ export type GlobalSlug = "siteSettings"
443
+
444
+ export type MediaCollectionSlug = "images"
445
+
446
+ export type StorageAdapterSlug = "convex"
447
+
448
+ export type DocumentBySlug = {
449
+ user: UserDocument
450
+ pages: PagesDocument
451
+ headers: HeadersDocument
452
+ footers: FootersDocument
453
+ themes: Theme
454
+ session: SessionDocument
455
+ account: AccountDocument
456
+ verification: VerificationDocument
457
+ apikey: ApikeyDocument
458
+ jwks: JwksDocument
459
+ organization: OrganizationDocument
460
+ member: MemberDocument
461
+ invitation: InvitationDocument
462
+ images: Image
463
+ }
464
+
465
+ export type GlobalDocumentBySlug = {
466
+ siteSettings: SiteSettingsGlobal
467
+ }
468
+
469
+ declare module "@vexcms/core" {
470
+ interface GeneratedVexTypes {
471
+ CollectionSlug:
472
+ | "user"
473
+ | "pages"
474
+ | "headers"
475
+ | "footers"
476
+ | "themes"
477
+ | "session"
478
+ | "account"
479
+ | "verification"
480
+ | "apikey"
481
+ | "jwks"
482
+ | "organization"
483
+ | "member"
484
+ | "invitation"
485
+ | "images"
486
+ GlobalSlug: "siteSettings"
487
+ MediaCollectionSlug: "images"
488
+ StorageAdapterSlug: "convex"
489
+ DocumentBySlug: {
490
+ user: UserDocument
491
+ pages: PagesDocument
492
+ headers: HeadersDocument
493
+ footers: FootersDocument
494
+ themes: Theme
495
+ session: SessionDocument
496
+ account: AccountDocument
497
+ verification: VerificationDocument
498
+ apikey: ApikeyDocument
499
+ jwks: JwksDocument
500
+ organization: OrganizationDocument
501
+ member: MemberDocument
502
+ invitation: InvitationDocument
503
+ images: Image
504
+ }
505
+ GlobalDocumentBySlug: {
506
+ siteSettings: SiteSettingsGlobal
507
+ }
508
+ CollectionsFieldTypeMap: {
509
+ user: {
510
+ text: "name" | "email" | "image" | "role" | "banReason" | "userId"
511
+ checkbox: "emailVerified" | "banned" | "isAnonymous"
512
+ date: "createdAt" | "updatedAt" | "banExpires"
513
+ array: "roles"
514
+ }
515
+ pages: {
516
+ text: "title" | "slug" | "metaTitle" | "metaDescription"
517
+ blocks: "blocks"
518
+ upload: "ogImage"
519
+ }
520
+ headers: {
521
+ text: "name"
522
+ blocks: "content"
523
+ }
524
+ footers: {
525
+ text: "name"
526
+ blocks: "content"
527
+ }
528
+ themes: {
529
+ text: "name" | "fontFamily" | "radius"
530
+ group: "light" | "dark"
531
+ }
532
+ session: {
533
+ date: "expiresAt" | "createdAt" | "updatedAt"
534
+ text:
535
+ "token" | "ipAddress" | "userAgent" | "userId" | "impersonatedBy" | "activeOrganizationId"
536
+ }
537
+ account: {
538
+ text:
539
+ | "accountId"
540
+ | "providerId"
541
+ | "userId"
542
+ | "accessToken"
543
+ | "refreshToken"
544
+ | "idToken"
545
+ | "scope"
546
+ | "password"
547
+ date: "accessTokenExpiresAt" | "refreshTokenExpiresAt" | "createdAt" | "updatedAt"
548
+ }
549
+ verification: {
550
+ text: "identifier" | "value"
551
+ date: "expiresAt" | "createdAt" | "updatedAt"
552
+ }
553
+ apikey: {
554
+ text:
555
+ | "configId"
556
+ | "name"
557
+ | "start"
558
+ | "referenceId"
559
+ | "prefix"
560
+ | "key"
561
+ | "permissions"
562
+ | "metadata"
563
+ number:
564
+ | "refillInterval"
565
+ | "refillAmount"
566
+ | "rateLimitTimeWindow"
567
+ | "rateLimitMax"
568
+ | "requestCount"
569
+ | "remaining"
570
+ date: "lastRefillAt" | "lastRequest" | "expiresAt" | "createdAt" | "updatedAt"
571
+ checkbox: "enabled" | "rateLimitEnabled"
572
+ }
573
+ jwks: {
574
+ text: "publicKey" | "privateKey"
575
+ date: "createdAt" | "expiresAt"
576
+ }
577
+ organization: {
578
+ text: "name" | "slug" | "logo" | "metadata"
579
+ date: "createdAt"
580
+ }
581
+ member: {
582
+ text: "organizationId" | "userId" | "role"
583
+ date: "createdAt"
584
+ }
585
+ invitation: {
586
+ text: "organizationId" | "email" | "role" | "status" | "inviterId"
587
+ date: "expiresAt" | "createdAt"
588
+ }
589
+ images: {
590
+ text: "filename" | "alt" | "mimeType" | "storageId" | "src"
591
+ number: "size" | "width" | "height"
592
+ checkbox: "deleted"
593
+ }
594
+ }
595
+ GlobalsFieldTypeMap: {
596
+ siteSettings: {
597
+ text:
598
+ | "name"
599
+ | "description"
600
+ | "metaTitle"
601
+ | "metaDescription"
602
+ | "twitterHandle"
603
+ | "googleAnalyticsId"
604
+ relationship: "activeTheme" | "adminTheme"
605
+ upload: "favicon" | "ogImage"
606
+ }
607
+ }
608
+ IndexFieldsBySlug: {
609
+ user: { by_email: readonly ["email"] }
610
+ pages: { by_slug: readonly ["slug"] }
611
+ headers: { by_name: readonly ["name"] }
612
+ footers: { by_name: readonly ["name"] }
613
+ themes: { by_name: readonly ["name"] }
614
+ session: { by_token: readonly ["token"]; by_userId: readonly ["userId"] }
615
+ account: { by_userId: readonly ["userId"] }
616
+ verification: { by_identifier: readonly ["identifier"] }
617
+ apikey: {
618
+ by_configId: readonly ["configId"]
619
+ by_referenceId: readonly ["referenceId"]
620
+ by_key: readonly ["key"]
621
+ }
622
+ jwks: {}
623
+ organization: { by_slug: readonly ["slug"] }
624
+ member: { by_organizationId: readonly ["organizationId"]; by_userId: readonly ["userId"] }
625
+ invitation: { by_organizationId: readonly ["organizationId"]; by_email: readonly ["email"] }
626
+ images: { by_deleted: readonly ["deleted"] }
627
+ }
628
+ CustomActionsBySlug: {}
629
+ AuthSlugs: {
630
+ user: "user"
631
+ organization: "organization"
632
+ }
633
+ }
634
+ }
@@ -0,0 +1,23 @@
1
+ import { type DataModel } from "@convex/_generated/dataModel"
2
+ import { createGetAuth } from "@vexcms/better-auth"
3
+ import { vexServerApi } from "@vexcms/core/server"
4
+
5
+ import { TABLE_SLUG_ORGANIZATIONS, TABLE_SLUG_SESSIONS, TABLE_SLUG_USERS } from "~/db/constants"
6
+ import config from "~/vex.config"
7
+
8
+ /**
9
+ * Bound server API — `config`/`getAuth` are threaded once here so
10
+ * `convex/pages.ts`, `convex/headers.ts`, and `convex/footers.ts` can import
11
+ * `find` directly instead of repeating the wiring in every file.
12
+ *
13
+ * Mirrors `apps/test/src/vexcms/api.ts`'s `vexServerApi` binding.
14
+ */
15
+ export const { get, find, search, create, remove, update, globals } = vexServerApi<DataModel>({
16
+ config,
17
+ getAuth: createGetAuth({
18
+ orgCollectionSlug: TABLE_SLUG_ORGANIZATIONS,
19
+ userCollectionSlug: TABLE_SLUG_USERS,
20
+ sessionCollectionSlug: TABLE_SLUG_SESSIONS,
21
+ resolveOrgs: true,
22
+ }),
23
+ })
@@ -1,4 +1,4 @@
1
- import { array, defineBlock, object, text } from "@vexcms/core"
1
+ import { array, defineBlock, group, text } from "@vexcms/core"
2
2
 
3
3
  import { BLOCK_SLUG_CTA } from "../constants"
4
4
 
@@ -18,7 +18,7 @@ export const ctaBlock = defineBlock({
18
18
  }),
19
19
  actions: array({
20
20
  label: "Actions",
21
- items: object({
21
+ items: group({
22
22
  fields: {
23
23
  label: text({ label: "Button Label", required: true }),
24
24
  href: text({ label: "Button Link", required: true }),
@@ -31,6 +31,6 @@ export const ctaBlock = defineBlock({
31
31
  }),
32
32
  },
33
33
  admin: {
34
- icon: "megaphone",
34
+ icon: "Megaphone",
35
35
  },
36
36
  })
@@ -1,9 +1,9 @@
1
- import type { BlockComponentProps } from "@vexcms/ui"
1
+ import type { BlockComponentProps } from "@vexcms/react"
2
2
 
3
3
  import Link from "next/link"
4
4
 
5
5
  import { cn } from "~/lib/utils"
6
- import { buttonVariants } from "~/components/ui/button"
6
+ import { buttonVariants } from "@vexcms/react"
7
7
 
8
8
  export { ctaBlock } from "./config"
9
9
 
@@ -1,4 +1,4 @@
1
- import { array, defineBlock, object, text } from "@vexcms/core"
1
+ import { array, defineBlock, group, text } from "@vexcms/core"
2
2
 
3
3
  import { BLOCK_SLUG_FAQ } from "../constants"
4
4
 
@@ -19,12 +19,12 @@ export const faqBlock = defineBlock({
19
19
  supportLink: text({
20
20
  label: "Support Link",
21
21
  defaultValue: "https://github.com/vexcms/vex/issues",
22
- admin: { description: "URL to contact support page" },
22
+ description: "URL to contact support page",
23
23
  }),
24
24
  items: array({
25
25
  label: "FAQ Items",
26
26
  required: true,
27
- items: object({
27
+ items: group({
28
28
  fields: {
29
29
  question: text({ label: "Question", required: true }),
30
30
  answer: text({ label: "Answer", required: true }),
@@ -65,6 +65,6 @@ export const faqBlock = defineBlock({
65
65
  }),
66
66
  },
67
67
  admin: {
68
- icon: "help-circle",
68
+ icon: "CircleQuestionMark",
69
69
  },
70
70
  })