@edgedev/create-edge-app 1.2.30 → 1.2.32

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.
package/.env CHANGED
@@ -11,4 +11,4 @@ VITE_FIREBASE_EMULATOR_FIRESTORE=
11
11
  VITE_FIREBASE_EMULATOR_FUNCTIONS=
12
12
  VITE_FIREBASE_EMULATOR_STORAGE=
13
13
  REGISTRATION_CODE=organization-registration-template
14
- DEVELOPMENT_MODE=false
14
+ DEVELOPMENT_MODE=false
package/.env.dev CHANGED
@@ -11,4 +11,4 @@ VITE_FIREBASE_EMULATOR_FIRESTORE=8080
11
11
  VITE_FIREBASE_EMULATOR_FUNCTIONS=5001
12
12
  VITE_FIREBASE_EMULATOR_STORAGE=9199
13
13
  REGISTRATION_CODE=organization-registration-template
14
- DEVELOPMENT_MODE=true
14
+ DEVELOPMENT_MODE=true
@@ -103,6 +103,7 @@ const schemas = {
103
103
  message: 'At least one domain is required',
104
104
  path: ['domains', 0],
105
105
  }),
106
+ forwardApex: z.boolean().optional(),
106
107
  contactEmail: z.string().optional(),
107
108
  contactPhone: z.string().optional(),
108
109
  theme: z.string({
@@ -783,6 +784,7 @@ const isSiteDiff = computed(() => {
783
784
  brandLogoLight: publishedSite.brandLogoLight,
784
785
  favicon: publishedSite.favicon,
785
786
  menuPosition: publishedSite.menuPosition,
787
+ forwardApex: publishedSite.forwardApex,
786
788
  contactEmail: publishedSite.contactEmail,
787
789
  contactPhone: publishedSite.contactPhone,
788
790
  metaTitle: publishedSite.metaTitle,
@@ -810,6 +812,7 @@ const isSiteDiff = computed(() => {
810
812
  brandLogoLight: siteData.value.brandLogoLight,
811
813
  favicon: siteData.value.favicon,
812
814
  menuPosition: siteData.value.menuPosition,
815
+ forwardApex: siteData.value.forwardApex,
813
816
  contactEmail: siteData.value.contactEmail,
814
817
  contactPhone: siteData.value.contactPhone,
815
818
  metaTitle: siteData.value.metaTitle,
@@ -851,6 +854,7 @@ const discardSiteSettings = async () => {
851
854
  brandLogoLight: publishedSite.brandLogoLight || '',
852
855
  favicon: publishedSite.favicon || '',
853
856
  menuPosition: publishedSite.menuPosition || '',
857
+ forwardApex: publishedSite.forwardApex === false ? false : true,
854
858
  contactEmail: publishedSite.contactEmail || '',
855
859
  contactPhone: publishedSite.contactPhone || '',
856
860
  metaTitle: publishedSite.metaTitle || '',
@@ -1699,6 +1703,7 @@ const pageSettingsUpdated = async (pageData) => {
1699
1703
  :enable-media-picker="true"
1700
1704
  :site-id="props.site"
1701
1705
  :domain-error="domainError"
1706
+ :settings-open="state.siteSettings"
1702
1707
  />
1703
1708
  </div>
1704
1709
  <SheetFooter class="pt-2 flex justify-between">
@@ -42,6 +42,10 @@ const props = defineProps({
42
42
  type: String,
43
43
  default: '',
44
44
  },
45
+ settingsOpen: {
46
+ type: Boolean,
47
+ default: true,
48
+ },
45
49
  })
46
50
 
47
51
  const edgeFirebase = inject('edgeFirebase')
@@ -101,41 +105,266 @@ const menuPositionOptions = [
101
105
 
102
106
  const domainError = computed(() => String(props.domainError || '').trim())
103
107
  const serverPagesProject = ref('')
108
+ const domainRegistry = ref({})
109
+ const loadingDomainRegistry = ref(false)
110
+ const hasLoadedDomainRegistry = ref(false)
104
111
  const pagesProject = computed(() => String(serverPagesProject.value || '').trim())
105
112
  const pagesDomain = computed(() => (pagesProject.value ? `${pagesProject.value}.pages.dev` : '(CLOUDFLARE_PAGES_PROJECT).pages.dev'))
113
+ const forwardApexEnabled = computed({
114
+ get: () => props.settings?.forwardApex !== false,
115
+ set: (value) => {
116
+ props.settings.forwardApex = !!value
117
+ },
118
+ })
119
+
120
+ const normalizeDomain = (value) => {
121
+ if (!value)
122
+ return ''
123
+ let normalized = String(value).trim().toLowerCase()
124
+ if (!normalized)
125
+ return ''
126
+ if (normalized.includes('://')) {
127
+ try {
128
+ normalized = new URL(normalized).host
129
+ }
130
+ catch {
131
+ normalized = normalized.split('://').pop() || normalized
132
+ }
133
+ }
134
+ normalized = normalized.split('/')[0] || ''
135
+ if (normalized.includes(':') && !normalized.startsWith('[')) {
136
+ normalized = normalized.split(':')[0] || ''
137
+ }
138
+ return normalized.replace(/\.+$/g, '')
139
+ }
140
+
141
+ const isIpv4Address = (value) => {
142
+ const parts = String(value || '').split('.')
143
+ if (parts.length !== 4)
144
+ return false
145
+ return parts.every((part) => {
146
+ if (!/^\d{1,3}$/.test(part))
147
+ return false
148
+ const num = Number(part)
149
+ return num >= 0 && num <= 255
150
+ })
151
+ }
152
+
153
+ const isIpv6Address = (value) => {
154
+ const normalized = String(value || '').toLowerCase()
155
+ if (!normalized.includes(':'))
156
+ return false
157
+ return /^[0-9a-f:]+$/.test(normalized)
158
+ }
159
+
160
+ const isIpAddress = value => isIpv4Address(value) || isIpv6Address(value)
161
+
162
+ const shouldDisplayDomainDnsRecords = (domain) => {
163
+ if (!domain)
164
+ return false
165
+ if (domain.includes('localhost'))
166
+ return false
167
+ if (isIpAddress(domain))
168
+ return false
169
+ if (domain.endsWith('.dev'))
170
+ return false
171
+ return true
172
+ }
173
+
174
+ const getCloudflareApexDomain = (domain) => {
175
+ if (!domain)
176
+ return ''
177
+ if (domain.startsWith('www.'))
178
+ return domain.slice(4)
179
+ return domain
180
+ }
181
+
182
+ const getCloudflarePagesDomain = (domain) => {
183
+ if (!domain)
184
+ return ''
185
+ if (domain.startsWith('www.'))
186
+ return domain
187
+ return `www.${domain}`
188
+ }
189
+
190
+ const normalizedDomains = computed(() => {
191
+ const values = Array.isArray(props.settings?.domains) ? props.settings.domains : []
192
+ return Array.from(new Set(values.map(normalizeDomain).filter(Boolean)))
193
+ })
194
+
195
+ const dnsEligibleDomains = computed(() => normalizedDomains.value.filter(shouldDisplayDomainDnsRecords))
196
+
197
+ const organizationId = computed(() => String(edgeGlobal?.edgeState?.currentOrganization || '').trim())
198
+ const shouldShowDomainRegistryLoading = computed(() => {
199
+ if (!normalizedDomains.value.length)
200
+ return false
201
+ return loadingDomainRegistry.value || !hasLoadedDomainRegistry.value
202
+ })
203
+ const DOMAIN_REGISTRY_POLL_MS = 2500
204
+ let domainRegistryPollTimer = null
205
+
206
+ const buildFallbackDomainEntry = (domain) => {
207
+ const apexDomain = getCloudflareApexDomain(domain)
208
+ const wwwDomain = getCloudflarePagesDomain(apexDomain)
209
+ const target = pagesDomain.value
210
+ const hasTarget = !!String(target || '').trim()
211
+ return {
212
+ domain,
213
+ apexDomain,
214
+ wwwDomain,
215
+ apexAttempted: false,
216
+ apexAdded: false,
217
+ apexError: '',
218
+ dnsGuidance: 'Add the www CNAME record. Apex is unavailable; forward apex to www.',
219
+ dnsRecords: {
220
+ target,
221
+ www: {
222
+ type: 'CNAME',
223
+ name: 'www',
224
+ host: wwwDomain,
225
+ value: target,
226
+ enabled: hasTarget,
227
+ },
228
+ apex: {
229
+ type: 'CNAME',
230
+ name: '@',
231
+ host: apexDomain,
232
+ value: target,
233
+ enabled: false,
234
+ },
235
+ },
236
+ }
237
+ }
238
+
239
+ const domainDnsEntries = computed(() => {
240
+ return dnsEligibleDomains.value.map((domain) => {
241
+ const fallback = buildFallbackDomainEntry(domain)
242
+ const value = domainRegistry.value?.[domain] || {}
243
+ const dnsRecords = {
244
+ ...fallback.dnsRecords,
245
+ ...(value.dnsRecords || {}),
246
+ www: {
247
+ ...fallback.dnsRecords.www,
248
+ ...(value?.dnsRecords?.www || {}),
249
+ },
250
+ apex: {
251
+ ...fallback.dnsRecords.apex,
252
+ ...(value?.dnsRecords?.apex || {}),
253
+ },
254
+ }
255
+ const apexAdded = value?.apexAdded === true
256
+ return {
257
+ ...fallback,
258
+ ...value,
259
+ dnsRecords,
260
+ apexAdded,
261
+ apexAttempted: value?.apexAttempted === true,
262
+ apexError: String(value?.apexError || '').trim(),
263
+ dnsGuidance: String(value?.dnsGuidance || '').trim()
264
+ || (apexAdded ? '' : fallback.dnsGuidance),
265
+ }
266
+ })
267
+ })
106
268
 
107
- onMounted(async () => {
269
+ const fetchDomainRegistry = async (options = {}) => {
270
+ const { background = false } = options
108
271
  if (!edgeFirebase?.runFunction)
109
272
  return
273
+ const domains = normalizedDomains.value
274
+ if (!background)
275
+ loadingDomainRegistry.value = true
110
276
  try {
111
- const response = await edgeFirebase.runFunction('cms-getCloudflarePagesProject', {})
277
+ const response = await edgeFirebase.runFunction('cms-getCloudflarePagesProject', {
278
+ orgId: organizationId.value,
279
+ siteId: props.siteId || '',
280
+ domains,
281
+ })
112
282
  serverPagesProject.value = String(response?.data?.project || '').trim()
283
+ const nextRegistry = response?.data?.domainRegistry
284
+ if (domains.length && nextRegistry && typeof nextRegistry === 'object')
285
+ domainRegistry.value = nextRegistry
286
+ else
287
+ domainRegistry.value = {}
288
+ hasLoadedDomainRegistry.value = true
113
289
  }
114
290
  catch {
115
291
  serverPagesProject.value = ''
292
+ domainRegistry.value = {}
293
+ hasLoadedDomainRegistry.value = true
116
294
  }
295
+ finally {
296
+ if (!background)
297
+ loadingDomainRegistry.value = false
298
+ }
299
+ }
300
+
301
+ const stopDomainRegistryPolling = () => {
302
+ if (domainRegistryPollTimer) {
303
+ clearInterval(domainRegistryPollTimer)
304
+ domainRegistryPollTimer = null
305
+ }
306
+ }
307
+
308
+ const startDomainRegistryPolling = () => {
309
+ stopDomainRegistryPolling()
310
+ if (!props.settingsOpen)
311
+ return
312
+ if (!normalizedDomains.value.length)
313
+ return
314
+ domainRegistryPollTimer = setInterval(() => {
315
+ fetchDomainRegistry({ background: true }).catch(() => {})
316
+ }, DOMAIN_REGISTRY_POLL_MS)
317
+ }
318
+
319
+ watch(() => `${props.siteId}:${organizationId.value}:${normalizedDomains.value.join('|')}`, async () => {
320
+ hasLoadedDomainRegistry.value = false
321
+ await fetchDomainRegistry()
322
+ startDomainRegistryPolling()
323
+ })
324
+
325
+ watch(() => props.settingsOpen, async (open) => {
326
+ if (open) {
327
+ hasLoadedDomainRegistry.value = false
328
+ await fetchDomainRegistry()
329
+ startDomainRegistryPolling()
330
+ }
331
+ else {
332
+ stopDomainRegistryPolling()
333
+ }
334
+ }, { immediate: true })
335
+
336
+ onBeforeUnmount(() => {
337
+ stopDomainRegistryPolling()
117
338
  })
339
+
340
+ watch(() => props.settings?.forwardApex, (value) => {
341
+ if (value === undefined)
342
+ props.settings.forwardApex = true
343
+ }, { immediate: true })
118
344
  </script>
119
345
 
120
346
  <template>
121
347
  <Tabs class="w-full" default-value="general">
122
- <TabsList class="w-full gap-2 bg-muted/40 p-1 rounded-lg">
123
- <TabsTrigger value="general" class="text-sm uppercase font-medium">
348
+ <TabsList class="w-full mt-3 bg-secondary rounded-sm grid grid-cols-2 md:grid-cols-4 xl:grid-cols-7 gap-1">
349
+ <TabsTrigger value="general" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
124
350
  General
125
351
  </TabsTrigger>
126
- <TabsTrigger value="appearance" class="text-sm uppercase font-medium">
352
+ <TabsTrigger value="domains" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
353
+ Domains
354
+ </TabsTrigger>
355
+ <TabsTrigger value="appearance" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
127
356
  Appearance
128
357
  </TabsTrigger>
129
- <TabsTrigger value="branding" class="text-sm uppercase font-medium">
358
+ <TabsTrigger value="branding" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
130
359
  Branding
131
360
  </TabsTrigger>
132
- <TabsTrigger value="seo" class="text-sm uppercase font-medium">
361
+ <TabsTrigger value="seo" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
133
362
  SEO
134
363
  </TabsTrigger>
135
- <TabsTrigger value="tracking" class="text-sm uppercase font-medium">
364
+ <TabsTrigger value="tracking" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
136
365
  Tracking Pixels
137
366
  </TabsTrigger>
138
- <TabsTrigger value="social" class="text-sm uppercase font-medium">
367
+ <TabsTrigger value="social" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
139
368
  Social Media
140
369
  </TabsTrigger>
141
370
  </TabsList>
@@ -147,46 +376,6 @@ onMounted(async () => {
147
376
  placeholder="Enter name"
148
377
  class="w-full"
149
378
  />
150
- <edge-shad-tags
151
- v-model="props.settings.domains"
152
- name="domains"
153
- label="Domains"
154
- placeholder="Add or remove domains"
155
- class="w-full"
156
- />
157
- <Alert v-if="domainError" variant="destructive">
158
- <CircleAlert class="h-4 w-4" />
159
- <AlertTitle>Domain error</AlertTitle>
160
- <AlertDescription class="text-sm">
161
- {{ domainError }}
162
- </AlertDescription>
163
- </Alert>
164
- <div class="rounded-lg border border-border/60 bg-muted/40 p-4 space-y-3">
165
- <div class="flex items-center justify-between">
166
- <div class="text-sm font-semibold text-foreground">
167
- Domain DNS records
168
- </div>
169
- <div class="text-xs text-muted-foreground">
170
- Target: <span class="font-mono">{{ pagesDomain }}</span>
171
- </div>
172
- </div>
173
- <p class="text-sm text-muted-foreground">
174
- Add these records at your DNS provider.
175
- </p>
176
- <div class="space-y-2 text-sm">
177
- <div class="grid grid-cols-[70px_1fr] gap-3">
178
- <div class="text-muted-foreground">CNAME</div>
179
- <div class="font-mono">www → {{ pagesDomain }}</div>
180
- </div>
181
- <div class="grid grid-cols-[70px_1fr] gap-3">
182
- <div class="text-muted-foreground">CNAME</div>
183
- <div class="font-mono">@ → {{ pagesDomain }}</div>
184
- </div>
185
- </div>
186
- <p class="text-xs text-muted-foreground">
187
- Then forward the root/apex (TLD) domain to <span class="font-mono">www</span> with a 301 redirect.
188
- </p>
189
- </div>
190
379
  <edge-shad-input
191
380
  v-model="props.settings.contactEmail"
192
381
  name="contactEmail"
@@ -219,6 +408,99 @@ onMounted(async () => {
219
408
  No organization users available for this site.
220
409
  </p>
221
410
  </TabsContent>
411
+ <TabsContent value="domains" class="pt-4 space-y-4">
412
+ <edge-shad-tags
413
+ v-model="props.settings.domains"
414
+ name="domains"
415
+ label="Domains"
416
+ placeholder="Add or remove domains"
417
+ class="w-full"
418
+ />
419
+ <div class="rounded-lg border border-border/60 bg-muted/40 p-4 space-y-3">
420
+ <edge-shad-switch
421
+ v-model="forwardApexEnabled"
422
+ name="forwardApex"
423
+ label="Forward Apex (non-www) domains to www"
424
+ class="w-full"
425
+ >
426
+ Use a single canonical host (www) to avoid duplicate URLs and consolidate SEO signals.
427
+ </edge-shad-switch>
428
+ <p class="text-xs text-amber-700 dark:text-amber-300">
429
+ Warning: if your DNS provider already redirects www to non-www, this can create a redirect loop.
430
+ </p>
431
+ </div>
432
+ <Alert v-if="domainError" variant="destructive">
433
+ <CircleAlert class="h-4 w-4" />
434
+ <AlertTitle>Domain error</AlertTitle>
435
+ <AlertDescription class="text-sm">
436
+ {{ domainError }}
437
+ </AlertDescription>
438
+ </Alert>
439
+ <div class="rounded-lg border border-border/60 bg-muted/40 p-4 space-y-3">
440
+ <div class="flex items-center justify-between">
441
+ <div class="text-sm font-semibold text-foreground">
442
+ Domain DNS records
443
+ </div>
444
+ <div class="text-xs text-muted-foreground">
445
+ Target: <span class="font-mono">{{ pagesDomain }}</span>
446
+ </div>
447
+ </div>
448
+ <p class="text-sm text-muted-foreground">
449
+ Records are listed for each domain.
450
+ </p>
451
+ <p v-if="shouldShowDomainRegistryLoading" class="text-xs text-muted-foreground">
452
+ Waiting for latest domain sync results...
453
+ </p>
454
+ <div v-if="!domainDnsEntries.length" class="text-sm text-muted-foreground italic">
455
+ Add at least one valid domain to see DNS records.
456
+ </div>
457
+ <div
458
+ v-for="entry in domainDnsEntries"
459
+ :key="entry.domain"
460
+ class="rounded-md border border-border/50 bg-background/70 p-3 space-y-3"
461
+ >
462
+ <div class="flex items-center justify-between gap-3">
463
+ <div class="text-sm font-semibold text-foreground font-mono">
464
+ {{ entry.domain }}
465
+ </div>
466
+ <div class="text-xs">
467
+ <span
468
+ v-if="entry.apexAdded"
469
+ class="rounded bg-emerald-500/15 text-emerald-700 dark:text-emerald-300 px-2 py-1"
470
+ >
471
+ Apex added
472
+ </span>
473
+ <span
474
+ v-else
475
+ class="rounded bg-amber-500/15 text-amber-700 dark:text-amber-300 px-2 py-1"
476
+ >
477
+ Apex not added
478
+ </span>
479
+ </div>
480
+ </div>
481
+ <div class="space-y-2 text-sm">
482
+ <div class="grid grid-cols-[70px_1fr] gap-3">
483
+ <div class="text-muted-foreground">CNAME</div>
484
+ <div class="font-mono">
485
+ {{ entry?.dnsRecords?.www?.name || 'www' }} → {{ entry?.dnsRecords?.www?.value || pagesDomain }}
486
+ </div>
487
+ </div>
488
+ <div class="grid grid-cols-[70px_1fr] gap-3">
489
+ <div class="text-muted-foreground">CNAME</div>
490
+ <div class="font-mono">
491
+ {{ entry?.dnsRecords?.apex?.name || '@' }} → {{ entry?.dnsRecords?.apex?.value || pagesDomain }}
492
+ </div>
493
+ </div>
494
+ </div>
495
+ <p v-if="entry.apexError" class="text-xs text-amber-700 dark:text-amber-300">
496
+ {{ entry.apexError }}
497
+ </p>
498
+ <p v-if="!entry.apexAdded && entry.dnsGuidance" class="text-xs text-muted-foreground">
499
+ {{ entry.dnsGuidance }}
500
+ </p>
501
+ </div>
502
+ </div>
503
+ </TabsContent>
222
504
  <TabsContent value="appearance" class="pt-4 space-y-4">
223
505
  <edge-shad-select-tags
224
506
  v-if="props.showThemeFields && props.isAdmin"
@@ -87,6 +87,24 @@ const filteredMetaFields = computed(() => {
87
87
  return (props.metaFields || []).filter(field => !skipFields.has(field.field))
88
88
  })
89
89
 
90
+ const profilePhotoField = computed(() => {
91
+ return (props.metaFields || []).find(field => field?.field === 'profilephoto') || {}
92
+ })
93
+
94
+ const profilePhotoSite = computed(() => {
95
+ const baseSite = String(profilePhotoField.value?.site || 'system-images').trim() || 'system-images'
96
+ const uid = edgeFirebase?.user?.uid
97
+ if (!uid)
98
+ return baseSite
99
+ return `${baseSite}-${uid}`
100
+ })
101
+
102
+ const profilePhotoTags = computed(() => {
103
+ if (Array.isArray(profilePhotoField.value?.tags) && profilePhotoField.value.tags.length)
104
+ return profilePhotoField.value.tags
105
+ return ['Headshots']
106
+ })
107
+
90
108
  const initializeDefaults = (meta) => {
91
109
  defaultFields.forEach((field) => {
92
110
  if (!(field.field in meta))
@@ -249,8 +267,8 @@ const menuIcon = computed(() => {
249
267
  v-model="state.meta.profilephoto"
250
268
  label="Profile Photo"
251
269
  dialog-title="Select Profile Photo"
252
- :site="`${clearwater - hub - images}-${edgeFirebase.user.uid}`"
253
- :default-tags="['Headshots']"
270
+ :site="profilePhotoSite"
271
+ :default-tags="profilePhotoTags"
254
272
  height-class="h-full min-h-[180px]"
255
273
  :include-cms-all="false"
256
274
  />
@@ -294,7 +312,7 @@ const menuIcon = computed(() => {
294
312
  :model-value="getByPath(state.meta, field.field, '')"
295
313
  :label="field?.label || 'Photo'"
296
314
  :dialog-title="field?.dialogTitle || 'Select Image'"
297
- :site="field?.site || 'clearwater-hub-images'"
315
+ :site="field?.site || 'system-images'"
298
316
  :include-cms-all="false"
299
317
  :default-tags="field?.tags || []"
300
318
  :height-class="field?.heightClass || 'h-[160px]'"
@@ -15,6 +15,7 @@ export const useSiteSettingsTemplate = () => {
15
15
  favicon: '',
16
16
  menuPosition: 'right',
17
17
  domains: [],
18
+ forwardApex: true,
18
19
  contactEmail: '',
19
20
  contactPhone: '',
20
21
  metaTitle: '',
@@ -49,6 +50,7 @@ export const useSiteSettingsTemplate = () => {
49
50
  favicon: { bindings: { 'field-type': 'text', 'label': 'Favicon' }, cols: '12', value: defaults.favicon },
50
51
  menuPosition: { bindings: { 'field-type': 'select', 'label': 'Menu Position', 'items': ['left', 'center', 'right'] }, cols: '12', value: defaults.menuPosition },
51
52
  domains: { bindings: { 'field-type': 'tags', 'label': 'Domains', 'helper': 'Add or remove domains' }, cols: '12', value: defaults.domains },
53
+ forwardApex: { bindings: { 'field-type': 'boolean', 'label': 'Forward Apex (non-www) domains to www' }, cols: '12', value: defaults.forwardApex },
52
54
  contactEmail: { bindings: { 'field-type': 'text', 'label': 'Contact Email' }, cols: '12', value: defaults.contactEmail },
53
55
  contactPhone: { bindings: { 'field-type': 'text', 'label': 'Contact Phone' }, cols: '12', value: defaults.contactPhone },
54
56
  metaTitle: { bindings: { 'field-type': 'text', 'label': 'Meta Title' }, cols: '12', value: defaults.metaTitle },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgedev/create-edge-app",
3
- "version": "1.2.30",
3
+ "version": "1.2.32",
4
4
  "description": "Create Edge Starter App",
5
5
  "bin": {
6
6
  "create-edge-app": "./bin/cli.js"