Skip to content

Commit b27075f

Browse files
committed
fix
1 parent cf7661f commit b27075f

File tree

3 files changed

+90
-22
lines changed

3 files changed

+90
-22
lines changed

components/PageMetadata.tsx

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect } from 'react';
1+
import React, { useEffect, useLayoutEffect } from 'react';
22
import { useMatches, useLocation } from 'react-router-dom';
33
import { Cssville } from "cssville-generators/build/cssville";
44

@@ -13,62 +13,74 @@ export const PageMetadata: React.FC<MetadataProps> = ({
1313
}) => {
1414
const matches = useMatches();
1515
const location = useLocation();
16-
17-
useEffect(() => {
18-
// Get the last match which contains the current route's handle
16+
17+
// Function to get metadata from current route
18+
const getMetadata = () => {
1919
const match = matches[matches.length - 1];
2020
let title = defaultTitle;
2121
let description = defaultDescription;
22-
23-
// Extract metadata from the route's handle
22+
2423
if (match && match.handle) {
2524
const handle = match.handle as any;
26-
27-
// For CSS Classes pages, we need to handle the dynamic title
25+
2826
if (handle.category === "CSS Classes" && handle.title === "") {
2927
const parts = location.pathname.split("/");
3028
const className = parts[parts.length - 1];
3129
const generator = Cssville.generators.find(g => g.name === className);
32-
30+
3331
if (generator) {
3432
title = `${generator.name} - Cssville CSS Classes`;
3533
description = `Learn about Cssville's ${generator.name} utility classes.`;
3634
}
3735
} else if (handle.title) {
38-
// For other pages, use the title from the handle
3936
title = handle.title;
4037
if (handle.category !== "Home") {
4138
title += " - Cssville";
4239
}
43-
40+
4441
if (handle.description) {
4542
description = handle.description;
4643
}
4744
}
4845
}
49-
46+
47+
return { title, description };
48+
};
49+
50+
// Update metadata immediately during render
51+
const { title, description } = getMetadata();
52+
53+
// Synchronously update the title as soon as possible
54+
if (typeof document !== 'undefined') {
55+
document.title = title;
56+
}
57+
58+
// Use useLayoutEffect for DOM mutations before browser paint
59+
useLayoutEffect(() => {
60+
const { title, description } = getMetadata();
61+
5062
// Update document head
5163
document.title = title;
52-
64+
5365
// Update meta description
5466
let metaDescription = document.querySelector('meta[name="description"]');
5567
if (metaDescription) {
5668
metaDescription.setAttribute('content', description);
5769
}
58-
70+
5971
// Update Open Graph and Twitter meta tags
6072
const ogTitle = document.querySelector('meta[property="og:title"]');
6173
const ogDescription = document.querySelector('meta[property="og:description"]');
6274
const twitterTitle = document.querySelector('meta[name="twitter:title"]');
6375
const twitterDescription = document.querySelector('meta[name="twitter:description"]');
64-
76+
6577
if (ogTitle) ogTitle.setAttribute('content', title);
6678
if (ogDescription) ogDescription.setAttribute('content', description);
6779
if (twitterTitle) twitterTitle.setAttribute('content', title);
6880
if (twitterDescription) twitterDescription.setAttribute('content', description);
69-
81+
7082
}, [matches, location.pathname, defaultTitle, defaultDescription]);
71-
83+
7284
// This component doesn't render anything
7385
return null;
74-
};
86+
};

index.tsx

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,76 @@ import hljs from 'highlight.js';
44
import "cssville-ui/cssville-ui.bundle.css"
55
import "cssville/cssville.css";
66
import "./site.css";
7-
import { createBrowserRouter, RouterProvider } from "react-router-dom";
7+
import { createBrowserRouter, RouterProvider, matchRoutes } from "react-router-dom";
88
import { Routes } from "./data/pagesData";
99
import { PageMetadata } from "./components/PageMetadata";
10+
import { Cssville } from "cssville-generators/build/cssville";
1011

12+
// Initialize metadata as early as possible based on current URL
13+
function initializeMetadata() {
14+
const pathname = window.location.pathname;
15+
16+
// Find matching route
17+
const matches = matchRoutes(Routes, pathname);
18+
19+
if (matches && matches.length > 0) {
20+
const match = matches[matches.length - 1];
21+
const handle = match.route.handle as any;
22+
23+
if (handle) {
24+
let title = handle.title || "Cssville - The most simple utility-first CSS framework";
25+
let description = handle.description || "Enhance your UI with ready-to-use CSS utility classes";
26+
27+
// Handle CSS Classes pages with dynamic titles
28+
if (handle.category === "CSS Classes" && handle.title === "") {
29+
const parts = pathname.split("/");
30+
const className = parts[parts.length - 1];
31+
const generator = Cssville.generators.find(g => g.name === className);
32+
33+
if (generator) {
34+
title = `${generator.name} - Cssville CSS Classes`;
35+
description = `Learn about Cssville's ${generator.name} utility classes.`;
36+
}
37+
} else if (handle.title && handle.category !== "Home") {
38+
title += " - Cssville";
39+
}
40+
41+
// Update document head immediately
42+
document.title = title;
43+
44+
// Update meta tags
45+
const metaDescription = document.querySelector('meta[name="description"]');
46+
if (metaDescription) {
47+
metaDescription.setAttribute('content', description);
48+
}
49+
50+
const ogTitle = document.querySelector('meta[property="og:title"]');
51+
const ogDescription = document.querySelector('meta[property="og:description"]');
52+
const twitterTitle = document.querySelector('meta[name="twitter:title"]');
53+
const twitterDescription = document.querySelector('meta[name="twitter:description"]');
54+
55+
if (ogTitle) ogTitle.setAttribute('content', title);
56+
if (ogDescription) ogDescription.setAttribute('content', description);
57+
if (twitterTitle) twitterTitle.setAttribute('content', title);
58+
if (twitterDescription) twitterDescription.setAttribute('content', description);
59+
}
60+
}
61+
}
1162

1263
const router = createBrowserRouter(Routes);
1364

1465
function docReady(fn: () => void) {
1566
// see if DOM is already available
1667
if (document.readyState === "complete" || document.readyState === "interactive") {
68+
// Initialize metadata before rendering React app
69+
initializeMetadata();
1770
// call on next available tick
1871
setTimeout(fn, 1);
1972
} else {
20-
document.addEventListener("DOMContentLoaded", fn);
73+
document.addEventListener("DOMContentLoaded", () => {
74+
initializeMetadata();
75+
fn();
76+
});
2177
}
2278
}
2379

0 commit comments

Comments
 (0)