@djangocfg/layouts 1.4.23 → 1.4.24
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/layouts",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.24",
|
|
4
4
|
"description": "Pre-built dashboard layouts, authentication pages, and admin templates for Next.js applications with Tailwind CSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"layouts",
|
|
@@ -85,9 +85,9 @@
|
|
|
85
85
|
"check": "tsc --noEmit"
|
|
86
86
|
},
|
|
87
87
|
"peerDependencies": {
|
|
88
|
-
"@djangocfg/api": "^1.4.
|
|
89
|
-
"@djangocfg/og-image": "^1.4.
|
|
90
|
-
"@djangocfg/ui": "^1.4.
|
|
88
|
+
"@djangocfg/api": "^1.4.24",
|
|
89
|
+
"@djangocfg/og-image": "^1.4.24",
|
|
90
|
+
"@djangocfg/ui": "^1.4.24",
|
|
91
91
|
"@hookform/resolvers": "^5.2.0",
|
|
92
92
|
"consola": "^3.4.2",
|
|
93
93
|
"lucide-react": "^0.468.0",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"vidstack": "0.6.15"
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
|
-
"@djangocfg/typescript-config": "^1.4.
|
|
112
|
+
"@djangocfg/typescript-config": "^1.4.24",
|
|
113
113
|
"@types/node": "^24.7.2",
|
|
114
114
|
"@types/react": "19.2.2",
|
|
115
115
|
"@types/react-dom": "19.2.1",
|
|
@@ -15,6 +15,48 @@ interface SeoProps {
|
|
|
15
15
|
siteUrl?: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Check if URL is absolute (starts with http:// or https://)
|
|
20
|
+
*/
|
|
21
|
+
function isAbsoluteUrl(url: string): boolean {
|
|
22
|
+
return /^https?:\/\//i.test(url);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get absolute site URL with smart fallbacks
|
|
27
|
+
*
|
|
28
|
+
* Priority:
|
|
29
|
+
* 1. Provided siteUrl (if absolute)
|
|
30
|
+
* 2. NEXT_PUBLIC_SITE_URL env var
|
|
31
|
+
* 3. NEXT_PUBLIC_VERCEL_URL (for Vercel deployments)
|
|
32
|
+
* 4. window.location.origin (client-side only)
|
|
33
|
+
*/
|
|
34
|
+
function getAbsoluteSiteUrl(siteUrl?: string): string | null {
|
|
35
|
+
// 1. Check if provided siteUrl is already absolute
|
|
36
|
+
if (siteUrl && isAbsoluteUrl(siteUrl)) {
|
|
37
|
+
return siteUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 2. Check NEXT_PUBLIC_SITE_URL env var
|
|
41
|
+
const envSiteUrl = process.env.NEXT_PUBLIC_SITE_URL;
|
|
42
|
+
if (envSiteUrl && isAbsoluteUrl(envSiteUrl)) {
|
|
43
|
+
return envSiteUrl.replace(/\/$/, '');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 3. Check Vercel URL (auto-set by Vercel)
|
|
47
|
+
const vercelUrl = process.env.NEXT_PUBLIC_VERCEL_URL;
|
|
48
|
+
if (vercelUrl) {
|
|
49
|
+
return `https://${vercelUrl}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 4. Client-side fallback (not available during SSR)
|
|
53
|
+
if (typeof window !== 'undefined') {
|
|
54
|
+
return window.location.origin;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
18
60
|
export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
|
|
19
61
|
const {
|
|
20
62
|
title,
|
|
@@ -29,6 +71,9 @@ export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
|
|
|
29
71
|
const ogTitle = ogImage?.title || title;
|
|
30
72
|
const ogSubtitle = ogImage?.subtitle || description;
|
|
31
73
|
|
|
74
|
+
// Get absolute site URL with smart fallbacks
|
|
75
|
+
const absoluteSiteUrl = getAbsoluteSiteUrl(siteUrl);
|
|
76
|
+
|
|
32
77
|
// Generate OG image URL using @djangocfg/og-image utilities
|
|
33
78
|
const ogImageUrl = ogImage
|
|
34
79
|
? generateOgImageUrl('/api/og', {
|
|
@@ -38,35 +83,42 @@ export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
|
|
|
38
83
|
})
|
|
39
84
|
: null;
|
|
40
85
|
|
|
41
|
-
// Make absolute URL if
|
|
42
|
-
const absoluteOgImageUrl = ogImageUrl &&
|
|
86
|
+
// Make absolute URL - only render og:image if we have absolute site URL
|
|
87
|
+
const absoluteOgImageUrl = ogImageUrl && absoluteSiteUrl
|
|
88
|
+
? `${absoluteSiteUrl}${ogImageUrl}`
|
|
89
|
+
: null;
|
|
43
90
|
|
|
44
91
|
return (
|
|
45
92
|
<Head>
|
|
46
93
|
<title>{title}</title>
|
|
47
94
|
<meta name="description" content={description} />
|
|
48
95
|
{keywords && <meta name="keywords" content={keywords} />}
|
|
49
|
-
|
|
96
|
+
|
|
50
97
|
{/* Favicon */}
|
|
51
98
|
<link rel="icon" type="image/png" href={icons?.logo192 || '/favicon.png'} />
|
|
52
|
-
|
|
99
|
+
|
|
53
100
|
{/* Open Graph */}
|
|
54
101
|
<meta property="og:title" content={openGraph?.title || ogTitle} />
|
|
55
102
|
<meta property="og:description" content={openGraph?.description || ogSubtitle} />
|
|
56
103
|
<meta property="og:type" content={openGraph?.type || 'website'} />
|
|
57
104
|
|
|
105
|
+
{/* Canonical URL */}
|
|
106
|
+
{absoluteSiteUrl && (
|
|
107
|
+
<meta property="og:url" content={absoluteSiteUrl} />
|
|
108
|
+
)}
|
|
109
|
+
|
|
58
110
|
{/* Site Name */}
|
|
59
111
|
{(openGraph?.siteName || pageConfig.projectName) && (
|
|
60
112
|
<meta property="og:site_name" content={openGraph?.siteName || pageConfig.projectName} />
|
|
61
113
|
)}
|
|
62
|
-
|
|
114
|
+
|
|
63
115
|
{/* Twitter */}
|
|
64
116
|
<meta name="twitter:card" content={twitter?.card || 'summary_large_image'} />
|
|
65
117
|
<meta name="twitter:title" content={twitter?.title || ogTitle} />
|
|
66
118
|
<meta name="twitter:description" content={twitter?.description || ogSubtitle} />
|
|
67
119
|
{twitter?.site && <meta name="twitter:site" content={twitter.site} />}
|
|
68
120
|
{twitter?.creator && <meta name="twitter:creator" content={twitter.creator} />}
|
|
69
|
-
|
|
121
|
+
|
|
70
122
|
{/* OG Images */}
|
|
71
123
|
{openGraph?.images?.length ? (
|
|
72
124
|
openGraph.images.map((image, index) => (
|
|
@@ -94,7 +146,7 @@ export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
|
|
|
94
146
|
) : absoluteOgImageUrl ? (
|
|
95
147
|
<meta name="twitter:image" content={absoluteOgImageUrl} />
|
|
96
148
|
) : null}
|
|
97
|
-
|
|
149
|
+
|
|
98
150
|
{/* JSON-LD */}
|
|
99
151
|
{jsonLd && (
|
|
100
152
|
<script
|
|
@@ -106,4 +158,4 @@ export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
|
|
|
106
158
|
)}
|
|
107
159
|
</Head>
|
|
108
160
|
);
|
|
109
|
-
}
|
|
161
|
+
}
|