@stackonward/cli 1.2.1 → 1.3.0
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/dist/index.js +17 -10
- package/dist/index.js.map +1 -1
- package/dist/resources/components/nuxt/site-source/app/app.vue +9 -6
- package/dist/resources/components/nuxt/site-source/app/assets/css/site-shell.css +268 -33
- package/dist/resources/components/nuxt/site-source/app/components/site/ApplicationHeader.vue +7 -4
- package/dist/resources/components/nuxt/site-source/app/components/site/ApplicationShell.vue +1 -1
- package/dist/resources/components/nuxt/site-source/app/components/site/ApplicationSidebar.vue +4 -3
- package/dist/resources/components/nuxt/site-source/app/components/site/BackToTop.vue +4 -12
- package/dist/resources/components/nuxt/site-source/app/components/site/ConsentSettingsButton.vue +24 -0
- package/dist/resources/components/nuxt/site-source/app/components/site/ContentArticlePage.vue +18 -6
- package/dist/resources/components/nuxt/site-source/app/components/site/ContentListPage.vue +2 -2
- package/dist/resources/components/nuxt/site-source/app/components/site/CookieConsent.vue +44 -4
- package/dist/resources/components/nuxt/site-source/app/components/site/LocaleSwitcher.vue +57 -0
- package/dist/resources/components/nuxt/site-source/app/components/site/MarketingFooter.vue +11 -9
- package/dist/resources/components/nuxt/site-source/app/components/site/MarketingHeader.vue +31 -19
- package/dist/resources/components/nuxt/site-source/app/components/site/MarketingShell.vue +7 -9
- package/dist/resources/components/nuxt/site-source/app/components/site/SiteBrand.vue +3 -2
- package/dist/resources/components/nuxt/site-source/app/components/site/StaticPage.vue +2 -1
- package/dist/resources/components/nuxt/site-source/app/components/site/ThemeSwitcher.vue +63 -0
- package/dist/resources/components/nuxt/site-source/app/components/site/ToastViewport.vue +3 -2
- package/dist/resources/components/nuxt/site-source/app/composables/useConsent.ts +299 -51
- package/dist/resources/components/nuxt/site-source/app/composables/useNavigation.ts +49 -6
- package/dist/resources/components/nuxt/site-source/app/composables/useSeo.ts +4 -2
- package/dist/resources/components/nuxt/site-source/app/composables/useSiteShell.ts +29 -11
- package/dist/resources/components/nuxt/site-source/app/plugins/consent.ts +43 -0
- package/dist/resources/components/nuxt/site-source/app/types/site-shell.ts +146 -59
- package/dist/resources/components/registry.json +30 -0
- package/dist/resources/registry.json +3 -3
- package/dist/resources/templates/nuxt/app/app.config.ts +83 -38
- package/dist/resources/templates/nuxt/app/i18n/locales/en.json +124 -0
- package/dist/resources/templates/nuxt/app/pages/legal/cookies.vue +68 -0
- package/dist/resources/templates/nuxt/nuxt.config.ts +16 -0
- package/dist/resources/templates/nuxt/package.json +2 -2
- package/dist/resources/templates/nuxt/test/unit/consent.test.ts +289 -0
- package/dist/resources/templates/nuxt/vitest.config.ts +6 -0
- package/package.json +3 -3
|
@@ -1,85 +1,172 @@
|
|
|
1
|
+
import type { ComputedRef, DeepReadonly, Ref } from "vue";
|
|
2
|
+
|
|
3
|
+
export interface LocalizedNavigationItemConfig {
|
|
4
|
+
readonly labelKey: string;
|
|
5
|
+
readonly to?: string;
|
|
6
|
+
readonly external?: boolean;
|
|
7
|
+
readonly descriptionKey?: string;
|
|
8
|
+
readonly children?: readonly LocalizedNavigationItemConfig[];
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
export interface MarketingNavigationItem {
|
|
2
|
-
label: string;
|
|
3
|
-
to?: string;
|
|
4
|
-
external?: boolean;
|
|
5
|
-
description?: string;
|
|
6
|
-
children?: MarketingNavigationItem[];
|
|
12
|
+
readonly label: string;
|
|
13
|
+
readonly to?: string;
|
|
14
|
+
readonly external?: boolean;
|
|
15
|
+
readonly description?: string;
|
|
16
|
+
readonly children?: readonly MarketingNavigationItem[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface AppNavigationItemConfig {
|
|
20
|
+
readonly labelKey: string;
|
|
21
|
+
readonly to: string;
|
|
22
|
+
readonly icon?: string;
|
|
23
|
+
readonly badge?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AppNavigationItem extends Omit<AppNavigationItemConfig, "labelKey"> {
|
|
27
|
+
readonly label: string;
|
|
7
28
|
}
|
|
8
29
|
|
|
9
|
-
export interface
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
icon?: string;
|
|
13
|
-
badge?: string;
|
|
30
|
+
export interface NavigationGroupConfig {
|
|
31
|
+
readonly labelKey?: string;
|
|
32
|
+
readonly items: readonly AppNavigationItemConfig[];
|
|
14
33
|
}
|
|
15
34
|
|
|
16
35
|
export interface NavigationGroup {
|
|
17
|
-
label?: string;
|
|
18
|
-
items: AppNavigationItem[];
|
|
36
|
+
readonly label?: string;
|
|
37
|
+
readonly items: readonly AppNavigationItem[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface FooterGroupConfig {
|
|
41
|
+
readonly titleKey: string;
|
|
42
|
+
readonly links: readonly LocalizedNavigationItemConfig[];
|
|
19
43
|
}
|
|
20
44
|
|
|
21
45
|
export interface FooterGroup {
|
|
22
|
-
title: string;
|
|
23
|
-
links: MarketingNavigationItem[];
|
|
46
|
+
readonly title: string;
|
|
47
|
+
readonly links: readonly MarketingNavigationItem[];
|
|
24
48
|
}
|
|
25
49
|
|
|
26
|
-
export interface
|
|
27
|
-
|
|
28
|
-
|
|
50
|
+
export interface SocialLinkConfig {
|
|
51
|
+
readonly labelKey: string;
|
|
52
|
+
readonly href: string;
|
|
29
53
|
}
|
|
30
54
|
|
|
31
55
|
export interface SocialLink {
|
|
32
|
-
label: string;
|
|
33
|
-
href: string;
|
|
56
|
+
readonly label: string;
|
|
57
|
+
readonly href: string;
|
|
34
58
|
}
|
|
35
59
|
|
|
36
60
|
export interface ContentListItem {
|
|
37
|
-
title: string;
|
|
38
|
-
description?: string;
|
|
39
|
-
to: string;
|
|
40
|
-
category?: string;
|
|
41
|
-
date?: string;
|
|
42
|
-
author?: string;
|
|
61
|
+
readonly title: string;
|
|
62
|
+
readonly description?: string;
|
|
63
|
+
readonly to: string;
|
|
64
|
+
readonly category?: string;
|
|
65
|
+
readonly date?: string;
|
|
66
|
+
readonly author?: string;
|
|
43
67
|
}
|
|
44
68
|
|
|
45
69
|
export interface ContentArticle {
|
|
46
|
-
title: string;
|
|
47
|
-
description?: string;
|
|
48
|
-
category?: string;
|
|
49
|
-
author?: string;
|
|
50
|
-
date?: string;
|
|
51
|
-
updatedAt?: string;
|
|
70
|
+
readonly title: string;
|
|
71
|
+
readonly description?: string;
|
|
72
|
+
readonly category?: string;
|
|
73
|
+
readonly author?: string;
|
|
74
|
+
readonly date?: string;
|
|
75
|
+
readonly updatedAt?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface StorageDisclosureConfig {
|
|
79
|
+
readonly name: string;
|
|
80
|
+
readonly category: "necessary" | "preferences" | "analytics";
|
|
81
|
+
readonly purposeKey: string;
|
|
82
|
+
readonly retentionKey: string;
|
|
83
|
+
readonly providerKey: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface SiteShellConsentConfig {
|
|
87
|
+
readonly enabled: boolean;
|
|
88
|
+
readonly storageKey: string;
|
|
89
|
+
readonly policyRevision: string;
|
|
90
|
+
readonly retentionDays: number;
|
|
91
|
+
readonly policyPath: string;
|
|
52
92
|
}
|
|
53
93
|
|
|
54
94
|
export interface SiteShellConfig {
|
|
55
|
-
name: string;
|
|
56
|
-
|
|
57
|
-
url: string;
|
|
58
|
-
defaultLocale: string;
|
|
59
|
-
homePath: string;
|
|
60
|
-
appPath: string;
|
|
61
|
-
logoText: string;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
secondaryActionPath: string;
|
|
65
|
-
consent:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
marketing: MarketingNavigationItem[];
|
|
74
|
-
app: NavigationGroup[];
|
|
75
|
-
footer: FooterGroup[];
|
|
76
|
-
legal: LegalLink[];
|
|
77
|
-
social: SocialLink[];
|
|
95
|
+
readonly name: string;
|
|
96
|
+
readonly descriptionKey: string;
|
|
97
|
+
readonly url: string;
|
|
98
|
+
readonly defaultLocale: string;
|
|
99
|
+
readonly homePath: string;
|
|
100
|
+
readonly appPath: string;
|
|
101
|
+
readonly logoText: string;
|
|
102
|
+
readonly primaryActionLabelKey: string;
|
|
103
|
+
readonly secondaryActionLabelKey: string;
|
|
104
|
+
readonly secondaryActionPath: string;
|
|
105
|
+
readonly consent: SiteShellConsentConfig;
|
|
106
|
+
readonly storageDisclosures: readonly StorageDisclosureConfig[];
|
|
107
|
+
readonly navigation: {
|
|
108
|
+
readonly marketing: readonly LocalizedNavigationItemConfig[];
|
|
109
|
+
readonly app: readonly NavigationGroupConfig[];
|
|
110
|
+
readonly footer: readonly FooterGroupConfig[];
|
|
111
|
+
readonly legal: readonly LocalizedNavigationItemConfig[];
|
|
112
|
+
readonly social: readonly SocialLinkConfig[];
|
|
78
113
|
};
|
|
79
|
-
content: {
|
|
80
|
-
blogPath: string;
|
|
81
|
-
authorPath: string;
|
|
82
|
-
previewPath: string;
|
|
83
|
-
sitemapSourcePath: string;
|
|
114
|
+
readonly content: {
|
|
115
|
+
readonly blogPath: string;
|
|
116
|
+
readonly authorPath: string;
|
|
117
|
+
readonly previewPath: string;
|
|
118
|
+
readonly sitemapSourcePath: string;
|
|
84
119
|
};
|
|
85
120
|
}
|
|
121
|
+
|
|
122
|
+
export interface ResolvedSiteNavigation {
|
|
123
|
+
readonly marketingNav: Readonly<ComputedRef<readonly MarketingNavigationItem[]>>;
|
|
124
|
+
readonly appNavGroups: Readonly<ComputedRef<readonly NavigationGroup[]>>;
|
|
125
|
+
readonly footerGroups: Readonly<ComputedRef<readonly FooterGroup[]>>;
|
|
126
|
+
readonly legalLinks: Readonly<ComputedRef<readonly MarketingNavigationItem[]>>;
|
|
127
|
+
readonly socialLinks: Readonly<ComputedRef<readonly SocialLink[]>>;
|
|
128
|
+
readonly primaryActionLabel: Readonly<ComputedRef<string>>;
|
|
129
|
+
readonly secondaryActionLabel: Readonly<ComputedRef<string>>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type ConsentValue = "accepted" | "rejected";
|
|
133
|
+
|
|
134
|
+
export type ConsentPersistenceError =
|
|
135
|
+
| "read-failed"
|
|
136
|
+
| "write-failed"
|
|
137
|
+
| "clear-failed"
|
|
138
|
+
| "write-and-clear-failed";
|
|
139
|
+
|
|
140
|
+
export interface ConsentState {
|
|
141
|
+
decision: ConsentValue | null;
|
|
142
|
+
ready: boolean;
|
|
143
|
+
settingsOpen: boolean;
|
|
144
|
+
persistence: "none" | "persisted" | "cleared" | "cleanup-failed" | "session-only";
|
|
145
|
+
error: ConsentPersistenceError | null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export type ConsentInitializationResult =
|
|
149
|
+
| { status: "restored"; value: ConsentValue }
|
|
150
|
+
| { status: "undecided"; cleanup: "not-required" | "cleared" }
|
|
151
|
+
| { status: "undecided"; cleanup: "failed"; error: "clear-failed" }
|
|
152
|
+
| { status: "storage-unavailable"; error: "read-failed" };
|
|
153
|
+
|
|
154
|
+
export type ConsentMutationResult =
|
|
155
|
+
| { status: "persisted"; value: ConsentValue }
|
|
156
|
+
| { status: "cleared"; value: "rejected"; error: "write-failed" }
|
|
157
|
+
| {
|
|
158
|
+
status: "session-only";
|
|
159
|
+
value: ConsentValue;
|
|
160
|
+
error: "write-failed" | "write-and-clear-failed";
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export interface SiteConsentController {
|
|
164
|
+
readonly state: DeepReadonly<Ref<ConsentState>>;
|
|
165
|
+
readonly visible: Readonly<ComputedRef<boolean>>;
|
|
166
|
+
initialize(): ConsentInitializationResult;
|
|
167
|
+
accept(): ConsentMutationResult;
|
|
168
|
+
reject(): ConsentMutationResult;
|
|
169
|
+
openSettings(): void;
|
|
170
|
+
closeSettings(): void;
|
|
171
|
+
dispose(): void;
|
|
172
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"button": {
|
|
3
3
|
"name": "Button",
|
|
4
4
|
"description": "Versatile button component with variants and sizes",
|
|
5
|
+
"installContext": "standalone",
|
|
5
6
|
"files": ["ui/Button.vue"],
|
|
6
7
|
"dependencies": [],
|
|
7
8
|
"devDependencies": [],
|
|
@@ -12,6 +13,7 @@
|
|
|
12
13
|
"input": {
|
|
13
14
|
"name": "Input",
|
|
14
15
|
"description": "Text input component with validation support",
|
|
16
|
+
"installContext": "standalone",
|
|
15
17
|
"files": ["ui/Input.vue"],
|
|
16
18
|
"dependencies": [],
|
|
17
19
|
"devDependencies": [],
|
|
@@ -22,6 +24,7 @@
|
|
|
22
24
|
"modal": {
|
|
23
25
|
"name": "Modal",
|
|
24
26
|
"description": "Modal dialog component with animations",
|
|
27
|
+
"installContext": "standalone",
|
|
25
28
|
"files": ["ui/Modal.vue"],
|
|
26
29
|
"dependencies": [],
|
|
27
30
|
"devDependencies": [],
|
|
@@ -32,6 +35,7 @@
|
|
|
32
35
|
"card": {
|
|
33
36
|
"name": "Card",
|
|
34
37
|
"description": "Card container component",
|
|
38
|
+
"installContext": "standalone",
|
|
35
39
|
"files": ["ui/Card.vue"],
|
|
36
40
|
"dependencies": [],
|
|
37
41
|
"devDependencies": [],
|
|
@@ -42,6 +46,7 @@
|
|
|
42
46
|
"app-image": {
|
|
43
47
|
"name": "AppImage",
|
|
44
48
|
"description": "Responsive image component with loading, placeholder, source-set, and error states",
|
|
49
|
+
"installContext": "standalone",
|
|
45
50
|
"files": ["ui/AppImage.vue"],
|
|
46
51
|
"dependencies": [],
|
|
47
52
|
"devDependencies": [],
|
|
@@ -52,6 +57,7 @@
|
|
|
52
57
|
"tooltip": {
|
|
53
58
|
"name": "Tooltip",
|
|
54
59
|
"description": "Accessible hover and focus tooltip primitive",
|
|
60
|
+
"installContext": "standalone",
|
|
55
61
|
"files": ["ui/Tooltip.vue"],
|
|
56
62
|
"dependencies": [],
|
|
57
63
|
"devDependencies": [],
|
|
@@ -62,6 +68,7 @@
|
|
|
62
68
|
"bottom-sheet": {
|
|
63
69
|
"name": "BottomSheet",
|
|
64
70
|
"description": "Mobile-friendly bottom sheet dialog with scroll lock and safe-area support",
|
|
71
|
+
"installContext": "standalone",
|
|
65
72
|
"files": ["ui/BottomSheet.vue"],
|
|
66
73
|
"dependencies": [],
|
|
67
74
|
"devDependencies": [],
|
|
@@ -72,6 +79,7 @@
|
|
|
72
79
|
"scroll-area": {
|
|
73
80
|
"name": "ScrollArea",
|
|
74
81
|
"description": "Controlled scroll container with exposed scroll helpers and reach-end events",
|
|
82
|
+
"installContext": "standalone",
|
|
75
83
|
"files": ["ui/ScrollArea.vue"],
|
|
76
84
|
"dependencies": [],
|
|
77
85
|
"devDependencies": [],
|
|
@@ -82,6 +90,7 @@
|
|
|
82
90
|
"file-upload": {
|
|
83
91
|
"name": "FileUpload",
|
|
84
92
|
"description": "Drag-and-drop file upload primitive wired to @stackonward/file validation",
|
|
93
|
+
"installContext": "standalone",
|
|
85
94
|
"files": ["media/FileUpload.vue"],
|
|
86
95
|
"dependencies": ["@stackonward/file"],
|
|
87
96
|
"devDependencies": [],
|
|
@@ -92,6 +101,7 @@
|
|
|
92
101
|
"video-player": {
|
|
93
102
|
"name": "VideoPlayer",
|
|
94
103
|
"description": "Video player primitive wired to @stackonward/composables playback state",
|
|
104
|
+
"installContext": "standalone",
|
|
95
105
|
"files": ["media/VideoPlayer.vue"],
|
|
96
106
|
"dependencies": ["@stackonward/composables"],
|
|
97
107
|
"devDependencies": [],
|
|
@@ -102,6 +112,7 @@
|
|
|
102
112
|
"toast": {
|
|
103
113
|
"name": "Toast",
|
|
104
114
|
"description": "Toast notification component",
|
|
115
|
+
"installContext": "standalone",
|
|
105
116
|
"files": ["feedback/Toast.vue", "feedback/useToast.ts"],
|
|
106
117
|
"dependencies": [],
|
|
107
118
|
"devDependencies": [],
|
|
@@ -112,6 +123,7 @@
|
|
|
112
123
|
"react-button": {
|
|
113
124
|
"name": "Button",
|
|
114
125
|
"description": "Versatile button component with variants and sizes",
|
|
126
|
+
"installContext": "standalone",
|
|
115
127
|
"files": ["ui/Button.tsx"],
|
|
116
128
|
"dependencies": [],
|
|
117
129
|
"devDependencies": [],
|
|
@@ -122,6 +134,7 @@
|
|
|
122
134
|
"react-input": {
|
|
123
135
|
"name": "Input",
|
|
124
136
|
"description": "Text input component with validation support",
|
|
137
|
+
"installContext": "standalone",
|
|
125
138
|
"files": ["ui/Input.tsx"],
|
|
126
139
|
"dependencies": [],
|
|
127
140
|
"devDependencies": [],
|
|
@@ -132,6 +145,7 @@
|
|
|
132
145
|
"nuxt-site-source": {
|
|
133
146
|
"name": "Nuxt Site Source",
|
|
134
147
|
"description": "Editable Nuxt product-site source: app shell, marketing shell, content shell, UI primitives, composables, plugins, theme tokens, and CSS.",
|
|
148
|
+
"installContext": "template",
|
|
135
149
|
"files": [
|
|
136
150
|
{
|
|
137
151
|
"path": "site-source/app/app.vue",
|
|
@@ -173,10 +187,18 @@
|
|
|
173
187
|
"path": "site-source/app/components/site/ContentListPage.vue",
|
|
174
188
|
"target": "app/components/site/ContentListPage.vue"
|
|
175
189
|
},
|
|
190
|
+
{
|
|
191
|
+
"path": "site-source/app/components/site/ConsentSettingsButton.vue",
|
|
192
|
+
"target": "app/components/site/ConsentSettingsButton.vue"
|
|
193
|
+
},
|
|
176
194
|
{
|
|
177
195
|
"path": "site-source/app/components/site/CookieConsent.vue",
|
|
178
196
|
"target": "app/components/site/CookieConsent.vue"
|
|
179
197
|
},
|
|
198
|
+
{
|
|
199
|
+
"path": "site-source/app/components/site/LocaleSwitcher.vue",
|
|
200
|
+
"target": "app/components/site/LocaleSwitcher.vue"
|
|
201
|
+
},
|
|
180
202
|
{
|
|
181
203
|
"path": "site-source/app/components/site/MarketingFooter.vue",
|
|
182
204
|
"target": "app/components/site/MarketingFooter.vue"
|
|
@@ -201,6 +223,10 @@
|
|
|
201
223
|
"path": "site-source/app/components/site/ToastViewport.vue",
|
|
202
224
|
"target": "app/components/site/ToastViewport.vue"
|
|
203
225
|
},
|
|
226
|
+
{
|
|
227
|
+
"path": "site-source/app/components/site/ThemeSwitcher.vue",
|
|
228
|
+
"target": "app/components/site/ThemeSwitcher.vue"
|
|
229
|
+
},
|
|
204
230
|
{
|
|
205
231
|
"path": "site-source/app/components/ui/BaseButton.vue",
|
|
206
232
|
"target": "app/components/ui/BaseButton.vue"
|
|
@@ -277,6 +303,10 @@
|
|
|
277
303
|
"path": "site-source/app/layouts/default.vue",
|
|
278
304
|
"target": "app/layouts/default.vue"
|
|
279
305
|
},
|
|
306
|
+
{
|
|
307
|
+
"path": "site-source/app/plugins/consent.ts",
|
|
308
|
+
"target": "app/plugins/consent.ts"
|
|
309
|
+
},
|
|
280
310
|
{
|
|
281
311
|
"path": "site-source/app/plugins/google-identity.client.ts",
|
|
282
312
|
"target": "app/plugins/google-identity.client.ts"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"name": "@stackonward/cli",
|
|
22
22
|
"description": "StackOnward project and resource CLI",
|
|
23
23
|
"type": "npm",
|
|
24
|
-
"version": "^1.
|
|
24
|
+
"version": "^1.3.0"
|
|
25
25
|
},
|
|
26
26
|
"@stackonward/cms-client": {
|
|
27
27
|
"name": "@stackonward/cms-client",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"name": "@stackonward/google-tag-manager-nuxt",
|
|
70
70
|
"description": "Consent-aware Google Tag Manager analytics integration for Nuxt",
|
|
71
71
|
"type": "npm",
|
|
72
|
-
"version": "^0.2.
|
|
72
|
+
"version": "^0.2.2"
|
|
73
73
|
},
|
|
74
74
|
"@stackonward/google-tag-manager": {
|
|
75
75
|
"name": "@stackonward/google-tag-manager",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"name": "@stackonward/nuxt-site-shell",
|
|
112
112
|
"description": "Brand-free Nuxt product-site shell",
|
|
113
113
|
"type": "layer",
|
|
114
|
-
"version": "^0.
|
|
114
|
+
"version": "^0.2.0"
|
|
115
115
|
},
|
|
116
116
|
"@stackonward/onex-cms-client": {
|
|
117
117
|
"name": "@stackonward/onex-cms-client",
|
|
@@ -4,94 +4,139 @@ export default defineAppConfig({
|
|
|
4
4
|
ui: siteUiTheme,
|
|
5
5
|
siteShell: {
|
|
6
6
|
name: "{{projectName}}",
|
|
7
|
-
description
|
|
8
|
-
"A premium product media workspace for generating product images, campaign sets, and short-form ad videos.",
|
|
7
|
+
descriptionKey: "site.description",
|
|
9
8
|
url: "",
|
|
10
9
|
defaultLocale: "en",
|
|
11
10
|
homePath: "/",
|
|
12
11
|
appPath: "/app",
|
|
13
12
|
logoText: "{{projectName}}",
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
primaryActionLabelKey: "actions.start",
|
|
14
|
+
secondaryActionLabelKey: "actions.signIn",
|
|
16
15
|
secondaryActionPath: "/app",
|
|
17
16
|
consent: {
|
|
18
17
|
enabled: true,
|
|
19
|
-
storageKey: "{{projectName}}-consent",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
rejectLabel: "Decline",
|
|
18
|
+
storageKey: "{{projectName}}-analytics-consent-v1",
|
|
19
|
+
policyRevision: "1",
|
|
20
|
+
retentionDays: 180,
|
|
21
|
+
policyPath: "/legal/cookies",
|
|
24
22
|
},
|
|
23
|
+
storageDisclosures: [
|
|
24
|
+
{
|
|
25
|
+
name: "{{projectName}}-analytics-consent-v1",
|
|
26
|
+
category: "necessary",
|
|
27
|
+
purposeKey: "legal.cookies.storage.consentPurpose",
|
|
28
|
+
retentionKey: "legal.cookies.storage.consentRetention",
|
|
29
|
+
providerKey: "legal.cookies.storage.firstParty",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "nuxt-color-mode",
|
|
33
|
+
category: "preferences",
|
|
34
|
+
purposeKey: "legal.cookies.storage.themePurpose",
|
|
35
|
+
retentionKey: "legal.cookies.storage.persistent",
|
|
36
|
+
providerKey: "legal.cookies.storage.firstParty",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "{{projectName}}_locale",
|
|
40
|
+
category: "preferences",
|
|
41
|
+
purposeKey: "legal.cookies.storage.localePurpose",
|
|
42
|
+
retentionKey: "legal.cookies.storage.localeRetention",
|
|
43
|
+
providerKey: "legal.cookies.storage.firstParty",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "_ga, _ga_*",
|
|
47
|
+
category: "analytics",
|
|
48
|
+
purposeKey: "legal.cookies.storage.analyticsPurpose",
|
|
49
|
+
retentionKey: "legal.cookies.storage.analyticsRetention",
|
|
50
|
+
providerKey: "legal.cookies.storage.google",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
25
53
|
navigation: {
|
|
26
54
|
marketing: [
|
|
27
|
-
{
|
|
55
|
+
{ labelKey: "navigation.items.product", to: "/" },
|
|
28
56
|
{
|
|
29
|
-
|
|
57
|
+
labelKey: "navigation.items.solutions",
|
|
30
58
|
children: [
|
|
31
59
|
{
|
|
32
|
-
|
|
60
|
+
labelKey: "navigation.items.workspace",
|
|
33
61
|
to: "/app",
|
|
34
|
-
|
|
62
|
+
descriptionKey: "navigation.descriptions.workspace",
|
|
35
63
|
},
|
|
36
64
|
{
|
|
37
|
-
|
|
65
|
+
labelKey: "navigation.items.designSystem",
|
|
38
66
|
to: "/ui",
|
|
39
|
-
|
|
40
|
-
"Tokens, components, checkout, identity, video, and infinite-scroll examples",
|
|
67
|
+
descriptionKey: "navigation.descriptions.designSystem",
|
|
41
68
|
},
|
|
42
69
|
],
|
|
43
70
|
},
|
|
44
71
|
{
|
|
45
|
-
|
|
72
|
+
labelKey: "navigation.items.resources",
|
|
46
73
|
children: [
|
|
47
74
|
{
|
|
48
|
-
|
|
75
|
+
labelKey: "navigation.items.playbook",
|
|
49
76
|
to: "/blog/creative-playbook",
|
|
50
|
-
|
|
77
|
+
descriptionKey: "navigation.descriptions.playbook",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
labelKey: "navigation.items.privacy",
|
|
81
|
+
to: "/legal/privacy",
|
|
82
|
+
descriptionKey: "navigation.descriptions.privacy",
|
|
51
83
|
},
|
|
52
|
-
{ label: "Privacy", to: "/legal/privacy", description: "Static policy page" },
|
|
53
84
|
],
|
|
54
85
|
},
|
|
55
|
-
{
|
|
56
|
-
{
|
|
86
|
+
{ labelKey: "navigation.items.pricing", to: "/#pricing" },
|
|
87
|
+
{ labelKey: "navigation.items.blog", to: "/blog" },
|
|
57
88
|
],
|
|
58
89
|
app: [
|
|
59
90
|
{
|
|
60
|
-
|
|
91
|
+
labelKey: "navigation.groups.production",
|
|
61
92
|
items: [
|
|
62
|
-
{
|
|
63
|
-
|
|
64
|
-
|
|
93
|
+
{
|
|
94
|
+
labelKey: "navigation.items.workspaceBoard",
|
|
95
|
+
to: "/app",
|
|
96
|
+
icon: "i-lucide-layout-dashboard",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
labelKey: "navigation.items.designSystem",
|
|
100
|
+
to: "/ui",
|
|
101
|
+
icon: "i-lucide-palette",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
labelKey: "navigation.items.contentHub",
|
|
105
|
+
to: "/blog",
|
|
106
|
+
icon: "i-lucide-newspaper",
|
|
107
|
+
},
|
|
65
108
|
],
|
|
66
109
|
},
|
|
67
110
|
],
|
|
68
111
|
footer: [
|
|
69
112
|
{
|
|
70
|
-
|
|
113
|
+
titleKey: "navigation.items.product",
|
|
71
114
|
links: [
|
|
72
|
-
{
|
|
73
|
-
{
|
|
74
|
-
{
|
|
115
|
+
{ labelKey: "navigation.items.overview", to: "/" },
|
|
116
|
+
{ labelKey: "navigation.items.workspaceBoard", to: "/app" },
|
|
117
|
+
{ labelKey: "navigation.items.designSystem", to: "/ui" },
|
|
75
118
|
],
|
|
76
119
|
},
|
|
77
120
|
{
|
|
78
|
-
|
|
121
|
+
titleKey: "navigation.items.resources",
|
|
79
122
|
links: [
|
|
80
|
-
{
|
|
81
|
-
{
|
|
123
|
+
{ labelKey: "navigation.items.contentHub", to: "/blog" },
|
|
124
|
+
{ labelKey: "navigation.items.creativePlaybook", to: "/blog/creative-playbook" },
|
|
82
125
|
],
|
|
83
126
|
},
|
|
84
127
|
{
|
|
85
|
-
|
|
128
|
+
titleKey: "navigation.items.company",
|
|
86
129
|
links: [
|
|
87
|
-
{
|
|
88
|
-
{
|
|
130
|
+
{ labelKey: "navigation.items.terms", to: "/legal/terms" },
|
|
131
|
+
{ labelKey: "navigation.items.privacy", to: "/legal/privacy" },
|
|
132
|
+
{ labelKey: "navigation.items.cookies", to: "/legal/cookies" },
|
|
89
133
|
],
|
|
90
134
|
},
|
|
91
135
|
],
|
|
92
136
|
legal: [
|
|
93
|
-
{
|
|
94
|
-
{
|
|
137
|
+
{ labelKey: "navigation.items.terms", to: "/legal/terms" },
|
|
138
|
+
{ labelKey: "navigation.items.privacy", to: "/legal/privacy" },
|
|
139
|
+
{ labelKey: "navigation.items.cookies", to: "/legal/cookies" },
|
|
95
140
|
],
|
|
96
141
|
social: [],
|
|
97
142
|
},
|