3aeb2b0d5d
Replaces the two Google Fonts stylesheets with self-hosted fonts via `@fontsource`, imported in the app entry (and Storybook preview), and removes the duplicate Inter that BlockNote was shipping. ## Why - **The caching argument for Google Fonts is dead.** Browsers partition the HTTP cache by top-level site (Chrome 86+, Firefox 85+, Safari even earlier), so a font cached from another website is never reused on ours. Every first-time visitor downloads the fonts either way — Google just adds a detour. - **Faster first paint.** This removes two render-blocking cross-origin stylesheets from `index.html` (DNS + TLS to `fonts.googleapis.com`, then a second connection to `fonts.gstatic.com`, with no preconnect today). The fonts now ship from our own `/assets` alongside the rest of the app, behind the same CDN and cache policy. - **Privacy.** Visitor IPs are no longer sent to Google on every page load. A German court ruled in 2022 that Google Fonts embedding violates GDPR, and privacy-conscious self-hosters currently have no way to opt out of the dependency. - **Air-gapped / offline self-hosted instances** currently render fallback system fonts; they now get the real ones. ## Font unification We were actually loading Inter from two places: the Google stylesheet, plus `@blocknote/core/fonts/inter.css` (8 weights, latin-only, woff+woff2) imported by the two rich-text editors — whichever loaded last won the cascade. Both are gone; `@fontsource` is now the single source: - Inter 400/500/600 (theme weights) + 700 (rich-text bold, previously only covered by the BlockNote copy) - DM Mono 400/500 (DM Mono has no 600 upstream; the old Google link requested one anyway) Fontsource ships the same `unicode-range` subsets as the Google CSS, so browsers still only download the subset they need (~60KB of woff2 for latin), and non-latin locales keep full coverage — which the latin-only BlockNote copy didn't provide. ## Notes - The BlockNote PDF export (`exportBlockNoteEditorToPdf.ts`) still fetches Inter TTFs from `fonts.gstatic.com` at export time — react-pdf needs TTF files, left unchanged here. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22506?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
87 lines
2.6 KiB
HTML
87 lines
2.6 KiB
HTML
<!doctype html>
|
|
<html lang="en" translate="no" class="light">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
|
|
<link
|
|
rel="icon"
|
|
type="image/x-icon"
|
|
href="/images/icons/android/android-launchericon-48-48.png"
|
|
data-rh="true"
|
|
/>
|
|
<link rel="apple-touch-icon" href="/images/icons/ios/192.png" />
|
|
<link rel="manifest" href="/manifest.json" />
|
|
|
|
<meta name="theme-color" content="#000000" />
|
|
<meta name="description" content="A modern open-source CRM" />
|
|
<meta
|
|
property="og:image"
|
|
content="https://raw.githubusercontent.com/twentyhq/twenty/main/docs/static/img/social-card.png"
|
|
/>
|
|
<meta property="og:description" content="A modern open-source CRM" />
|
|
<meta property="og:title" content="Twenty" />
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta
|
|
name="twitter:image"
|
|
content="https://raw.githubusercontent.com/twentyhq/twenty/main/docs/static/img/social-card.png"
|
|
/>
|
|
|
|
<meta name="twitter:description" content="A modern open-source CRM" />
|
|
<meta name="twitter:title" content="Twenty" />
|
|
<title>Twenty</title>
|
|
<!-- BEGIN: Twenty Config -->
|
|
<script id="twenty-env-config">
|
|
window._env_ = {
|
|
// This will be overwritten
|
|
};
|
|
</script>
|
|
<!-- END: Twenty Config -->
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<script type="module">
|
|
const disableInputAutoZoom = () => {
|
|
const viewportMetadata = document.querySelector('meta[name=viewport]');
|
|
|
|
if (viewportMetadata !== null) {
|
|
viewportMetadata.setAttribute(
|
|
'content',
|
|
'width=device-width, initial-scale=1.0, maximum-scale=1.0',
|
|
);
|
|
}
|
|
};
|
|
|
|
const isIOS = /iPad|iPhone/.test(navigator.userAgent);
|
|
if (isIOS) {
|
|
disableInputAutoZoom();
|
|
}
|
|
</script>
|
|
<style>
|
|
:root {
|
|
/* THEME_DARK.background.tertiary */
|
|
--theme-dark-background-tertiary: #1d1d1d;
|
|
/* THEME_LIGHT.background.tertiary */
|
|
--theme-light-background-tertiary: #f1f1f1;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
html,
|
|
body {
|
|
background-color: var(--theme-dark-background-tertiary);
|
|
}
|
|
}
|
|
|
|
@media (prefers-color-scheme: light) {
|
|
html,
|
|
body {
|
|
background-color: var(--theme-light-background-tertiary);
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
<div id="root"></div>
|
|
<script type="module" src="/src/index.tsx"></script>
|
|
</body>
|
|
</html>
|