Skip to content

Commit 0e18c7e

Browse files
authored
feat(app): update starter to be fully compliant with Nuxt Studio (#145)
1 parent a653939 commit 0e18c7e

18 files changed

+622
-577
lines changed
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
import { UCard } from '#components'
3+
4+
defineProps<{
5+
reverse?: boolean
6+
card?: boolean
7+
}>()
8+
</script>
9+
10+
<template>
11+
<component :is="card ? UCard : 'div'">
12+
<div class="grid grid-cols-3 items-center w-full gap-x-8">
13+
<div :class="{ 'order-2': reverse }">
14+
<slot name="image" />
15+
</div>
16+
<div class="col-span-2">
17+
<slot />
18+
</div>
19+
</div>
20+
</component>
21+
</template>

app/components/content/Pictures.vue

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script setup lang="ts">
2+
defineProps<{
3+
orientation: 'horizontal' | 'vertical'
4+
}>()
5+
</script>
6+
7+
<template>
8+
<div
9+
class="flex items-center justify-between"
10+
:class="orientation === 'vertical' ? 'flex-col space-y-4' : 'flex-row space-x-4'"
11+
>
12+
<slot />
13+
</div>
14+
</template>

app/pages/blog/[slug].vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
1212
})
1313
})
1414
15-
const title = post.value.title
16-
const description = post.value.description
15+
const title = post.value.seo?.title || post.value.title
16+
const description = post.value.seo?.description || post.value.description
1717
1818
useSeoMeta({
1919
title,

app/pages/index.vue

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ const { data: page } = await useAsyncData('index', () => queryCollection('index'
33
44
useSeoMeta({
55
titleTemplate: '',
6-
title: page.value?.title,
7-
ogTitle: page.value?.title,
8-
description: page.value?.description,
9-
ogDescription: page.value?.description
6+
title: page.value?.seo?.title || page.value?.title,
7+
ogTitle: page.value?.seo?.title || page.value?.title,
8+
description: page.value?.seo?.description || page.value?.description,
9+
ogDescription: page.value?.seo?.description || page.value?.description
1010
})
1111
</script>
1212

1313
<template>
1414
<div v-if="page">
1515
<UPageHero
16-
:title="page.hero.title"
17-
:description="page.hero.description"
16+
:title="page.title"
17+
:description="page.description"
1818
:links="page.hero.links"
1919
>
2020
<template #top>

app/pages/pricing.vue

+8-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
const { data: page } = await useAsyncData('pricing', () => queryCollection('pricing').first())
33
44
useSeoMeta({
5-
title: page.value?.title,
6-
ogTitle: page.value?.title,
7-
description: page.value?.description,
8-
ogDescription: page.value?.description
5+
title: page.value?.seo?.title || page.value?.title,
6+
ogTitle: page.value?.seo?.title || page.value?.title,
7+
description: page.value?.seo?.description || page.value?.description,
8+
ogDescription: page.value?.seo?.description || page.value?.description
99
})
1010
1111
defineOgImageComponent('Saas')
@@ -26,7 +26,10 @@ const items = ref([
2626

2727
<template>
2828
<div v-if="page">
29-
<UPageHero v-bind="page.hero">
29+
<UPageHero
30+
:title="page.title"
31+
:description="page.description"
32+
>
3033
<template #links>
3134
<UTabs
3235
v-model="isYearly"

content.config.ts

+33-58
Original file line numberDiff line numberDiff line change
@@ -5,94 +5,74 @@ const colorEnum = z.enum(['primary', 'secondary', 'neutral', 'error', 'warning',
55
const sizeEnum = z.enum(['xs', 'sm', 'md', 'lg', 'xl'])
66
const orientationEnum = z.enum(['vertical', 'horizontal'])
77

8-
const baseSchema = {
8+
const createBaseSchema = () => z.object({
99
title: z.string().nonempty(),
1010
description: z.string().nonempty()
11-
}
11+
})
1212

13-
const linkSchema = z.object({
13+
const createFeatureItemSchema = () => createBaseSchema().extend({
14+
icon: z.string().nonempty().editor({ input: 'icon' })
15+
})
16+
17+
const createLinkSchema = () => z.object({
1418
label: z.string().nonempty(),
1519
to: z.string().nonempty(),
16-
icon: z.string().optional(),
20+
icon: z.string().optional().editor({ input: 'icon' }),
1721
size: sizeEnum.optional(),
1822
trailing: z.boolean().optional(),
1923
target: z.string().optional(),
2024
color: colorEnum.optional(),
2125
variant: variantEnum.optional()
2226
})
2327

24-
const imageSchema = z.object({
25-
src: z.string().nonempty(),
28+
const createImageSchema = () => z.object({
29+
src: z.string().nonempty().editor({ input: 'media' }),
2630
alt: z.string().optional(),
2731
loading: z.string().optional(),
2832
srcset: z.string().optional()
2933
})
3034

31-
const featureItemSchema = z.object({
32-
...baseSchema,
33-
icon: z.string().nonempty()
34-
})
35-
36-
const sectionSchema = z.object({
37-
headline: z.string().optional(),
38-
...baseSchema,
39-
features: z.array(featureItemSchema)
40-
})
41-
4235
export const collections = {
4336
docs: defineCollection({
4437
type: 'page',
45-
source: '1.docs/**/*',
46-
schema: z.object({
47-
title: z.string().nonempty(),
48-
description: z.string().nonempty()
49-
})
38+
source: '1.docs/**/*'
5039
}),
5140
posts: defineCollection({
5241
type: 'page',
5342
source: '3.blog/**/*',
5443
schema: z.object({
55-
title: z.string().nonempty(),
56-
description: z.string().nonempty(),
57-
image: z.object({ src: z.string().nonempty() }),
44+
image: z.object({ src: z.string().nonempty().editor({ input: 'media' }) }),
5845
authors: z.array(
5946
z.object({
6047
name: z.string().nonempty(),
6148
to: z.string().nonempty(),
62-
avatar: z.object({ src: z.string().nonempty() })
49+
avatar: z.object({ src: z.string().nonempty().editor({ input: 'media' }) })
6350
})
6451
),
65-
date: z.string().nonempty(),
52+
date: z.date(),
6653
badge: z.object({ label: z.string().nonempty() })
6754
})
6855
}),
6956
index: defineCollection({
7057
source: '0.index.yml',
71-
type: 'data',
58+
type: 'page',
7259
schema: z.object({
73-
title: z.string().nonempty(),
74-
description: z.string().nonempty(),
75-
hero: sectionSchema.extend({
76-
headline: z.object({
77-
label: z.string().nonempty(),
78-
to: z.string().nonempty(),
79-
icon: z.string().nonempty()
80-
}),
81-
links: z.array(linkSchema)
82-
}),
60+
hero: z.object(({
61+
links: z.array(createLinkSchema())
62+
})),
8363
sections: z.array(
84-
sectionSchema.extend({
64+
createBaseSchema().extend({
8565
id: z.string().nonempty(),
8666
orientation: orientationEnum.optional(),
87-
features: z.array(featureItemSchema),
88-
links: z.array(linkSchema),
89-
reverse: z.boolean().optional()
67+
reverse: z.boolean().optional(),
68+
features: z.array(createFeatureItemSchema())
9069
})
9170
),
92-
features: sectionSchema.extend({
93-
items: z.array(featureItemSchema)
71+
features: createBaseSchema().extend({
72+
items: z.array(createFeatureItemSchema())
9473
}),
95-
testimonials: sectionSchema.extend({
74+
testimonials: createBaseSchema().extend({
75+
headline: z.string().optional(),
9676
items: z.array(
9777
z.object({
9878
quote: z.string().nonempty(),
@@ -101,24 +81,20 @@ export const collections = {
10181
description: z.string().nonempty(),
10282
to: z.string().nonempty(),
10383
target: z.string().nonempty(),
104-
avatar: imageSchema
84+
avatar: createImageSchema()
10585
})
10686
})
10787
)
10888
}),
109-
cta: sectionSchema.extend({
110-
links: z.array(linkSchema)
89+
cta: createBaseSchema().extend({
90+
links: z.array(createLinkSchema())
11191
})
11292
})
11393
}),
11494
pricing: defineCollection({
11595
source: '2.pricing.yml',
116-
type: 'data',
117-
schema: sectionSchema.extend({
118-
hero: z.object({
119-
title: z.string().nonempty(),
120-
description: z.string().nonempty()
121-
}),
96+
type: 'page',
97+
schema: z.object({
12298
plans: z.array(
12399
z.object({
124100
title: z.string().nonempty(),
@@ -129,7 +105,7 @@ export const collections = {
129105
}),
130106
billing_period: z.string().nonempty(),
131107
billing_cycle: z.string().nonempty(),
132-
button: linkSchema,
108+
button: createLinkSchema(),
133109
features: z.array(z.string().nonempty()),
134110
highlight: z.boolean().optional()
135111
})
@@ -138,7 +114,7 @@ export const collections = {
138114
title: z.string().nonempty(),
139115
icons: z.array(z.string())
140116
}),
141-
faq: sectionSchema.extend({
117+
faq: createBaseSchema().extend({
142118
items: z.array(
143119
z.object({
144120
label: z.string().nonempty(),
@@ -151,7 +127,6 @@ export const collections = {
151127
}),
152128
blog: defineCollection({
153129
source: '3.blog.yml',
154-
type: 'data',
155-
schema: sectionSchema
130+
type: 'page'
156131
})
157132
}

content/0.index.yml

+17-16
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
title: Nuxt UI Pro - SaaS template
2-
description: Nuxt UI Pro is a collection of premium Vue components built on top of Nuxt UI to create beautiful & responsive Nuxt applications in minutes.
1+
title: Build your SaaS with Nuxt UI Pro
2+
description: Nuxt UI Pro is a collection of premium Vue components built on top of Nuxt UI to create beautiful & responsive Nuxt applications in minutes. It includes all primitives to build landing pages, documentations, blogs, dashboards or entire SaaS products.
3+
seo:
4+
title: Nuxt UI Pro - SaaS template
5+
description: Nuxt UI Pro is a collection of premium Vue components built on top of Nuxt UI to create beautiful & responsive Nuxt applications in minutes.
36
navigation: false
47
hero:
5-
title: Build your SaaS with Nuxt UI Pro
6-
description: Nuxt UI Pro is a collection of premium Vue components built on top of Nuxt UI to create beautiful & responsive Nuxt applications in minutes. It includes all primitives to build landing pages, documentations, blogs, dashboards or entire SaaS products.
78
links:
89
- label: Get started
910
icon: i-lucide-arrow-right
@@ -74,61 +75,61 @@ testimonials:
7475
title: Trusted by Industry Leaders
7576
description: Join thousands of companies worldwide who have transformed their digital presence with our platform.
7677
items:
77-
- quote: "The developer experience is unmatched. We migrated our entire infrastructure in weeks instead of months, and our team's productivity has increased dramatically. The TypeScript support and component library saved us months of development time."
78+
- quote: The developer experience is unmatched. We migrated our entire infrastructure in weeks instead of months, and our team's productivity has increased dramatically. The TypeScript support and component library saved us months of development time.
7879
user:
7980
name: Sarah Chen
8081
description: CTO at TechScale Solutions
8182
avatar:
8283
src: https://i.pravatar.cc/120?img=1
83-
- quote: "After implementing the edge computing features, our global application response times dropped by 70%. Our European and Asian markets saw immediate improvements in user engagement and conversion rates."
84+
- quote: After implementing the edge computing features, our global application response times dropped by 70%. Our European and Asian markets saw immediate improvements in user engagement and conversion rates.
8485
user:
8586
name: Marcus Rodriguez
8687
description: VP of Engineering at DataFlow
8788
avatar:
8889
src: https://i.pravatar.cc/120?img=7
89-
- quote: "The platform's security features gave us peace of mind during our SOC 2 certification. The built-in compliance tools and audit logs made the process seamless."
90+
- quote: The platform's security features gave us peace of mind during our SOC 2 certification. The built-in compliance tools and audit logs made the process seamless.
9091
user:
9192
name: David Kumar
9293
description: Security Director at SecureStack
9394
avatar:
9495
src: https://i.pravatar.cc/120?img=3
95-
- quote: "During our Black Friday sale, we handled 15x our normal traffic without a hitch. The auto-scaling features worked flawlessly, and our monitoring dashboard gave us real-time insights throughout the event."
96+
- quote: During our Black Friday sale, we handled 15x our normal traffic without a hitch. The auto-scaling features worked flawlessly, and our monitoring dashboard gave us real-time insights throughout the event.
9697
user:
9798
name: Emily Zhang
9899
description: Lead Architect at ScaleForce
99100
avatar:
100101
src: https://i.pravatar.cc/120?img=5
101-
- quote: "The support team goes above and beyond. They helped us optimize our CI/CD pipeline and suggested performance improvements that reduced our build times by 45%."
102+
- quote: The support team goes above and beyond. They helped us optimize our CI/CD pipeline and suggested performance improvements that reduced our build times by 45%.
102103
user:
103104
name: James Wilson
104105
description: DevOps Lead at CloudPro
105106
avatar:
106107
src: https://i.pravatar.cc/120?img=8
107-
- quote: "Switching to this platform reduced our infrastructure costs by 40% while improving performance. The cost savings alone paid for the investment within the first quarter."
108+
- quote: Switching to this platform reduced our infrastructure costs by 40% while improving performance. The cost savings alone paid for the investment within the first quarter.
108109
user:
109110
name: Lisa Patel
110111
description: CEO at AutoScale
111112
avatar:
112113
src: https://i.pravatar.cc/120?img=9
113-
- quote: "The accessibility features and responsive components helped us achieve WCAG 2.1 compliance with minimal custom development. Our site now scores 100 on Lighthouse accessibility metrics."
114+
- quote: The accessibility features and responsive components helped us achieve WCAG 2.1 compliance with minimal custom development. Our site now scores 100 on Lighthouse accessibility metrics.
114115
user:
115116
name: Michael Torres
116117
description: Frontend Lead at AccessFirst
117118
avatar:
118119
src: https://i.pravatar.cc/120?img=11
119-
- quote: "We serve millions of API requests daily, and the real-time analytics and monitoring tools have been invaluable for optimizing our performance and identifying bottlenecks."
120+
- quote: We serve millions of API requests daily, and the real-time analytics and monitoring tools have been invaluable for optimizing our performance and identifying bottlenecks.
120121
user:
121122
name: Rachel Kim
122123
description: Performance Engineer at APIHub
123124
avatar:
124125
src: https://i.pravatar.cc/120?img=10
125-
- quote: "The component library and design system tools helped us maintain consistency across our 20+ micro-frontends. Our development velocity has never been better."
126+
- quote: The component library and design system tools helped us maintain consistency across our 20+ micro-frontends. Our development velocity has never been better.
126127
user:
127128
name: Thomas Weber
128129
description: UI Architecture Lead at DesignScale
129130
avatar:
130131
src: https://i.pravatar.cc/120?img=12
131-
- quote: "Integration with our existing tools was seamless. The webhooks and API documentation made it easy to automate our workflows and enhance our development pipeline."
132+
- quote: Integration with our existing tools was seamless. The webhooks and API documentation made it easy to automate our workflows and enhance our development pipeline.
132133
user:
133134
name: Sophia Martinez
134135
description: Integration Specialist at TechFlow
@@ -139,11 +140,11 @@ cta:
139140
description: Nuxt UI Pro is free in development, but you need a license to use it in production.
140141
links:
141142
- label: Buy now
142-
to: 'https://ui.nuxt.com/pro/purchase'
143+
to: https://ui.nuxt.com/pro/purchase
143144
target: _blank
144145
icon: i-lucide-shopping-cart
145146
- label: License
146-
to: 'https://ui.nuxt.com/getting-started/license'
147+
to: https://ui.nuxt.com/getting-started/license
147148
trailingIcon: i-lucide-circle-help
148149
target: _blank
149150
variant: subtle

content/1.docs/1.getting-started/1.index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ to: https://codesandbox.io/s/github/nuxt-ui-pro/saas/
4141
---
4242
::
4343

44-
Or open [Nuxt UI playground](https://ui.nuxt.com/playground){target=_blank}.
44+
Or open [Nuxt UI playground](https://ui.nuxt.com/playground).

content/2.pricing.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
title: Pricing
2-
description: Choose the plan that's right for you.
1+
title: A plan for every need
2+
description: Our plans are designed to meet the requirements of both beginners and players. Get the right plan that suits you.
3+
seo:
4+
title: Pricing
5+
description: Choose the plan that's right for you.
36
navigation.icon: i-lucide-credit-card
4-
hero:
5-
title: A plan for every need
6-
description: Our plans are designed to meet the requirements of both beginners and players. Get the right plan that suits you.
77
plans:
88
- title: Basic
99
description: A basic plan for individuals.

0 commit comments

Comments
 (0)