@djangocfg/layouts 1.4.24 → 1.4.26

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.24",
3
+ "version": "1.4.26",
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.24",
89
- "@djangocfg/og-image": "^1.4.24",
90
- "@djangocfg/ui": "^1.4.24",
88
+ "@djangocfg/api": "^1.4.26",
89
+ "@djangocfg/og-image": "^1.4.26",
90
+ "@djangocfg/ui": "^1.4.26",
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.24",
112
+ "@djangocfg/typescript-config": "^1.4.26",
113
113
  "@types/node": "^24.7.2",
114
114
  "@types/react": "19.2.2",
115
115
  "@types/react-dom": "19.2.1",
@@ -1,5 +1,6 @@
1
1
  import { Fragment } from 'react';
2
2
  import Head from 'next/head';
3
+ import { useRouter } from 'next/router';
3
4
  import { generateOgImageUrl } from '@djangocfg/og-image/utils';
4
5
 
5
6
  import { PageConfig } from '../../../types/pageConfig';
@@ -13,6 +14,8 @@ interface SeoProps {
13
14
  logoVector?: string;
14
15
  };
15
16
  siteUrl?: string;
17
+ /** Override canonical URL (defaults to current page URL) */
18
+ canonicalUrl?: string;
16
19
  }
17
20
 
18
21
  /**
@@ -28,8 +31,7 @@ function isAbsoluteUrl(url: string): boolean {
28
31
  * Priority:
29
32
  * 1. Provided siteUrl (if absolute)
30
33
  * 2. NEXT_PUBLIC_SITE_URL env var
31
- * 3. NEXT_PUBLIC_VERCEL_URL (for Vercel deployments)
32
- * 4. window.location.origin (client-side only)
34
+ * 3. window.location.origin (client-side only)
33
35
  */
34
36
  function getAbsoluteSiteUrl(siteUrl?: string): string | null {
35
37
  // 1. Check if provided siteUrl is already absolute
@@ -43,13 +45,7 @@ function getAbsoluteSiteUrl(siteUrl?: string): string | null {
43
45
  return envSiteUrl.replace(/\/$/, '');
44
46
  }
45
47
 
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)
48
+ // 3. Client-side fallback (not available during SSR)
53
49
  if (typeof window !== 'undefined') {
54
50
  return window.location.origin;
55
51
  }
@@ -57,7 +53,9 @@ function getAbsoluteSiteUrl(siteUrl?: string): string | null {
57
53
  return null;
58
54
  }
59
55
 
60
- export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
56
+ export default function Seo({ pageConfig, icons, siteUrl, canonicalUrl }: SeoProps) {
57
+ const router = useRouter();
58
+
61
59
  const {
62
60
  title,
63
61
  description,
@@ -74,6 +72,11 @@ export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
74
72
  // Get absolute site URL with smart fallbacks
75
73
  const absoluteSiteUrl = getAbsoluteSiteUrl(siteUrl);
76
74
 
75
+ // Build canonical URL: custom > siteUrl + current path
76
+ const currentPath = router.asPath.split('?')[0]; // Remove query params
77
+ const absoluteCanonicalUrl = canonicalUrl
78
+ || (absoluteSiteUrl ? `${absoluteSiteUrl}${currentPath}` : null);
79
+
77
80
  // Generate OG image URL using @djangocfg/og-image utilities
78
81
  const ogImageUrl = ogImage
79
82
  ? generateOgImageUrl('/api/og', {
@@ -97,14 +100,19 @@ export default function Seo({ pageConfig, icons, siteUrl }: SeoProps) {
97
100
  {/* Favicon */}
98
101
  <link rel="icon" type="image/png" href={icons?.logo192 || '/favicon.png'} />
99
102
 
103
+ {/* Canonical URL - important for SEO */}
104
+ {absoluteCanonicalUrl && (
105
+ <link rel="canonical" href={absoluteCanonicalUrl} />
106
+ )}
107
+
100
108
  {/* Open Graph */}
101
109
  <meta property="og:title" content={openGraph?.title || ogTitle} />
102
110
  <meta property="og:description" content={openGraph?.description || ogSubtitle} />
103
111
  <meta property="og:type" content={openGraph?.type || 'website'} />
104
112
 
105
- {/* Canonical URL */}
106
- {absoluteSiteUrl && (
107
- <meta property="og:url" content={absoluteSiteUrl} />
113
+ {/* OG Canonical URL */}
114
+ {absoluteCanonicalUrl && (
115
+ <meta property="og:url" content={absoluteCanonicalUrl} />
108
116
  )}
109
117
 
110
118
  {/* Site Name */}