@stackonward/nuxt-site-shell 0.0.1

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.
@@ -0,0 +1,79 @@
1
+ interface MarketingNavigationItem {
2
+ label: string;
3
+ to?: string;
4
+ external?: boolean;
5
+ description?: string;
6
+ children?: MarketingNavigationItem[];
7
+ }
8
+ interface AppNavigationItem {
9
+ label: string;
10
+ to: string;
11
+ icon?: string;
12
+ badge?: string;
13
+ }
14
+ interface NavigationGroup {
15
+ label?: string;
16
+ items: AppNavigationItem[];
17
+ }
18
+ interface FooterGroup {
19
+ title: string;
20
+ links: MarketingNavigationItem[];
21
+ }
22
+ interface LegalLink {
23
+ label: string;
24
+ to: string;
25
+ }
26
+ interface SocialLink {
27
+ label: string;
28
+ href: string;
29
+ }
30
+ interface ContentListItem {
31
+ title: string;
32
+ description?: string;
33
+ to: string;
34
+ category?: string;
35
+ date?: string;
36
+ author?: string;
37
+ }
38
+ interface ContentArticle {
39
+ title: string;
40
+ description?: string;
41
+ category?: string;
42
+ author?: string;
43
+ date?: string;
44
+ updatedAt?: string;
45
+ }
46
+ interface SiteShellConfig {
47
+ name: string;
48
+ description: string;
49
+ url: string;
50
+ defaultLocale: string;
51
+ homePath: string;
52
+ appPath: string;
53
+ logoText: string;
54
+ primaryActionLabel: string;
55
+ secondaryActionLabel: string;
56
+ secondaryActionPath: string;
57
+ consent: {
58
+ enabled: boolean;
59
+ storageKey: string;
60
+ message: string;
61
+ acceptLabel: string;
62
+ rejectLabel: string;
63
+ };
64
+ navigation: {
65
+ marketing: MarketingNavigationItem[];
66
+ app: NavigationGroup[];
67
+ footer: FooterGroup[];
68
+ legal: LegalLink[];
69
+ social: SocialLink[];
70
+ };
71
+ content: {
72
+ blogPath: string;
73
+ authorPath: string;
74
+ previewPath: string;
75
+ sitemapSourcePath: string;
76
+ };
77
+ }
78
+
79
+ export type { AppNavigationItem, ContentArticle, ContentListItem, FooterGroup, LegalLink, MarketingNavigationItem, NavigationGroup, SiteShellConfig, SocialLink };
@@ -0,0 +1,79 @@
1
+ interface MarketingNavigationItem {
2
+ label: string;
3
+ to?: string;
4
+ external?: boolean;
5
+ description?: string;
6
+ children?: MarketingNavigationItem[];
7
+ }
8
+ interface AppNavigationItem {
9
+ label: string;
10
+ to: string;
11
+ icon?: string;
12
+ badge?: string;
13
+ }
14
+ interface NavigationGroup {
15
+ label?: string;
16
+ items: AppNavigationItem[];
17
+ }
18
+ interface FooterGroup {
19
+ title: string;
20
+ links: MarketingNavigationItem[];
21
+ }
22
+ interface LegalLink {
23
+ label: string;
24
+ to: string;
25
+ }
26
+ interface SocialLink {
27
+ label: string;
28
+ href: string;
29
+ }
30
+ interface ContentListItem {
31
+ title: string;
32
+ description?: string;
33
+ to: string;
34
+ category?: string;
35
+ date?: string;
36
+ author?: string;
37
+ }
38
+ interface ContentArticle {
39
+ title: string;
40
+ description?: string;
41
+ category?: string;
42
+ author?: string;
43
+ date?: string;
44
+ updatedAt?: string;
45
+ }
46
+ interface SiteShellConfig {
47
+ name: string;
48
+ description: string;
49
+ url: string;
50
+ defaultLocale: string;
51
+ homePath: string;
52
+ appPath: string;
53
+ logoText: string;
54
+ primaryActionLabel: string;
55
+ secondaryActionLabel: string;
56
+ secondaryActionPath: string;
57
+ consent: {
58
+ enabled: boolean;
59
+ storageKey: string;
60
+ message: string;
61
+ acceptLabel: string;
62
+ rejectLabel: string;
63
+ };
64
+ navigation: {
65
+ marketing: MarketingNavigationItem[];
66
+ app: NavigationGroup[];
67
+ footer: FooterGroup[];
68
+ legal: LegalLink[];
69
+ social: SocialLink[];
70
+ };
71
+ content: {
72
+ blogPath: string;
73
+ authorPath: string;
74
+ previewPath: string;
75
+ sitemapSourcePath: string;
76
+ };
77
+ }
78
+
79
+ export type { AppNavigationItem, ContentArticle, ContentListItem, FooterGroup, LegalLink, MarketingNavigationItem, NavigationGroup, SiteShellConfig, SocialLink };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+
package/nuxt.config.ts ADDED
@@ -0,0 +1,215 @@
1
+ import { defineNuxtConfig } from "nuxt/config";
2
+
3
+ const APP_NO_CACHE_ROUTE_RULE = {
4
+ swr: false as const,
5
+ cache: false as const,
6
+ headers: {
7
+ "Cache-Control": "no-cache, no-store, must-revalidate",
8
+ },
9
+ };
10
+
11
+ const siteUrl = process.env.NUXT_PUBLIC_SITE_URL || "https://example.com";
12
+ const siteName = process.env.NUXT_PUBLIC_SITE_NAME || "Product Platform";
13
+ const siteDescription =
14
+ process.env.NUXT_PUBLIC_SITE_DESCRIPTION || "Reusable Nuxt product-site foundation.";
15
+ const siteEnv = process.env.NUXT_PUBLIC_SITE_ENV || process.env.NODE_ENV || "development";
16
+ const isProduction = siteEnv === "production";
17
+
18
+ export default defineNuxtConfig({
19
+ extends: ["@stackonward/nuxt-layer-base"],
20
+ future: { compatibilityVersion: 4 },
21
+ modules: [
22
+ "@nuxt/ui",
23
+ "@vueuse/nuxt",
24
+ "@pinia/colada-nuxt",
25
+ "@nuxt/image",
26
+ "@nuxtjs/seo",
27
+ "@nuxt/scripts",
28
+ ],
29
+ devtools: {
30
+ enabled: !isProduction,
31
+ timeline: {
32
+ enabled: false,
33
+ },
34
+ },
35
+ app: {
36
+ head: {
37
+ titleTemplate: `%s | ${siteName}`,
38
+ meta: [
39
+ { charset: "utf-8" },
40
+ { name: "viewport", content: "width=device-width, initial-scale=1.0" },
41
+ { "http-equiv": "x-ua-compatible", content: "ie=edge" },
42
+ { name: "renderer", content: "webkit" },
43
+ { name: "format-detection", content: "telephone=no" },
44
+ ...(!isProduction ? [{ name: "robots", content: "noindex,nofollow" }] : []),
45
+ ],
46
+ link: [
47
+ { rel: "icon", type: "image/svg+xml", href: "/favicon.svg" },
48
+ { rel: "dns-prefetch", href: "https://www.googletagmanager.com" },
49
+ { rel: "dns-prefetch", href: "https://www.google-analytics.com" },
50
+ { rel: "dns-prefetch", href: "https://accounts.google.com" },
51
+ { rel: "dns-prefetch", href: "https://www.youtube.com" },
52
+ { rel: "dns-prefetch", href: "https://i.ytimg.com" },
53
+ ],
54
+ },
55
+ },
56
+ site: {
57
+ url: siteUrl,
58
+ name: siteName,
59
+ description: siteDescription,
60
+ defaultLocale: "en",
61
+ trailingSlash: false,
62
+ indexable: isProduction,
63
+ },
64
+ colorMode: {
65
+ preference: "light",
66
+ fallback: "light",
67
+ storageKey: "nuxt-color-mode",
68
+ storage: "localStorage",
69
+ classSuffix: "",
70
+ },
71
+ runtimeConfig: {
72
+ public: {
73
+ app: {
74
+ version: process.env.NUXT_PUBLIC_APP_VERSION || process.env.npm_package_version || "0.0.1",
75
+ },
76
+ api: {
77
+ timeout: Number.parseInt(process.env.NUXT_PUBLIC_API_TIMEOUT || "30000", 10),
78
+ },
79
+ site: {
80
+ url: siteUrl,
81
+ env: siteEnv,
82
+ name: siteName,
83
+ description: siteDescription,
84
+ },
85
+ analytics: {
86
+ enabled: process.env.NUXT_PUBLIC_ANALYTICS_ENABLED === "true",
87
+ debug: process.env.NUXT_PUBLIC_ANALYTICS_DEBUG === "true",
88
+ requireConsent: process.env.NUXT_PUBLIC_ANALYTICS_REQUIRE_CONSENT !== "false",
89
+ pageTracking: process.env.NUXT_PUBLIC_ANALYTICS_PAGE_TRACKING !== "false",
90
+ dataLayerName: process.env.NUXT_PUBLIC_ANALYTICS_DATA_LAYER || "dataLayer",
91
+ gaId: process.env.NUXT_PUBLIC_GA_ID || "",
92
+ gtmId: process.env.NUXT_PUBLIC_GTM_ID || "",
93
+ },
94
+ identity: {
95
+ google: {
96
+ enabled: process.env.NUXT_PUBLIC_GOOGLE_IDENTITY_ENABLED === "true",
97
+ clientId: process.env.NUXT_PUBLIC_GOOGLE_CLIENT_ID || "",
98
+ credentialEndpoint: process.env.NUXT_PUBLIC_GOOGLE_CREDENTIAL_ENDPOINT || "",
99
+ oneTap: process.env.NUXT_PUBLIC_GOOGLE_ONE_TAP === "true",
100
+ autoPrompt: process.env.NUXT_PUBLIC_GOOGLE_AUTO_PROMPT === "true",
101
+ },
102
+ },
103
+ checkout: {
104
+ url: process.env.NUXT_PUBLIC_CHECKOUT_URL || "",
105
+ resultParam: process.env.NUXT_PUBLIC_CHECKOUT_RESULT_PARAM || "checkout_status",
106
+ },
107
+ media: {
108
+ youtube: {
109
+ privacyEnhanced: process.env.NUXT_PUBLIC_YOUTUBE_PRIVACY_ENHANCED !== "false",
110
+ },
111
+ },
112
+ },
113
+ },
114
+ ui: {
115
+ fonts: false,
116
+ theme: {
117
+ colors: ["primary", "secondary", "success", "info", "warning", "error", "neutral"],
118
+ },
119
+ },
120
+ nitro: {
121
+ experimental: {
122
+ wasm: true,
123
+ },
124
+ esbuild: {
125
+ options: {
126
+ target: "es2022",
127
+ },
128
+ },
129
+ compressPublicAssets: {
130
+ gzip: true,
131
+ brotli: true,
132
+ },
133
+ prerender: {
134
+ crawlLinks: false,
135
+ failOnError: false,
136
+ ignore: ["/api/**", "/app/**"],
137
+ },
138
+ routeRules: {
139
+ "/_nuxt/**": {
140
+ headers: {
141
+ "Cache-Control": "public, max-age=31536000, immutable",
142
+ },
143
+ },
144
+ "/api/**": APP_NO_CACHE_ROUTE_RULE,
145
+ "/app/**": APP_NO_CACHE_ROUTE_RULE,
146
+ "/checkout/**": APP_NO_CACHE_ROUTE_RULE,
147
+ "/sitemap.xml": { swr: 3600 },
148
+ "/sitemap_index.xml": { swr: 3600 },
149
+ "/__sitemap__/**": { swr: 3600 },
150
+ },
151
+ },
152
+ vite: {
153
+ define: {
154
+ global: "globalThis",
155
+ },
156
+ optimizeDeps: {
157
+ include: ["vue", "vue-router", "@vueuse/core", "vue-i18n"],
158
+ },
159
+ },
160
+ typescript: {
161
+ strict: true,
162
+ },
163
+ experimental: {
164
+ asyncEntry: isProduction,
165
+ payloadExtraction: true,
166
+ renderJsonPayloads: true,
167
+ componentIslands: true,
168
+ },
169
+ image: {
170
+ provider: "none",
171
+ },
172
+ icon: {
173
+ mode: "css",
174
+ serverBundle: "auto",
175
+ collections: ["lucide"],
176
+ fetchTimeout: 3000,
177
+ },
178
+ ogImage: {
179
+ enabled: process.env.NUXT_PUBLIC_OG_IMAGE_ENABLED === "true",
180
+ defaults: {
181
+ width: 1200,
182
+ height: 630,
183
+ extension: "png",
184
+ },
185
+ },
186
+ robots: isProduction
187
+ ? {
188
+ allow: ["/"],
189
+ sitemap: `${siteUrl}/sitemap.xml`,
190
+ }
191
+ : {
192
+ disallow: ["/"],
193
+ },
194
+ schemaOrg: {
195
+ enabled: process.env.NUXT_PUBLIC_SCHEMA_ORG_ENABLED === "true",
196
+ identity: {
197
+ type: "Organization",
198
+ name: siteName,
199
+ logo: "/logo.svg",
200
+ },
201
+ },
202
+ seo: {
203
+ meta: {
204
+ twitterCard: "summary_large_image",
205
+ ogImage: "/og-default.jpg",
206
+ },
207
+ },
208
+ sitemap: {
209
+ enabled: isProduction,
210
+ defaults: {
211
+ changefreq: "daily",
212
+ priority: 0.8,
213
+ },
214
+ },
215
+ });
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@stackonward/nuxt-site-shell",
3
+ "version": "0.0.1",
4
+ "description": "Brand-free Nuxt product-site platform layer for modules, runtime config, SEO and theme seams",
5
+ "type": "module",
6
+ "main": "./nuxt.config.ts",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": "./nuxt.config.ts",
10
+ "./runtime": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "src",
18
+ "public",
19
+ "nuxt.config.ts"
20
+ ],
21
+ "sideEffects": [
22
+ "./app/assets/css/*.css"
23
+ ],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/1yhy/stackonward.git",
30
+ "directory": "packages/nuxt/site-shell"
31
+ },
32
+ "keywords": [
33
+ "nuxt",
34
+ "nuxt-layer",
35
+ "site-shell",
36
+ "marketing",
37
+ "app-shell",
38
+ "content-shell"
39
+ ],
40
+ "license": "MIT",
41
+ "peerDependencies": {
42
+ "@iconify-json/lucide": ">=1.2.0",
43
+ "@stackonward/nuxt-layer-base": "^0.0.1",
44
+ "@nuxt/image": ">=2.0.0 <3",
45
+ "@nuxt/scripts": ">=1.3.0 <2",
46
+ "@nuxt/ui": ">=4.9.0 <5",
47
+ "@nuxtjs/seo": ">=5.3.0 <6",
48
+ "@pinia/colada-nuxt": ">=1.0.0 <2",
49
+ "@vueuse/nuxt": ">=14.0.0 <15",
50
+ "nuxt": ">=3.15.0",
51
+ "pinia": ">=3.0.4 <4",
52
+ "tailwindcss": ">=4.0.0 <5",
53
+ "unhead": ">=3.1.7 <4",
54
+ "vue": "^3.5.0"
55
+ },
56
+ "devDependencies": {
57
+ "@iconify-json/lucide": "^1.2.116",
58
+ "@nuxt/image": "^2.0.0",
59
+ "@nuxt/kit": "^4.4.8",
60
+ "@nuxt/scripts": "^1.3.0",
61
+ "@nuxt/ui": "^4.9.0",
62
+ "@nuxtjs/seo": "^5.3.2",
63
+ "@pinia/colada-nuxt": "^1.0.1",
64
+ "@vueuse/nuxt": "^14.3.0",
65
+ "nuxt": "^4.4.8",
66
+ "pinia": "^3.0.4",
67
+ "tailwindcss": "^4.3.2",
68
+ "typescript": "^5.7.0",
69
+ "unhead": "^3.1.7",
70
+ "unbuild": "^3.5.0",
71
+ "vue": "^3.5.0",
72
+ "@stackonward/nuxt-layer-base": "0.0.1"
73
+ },
74
+ "scripts": {
75
+ "build": "unbuild",
76
+ "typecheck": "tsc --noEmit"
77
+ }
78
+ }
Binary file
Binary file
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Product platform">
2
+ <rect width="64" height="64" rx="14" fill="#a86550" />
3
+ <path d="M18 20h18c7.7 0 13 4.9 13 12s-5.3 12-13 12H18V20Zm11 8v8h7c2.7 0 4.5-1.6 4.5-4s-1.8-4-4.5-4h-7Z" fill="#ffffff" />
4
+ <path d="M14 48h36v4H14v-4Z" fill="#111827" />
5
+ </svg>
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 64" role="img" aria-label="Product platform">
2
+ <rect x="0" y="8" width="48" height="48" rx="12" fill="#a86550" />
3
+ <path d="M13 20h15c7.4 0 12.5 4.8 12.5 12S35.4 44 28 44H13V20Zm9 8v8h6c2.5 0 4-1.6 4-4s-1.5-4-4-4h-6Z" fill="#ffffff" />
4
+ <path d="M10 50h34v4H10v-4Z" fill="#111827" />
5
+ <path d="M68 23h86v7H68v-7Zm0 13h132v7H68v-7Z" fill="#111827" />
6
+ </svg>
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ export type {
2
+ AppNavigationItem,
3
+ ContentArticle,
4
+ ContentListItem,
5
+ FooterGroup,
6
+ LegalLink,
7
+ MarketingNavigationItem,
8
+ NavigationGroup,
9
+ SiteShellConfig,
10
+ SocialLink,
11
+ } from "./types.js";
package/src/types.ts ADDED
@@ -0,0 +1,85 @@
1
+ export interface MarketingNavigationItem {
2
+ label: string;
3
+ to?: string;
4
+ external?: boolean;
5
+ description?: string;
6
+ children?: MarketingNavigationItem[];
7
+ }
8
+
9
+ export interface AppNavigationItem {
10
+ label: string;
11
+ to: string;
12
+ icon?: string;
13
+ badge?: string;
14
+ }
15
+
16
+ export interface NavigationGroup {
17
+ label?: string;
18
+ items: AppNavigationItem[];
19
+ }
20
+
21
+ export interface FooterGroup {
22
+ title: string;
23
+ links: MarketingNavigationItem[];
24
+ }
25
+
26
+ export interface LegalLink {
27
+ label: string;
28
+ to: string;
29
+ }
30
+
31
+ export interface SocialLink {
32
+ label: string;
33
+ href: string;
34
+ }
35
+
36
+ export interface ContentListItem {
37
+ title: string;
38
+ description?: string;
39
+ to: string;
40
+ category?: string;
41
+ date?: string;
42
+ author?: string;
43
+ }
44
+
45
+ export interface ContentArticle {
46
+ title: string;
47
+ description?: string;
48
+ category?: string;
49
+ author?: string;
50
+ date?: string;
51
+ updatedAt?: string;
52
+ }
53
+
54
+ export interface SiteShellConfig {
55
+ name: string;
56
+ description: string;
57
+ url: string;
58
+ defaultLocale: string;
59
+ homePath: string;
60
+ appPath: string;
61
+ logoText: string;
62
+ primaryActionLabel: string;
63
+ secondaryActionLabel: string;
64
+ secondaryActionPath: string;
65
+ consent: {
66
+ enabled: boolean;
67
+ storageKey: string;
68
+ message: string;
69
+ acceptLabel: string;
70
+ rejectLabel: string;
71
+ };
72
+ navigation: {
73
+ marketing: MarketingNavigationItem[];
74
+ app: NavigationGroup[];
75
+ footer: FooterGroup[];
76
+ legal: LegalLink[];
77
+ social: SocialLink[];
78
+ };
79
+ content: {
80
+ blogPath: string;
81
+ authorPath: string;
82
+ previewPath: string;
83
+ sitemapSourcePath: string;
84
+ };
85
+ }