Commitfa880f2unknown_key
fix(jsx): inline <style> + <script> use dangerouslySetInnerHTML
fix(jsx): inline <style> + <script> use dangerouslySetInnerHTML
THE actual root cause user has been seeing all day. Hono JSX HTML-escapes
content inside <style>{css}</style> and <script>{js}</script> blocks.
Every quoted font name in CSS ('Segoe UI', 'Inter Tight', 'Helvetica
Neue') and every JS string literal ('serviceWorker', '/sw.js', etc.)
had apostrophes turned into ' entities.
Per HTML5, <style> and <script> are 'raw text' elements — entities are
NOT decoded by the browser inside them. So the CSS parser saw
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', ...
which is invalid CSS, threw out the entire declaration, and the browser
fell back to its UA default font. On Safari/iPad that default is a serif
typeface — explaining 'looks 80s, looks like Times New Roman, why is
nothing my CSS is applying.'
Same bug on every inline script: pwaRegisterScript, navScript (cmdk
palette), versionPollerScript, themeInitScript — none of them were
parsing because their string literals had escaped apostrophes ('''
is a syntax error in JS).
Fix: every <style>{x}</style> -> <style dangerouslySetInnerHTML={{__html: x}} />
every <script>{x}</script> -> <script dangerouslySetInnerHTML={{__html: x}} />
Files touched: layout.tsx (3 styles + 4 scripts), landing.tsx (1 style),
marketing.tsx (3 styles).
After this lands: every browser sees real CSS + real JS. Fonts load
properly. Animations work. Theme toggle works. CmdK works. Version
poller works. The site stops looking like 1985.3 files changed+11−11fa880f24cd523e6572af8794edc7cb82241a646e
3 changed files+11−11
Modifiedsrc/routes/marketing.tsx+3−3View fileUnifiedSplit
@@ -31,7 +31,7 @@ marketing.get("/pricing", (c) => {
3131
3232const PricingPage: FC = () => (
3333 <>
34 <style>{pricingCss}</style>
34 <style dangerouslySetInnerHTML={{ __html: pricingCss }} />
3535 <div class="mkt-root">
3636 <header class="mkt-hero">
3737 <div class="eyebrow">Pricing</div>
@@ -253,7 +253,7 @@ marketing.get("/features", (c) => {
253253
254254const FeaturesPage: FC = () => (
255255 <>
256 <style>{featuresCss}</style>
256 <style dangerouslySetInnerHTML={{ __html: featuresCss }} />
257257 <div class="mkt-root">
258258 <header class="mkt-hero">
259259 <div class="eyebrow">Features</div>
@@ -503,7 +503,7 @@ marketing.get("/about", (c) => {
503503
504504const AboutPage: FC = () => (
505505 <>
506 <style>{aboutCss}</style>
506 <style dangerouslySetInnerHTML={{ __html: aboutCss }} />
507507 <div class="mkt-root">
508508 <header class="mkt-hero">
509509 <div class="eyebrow">About</div>
Modifiedsrc/views/landing.tsx+1−1View fileUnifiedSplit
@@ -26,7 +26,7 @@ export const LandingHero: FC<LandingPageProps> = ({ stats } = {}) => {
2626
2727 return (
2828 <>
29 <style>{landingCss}</style>
29 <style dangerouslySetInnerHTML={{ __html: landingCss }} />
3030
3131 <div class="landing-root">
3232 {/* ---------- Hero ---------- */}
Modifiedsrc/views/layout.tsx+7−7View fileUnifiedSplit
@@ -23,9 +23,9 @@ export const Layout: FC<
2323 <link rel="manifest" href="/manifest.webmanifest" />
2424 <link rel="icon" type="image/svg+xml" href="/icon.svg" />
2525 <title>{title ? `${title} — gluecron` : "gluecron"}</title>
26 <script>{themeInitScript}</script>
27 <style>{css}</style>
28 <style>{hljsThemeCss}</style>
26 <script dangerouslySetInnerHTML={{ __html: themeInitScript }} />
27
28
2929 </head>
3030
3131 <div class="prelaunch-banner" role="status" aria-live="polite">
@@ -155,7 +155,7 @@ export const Layout: FC<
155155 Reload
156156 </button>
157157 </div>
158 <script>{versionPollerScript}</script>
158
159159 {/* Block I4 — Command palette shell (hidden by default) */}
160160 <div
161161 id="cmdk-backdrop"
@@ -174,9 +174,9 @@ export const Layout: FC<
174174 />
175175
176176 </div>
177 <script>{clientJs}</script>
178 <script>{pwaRegisterScript}</script>
179 <script>{navScript}</script>
177
178
179
180180 </body>
181181 </html>
182182 );
183183