+
+
+ {/* Contrib graph background — right-aligned, radial fade */}
+
+
+
+
+
+
Open source from day one
-
+
Supabase is built in the open because we believe great developer tools should be
transparent, inspectable, and owned by the community. Read, contribute, self-host.
You're never locked in, and always in control.
@@ -112,22 +190,6 @@ export function OpenSourceSection() {
-
-
-
-
-
- GitHub Stars
-
-
- {stars}
-
-
- Top 100 GitHub repos
-
-
diff --git a/apps/www/app/layout.tsx b/apps/www/app/layout.tsx
index bd90908ee0c..98990119e37 100644
--- a/apps/www/app/layout.tsx
+++ b/apps/www/app/layout.tsx
@@ -3,7 +3,7 @@ import 'config/code-hike.scss'
import '../styles/index.css'
import { APP_NAME, DEFAULT_META_DESCRIPTION } from '~/lib/constants'
-import { ktfPrima } from '~/lib/fonts'
+import { geistMono, ktfPrima } from '~/lib/fonts'
import { Agentation } from 'agentation'
import { Metadata } from 'next'
import type { Viewport } from 'next'
@@ -47,7 +47,7 @@ export const viewport: Viewport = {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
-
+
{children}
{process.env.NODE_ENV === 'development' &&
}
diff --git a/apps/www/app/providers.tsx b/apps/www/app/providers.tsx
index 663b4d9c206..b19d8159f48 100644
--- a/apps/www/app/providers.tsx
+++ b/apps/www/app/providers.tsx
@@ -11,8 +11,9 @@ import {
useThemeSandbox,
} from 'common'
import { WwwCommandMenu } from 'components/CommandMenu'
+import { FontDevtools } from 'components/FontDevtools'
import { DevToolbar, DevToolbarProvider } from 'dev-tools'
-import { API_URL } from 'lib/constants'
+import { API_URL, IS_PROD } from 'lib/constants'
import { themes, TooltipProvider, SonnerToaster } from 'ui'
import { CommandProvider } from 'ui-patterns/CommandMenu'
import { useConsentToast } from 'ui-patterns/consent'
@@ -44,6 +45,7 @@ function Providers({ children }: { children: React.ReactNode }) {
enabled={IS_PLATFORM}
/>
+ {!IS_PROD &&
}
diff --git a/apps/www/components/FontDevtools.tsx b/apps/www/components/FontDevtools.tsx
new file mode 100644
index 00000000000..aa9222f5c63
--- /dev/null
+++ b/apps/www/components/FontDevtools.tsx
@@ -0,0 +1,161 @@
+'use client'
+
+import { useCallback, useEffect, useState } from 'react'
+import {
+ Button,
+ Label_Shadcn_ as Label,
+ Popover_Shadcn_ as Popover,
+ PopoverContent_Shadcn_ as PopoverContent,
+ PopoverTrigger_Shadcn_ as PopoverTrigger,
+ Select_Shadcn_ as Select,
+ SelectContent_Shadcn_ as SelectContent,
+ SelectItem_Shadcn_ as SelectItem,
+ SelectTrigger_Shadcn_ as SelectTrigger,
+ SelectValue_Shadcn_ as SelectValue,
+} from 'ui'
+
+const FONT_OPTIONS = {
+ sans: [
+ { label: 'KTF Prima', value: 'var(--font-ktf-prima), ui-sans-serif, system-ui, sans-serif' },
+ { label: 'System UI', value: 'ui-sans-serif, system-ui, sans-serif' },
+ { label: 'Inter', value: 'Inter, ui-sans-serif, system-ui, sans-serif' },
+ {
+ label: 'Helvetica Neue',
+ value: '"Helvetica Neue", Helvetica, Arial, sans-serif',
+ },
+ ],
+ mono: [
+ { label: 'Geist Mono', value: 'var(--font-geist-mono), ui-monospace, Menlo, monospace' },
+ { label: 'System Mono', value: 'ui-monospace, Menlo, Monaco, monospace' },
+ {
+ label: 'JetBrains Mono',
+ value: '"JetBrains Mono", ui-monospace, monospace',
+ },
+ ],
+} as const
+
+const STORAGE_KEY = 'www-font-devtools'
+const STYLE_ID = 'font-devtools-override'
+
+function getStored(): { sans?: string; mono?: string } {
+ try {
+ return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}')
+ } catch {
+ return {}
+ }
+}
+
+function applyOverrides(sans?: string, mono?: string) {
+ let el = document.getElementById(STYLE_ID) as HTMLStyleElement | null
+ const rules: string[] = []
+
+ if (sans) {
+ rules.push(`:root { --font-sans: ${sans} !important; }`)
+ }
+ if (mono) {
+ rules.push(`:root { --font-mono: ${mono} !important; }`)
+ }
+
+ if (rules.length === 0) {
+ el?.remove()
+ return
+ }
+
+ if (!el) {
+ el = document.createElement('style')
+ el.id = STYLE_ID
+ document.head.appendChild(el)
+ }
+ el.textContent = rules.join('\n')
+}
+
+export function FontDevtools() {
+ const [sans, setSans] = useState('')
+ const [mono, setMono] = useState('')
+
+ useEffect(() => {
+ const stored = getStored()
+ if (stored.sans) setSans(stored.sans)
+ if (stored.mono) setMono(stored.mono)
+ if (stored.sans || stored.mono) {
+ applyOverrides(stored.sans, stored.mono)
+ }
+ }, [])
+
+ const update = useCallback(
+ (type: 'sans' | 'mono', value: string) => {
+ const nextSans = type === 'sans' ? value : sans
+ const nextMono = type === 'mono' ? value : mono
+ setSans(nextSans)
+ setMono(nextMono)
+
+ applyOverrides(nextSans || undefined, nextMono || undefined)
+
+ const stored: Record
= {}
+ if (nextSans) stored.sans = nextSans
+ if (nextMono) stored.mono = nextMono
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(stored))
+ },
+ [sans, mono]
+ )
+
+ const reset = useCallback(() => {
+ setSans('')
+ setMono('')
+ applyOverrides()
+ localStorage.removeItem(STORAGE_KEY)
+ }, [])
+
+ return (
+
+
+
+
+ Aa
+
+
+
+
+ Font Devtools
+
+
+
+ Sans
+ update('sans', v)}>
+
+
+
+
+ {FONT_OPTIONS.sans.map((f) => (
+
+ {f.label}
+
+ ))}
+
+
+
+
+
+ Mono
+ update('mono', v)}>
+
+
+
+
+ {FONT_OPTIONS.mono.map((f) => (
+
+ {f.label}
+
+ ))}
+
+
+
+
+
+ Reset to defaults
+
+
+
+
+ )
+}
diff --git a/apps/www/lib/fonts.ts b/apps/www/lib/fonts.ts
index a2104e5292e..761a4161047 100644
--- a/apps/www/lib/fonts.ts
+++ b/apps/www/lib/fonts.ts
@@ -1,5 +1,12 @@
+import { Geist_Mono } from 'next/font/google'
import localFont from 'next/font/local'
+export const geistMono = Geist_Mono({
+ subsets: ['latin'],
+ variable: '--font-geist-mono',
+ display: 'swap',
+})
+
export const ktfPrima = localFont({
src: [
{
diff --git a/apps/www/pages/_app.tsx b/apps/www/pages/_app.tsx
index 30c4b7aa58b..003c24e61d5 100644
--- a/apps/www/pages/_app.tsx
+++ b/apps/www/pages/_app.tsx
@@ -15,7 +15,7 @@ import { DevToolbar, DevToolbarProvider } from 'dev-tools'
import { DefaultSeo } from 'next-seo'
import type { AppProps } from 'next/app'
import Head from 'next/head'
-import { ktfPrima } from '~/lib/fonts'
+import { geistMono, ktfPrima } from '~/lib/fonts'
import { useRouter } from 'next/router'
import { SonnerToaster, themes, TooltipProvider } from 'ui'
import { CommandProvider } from 'ui-patterns/CommandMenu'
@@ -26,7 +26,8 @@ import MetaFaviconsPagesRouter, {
DEFAULT_FAVICON_THEME_COLOR,
} from 'common/MetaFavicons/pages-router'
import { WwwCommandMenu } from '~/components/CommandMenu'
-import { API_URL, APP_NAME, DEFAULT_META_DESCRIPTION } from '~/lib/constants'
+import { FontDevtools } from '~/components/FontDevtools'
+import { API_URL, APP_NAME, DEFAULT_META_DESCRIPTION, IS_PROD } from '~/lib/constants'
import useDarkLaunchWeeks from '../hooks/useDarkLaunchWeeks'
import { useWwwCommandMenuTelemetry } from '../hooks/useWwwCommandMenuTelemetry'
@@ -54,7 +55,7 @@ export default function App({ Component, pageProps }: AppProps) {
}
return (
-
+
@@ -110,6 +111,7 @@ export default function App({ Component, pageProps }: AppProps) {
enabled={IS_PLATFORM}
/>
+ {!IS_PROD && }
diff --git a/apps/www/public/rss.xml b/apps/www/public/rss.xml
index b30fc5ae253..18f8f9cccd0 100644
--- a/apps/www/public/rss.xml
+++ b/apps/www/public/rss.xml
@@ -2766,4 +2766,4 @@
-
+
\ No newline at end of file
diff --git a/apps/www/styles/index.css b/apps/www/styles/index.css
index c7a65d64565..8c2b8f3445c 100644
--- a/apps/www/styles/index.css
+++ b/apps/www/styles/index.css
@@ -24,6 +24,8 @@
}
:root {
+ --font-sans: var(--font-ktf-prima), ui-sans-serif, system-ui, sans-serif;
+ --font-mono: var(--font-geist-mono), ui-monospace, Menlo, monospace;
--heading-tracking: -0.02em;
--body-tracking: -0.01em;
--heading-leading: 1.1;
@@ -36,7 +38,6 @@ html {
body {
@apply bg text-foreground;
- font-family: var(--font-ktf-prima), ui-sans-serif, system-ui, sans-serif;
letter-spacing: var(--body-tracking);
line-height: var(--body-leading);
-webkit-font-smoothing: antialiased;
@@ -44,11 +45,15 @@ body {
}
h1, h2, h3, h4, h5, h6 {
- font-family: var(--font-ktf-prima), ui-sans-serif, system-ui, sans-serif;
letter-spacing: var(--heading-tracking);
line-height: var(--heading-leading);
}
+pre, code, kbd, samp,
+pre *, code *, kbd *, samp * {
+ font-family: var(--font-mono) !important;
+}
+
/* h1,
h2,
h3,
diff --git a/packages/config/tailwind.config.js b/packages/config/tailwind.config.js
index c9469032a5f..cb38d1c94e3 100644
--- a/packages/config/tailwind.config.js
+++ b/packages/config/tailwind.config.js
@@ -273,7 +273,7 @@ const uiConfig = ui({
},
figcaption: {
color: 'hsl(var(--foreground-muted))',
- fontFamily: 'Office Code Pro, monospace',
+ fontFamily: 'var(--font-mono)',
},
'figure.quote-figure p:first-child': {
marginTop: '0 !important',
@@ -374,8 +374,8 @@ const uiConfig = ui({
xs: '480px',
},
fontFamily: {
- sans: 'var(--font-ktf-prima), ui-sans-serif, system-ui, sans-serif',
- mono: 'var(--font-source-code-pro), Source Code Pro, Office Code Pro, Menlo, monospace',
+ sans: 'var(--font-sans)',
+ mono: 'var(--font-mono)',
},
// shadcn defaults START
diff --git a/packages/ui-patterns/src/TweetCard/index.tsx b/packages/ui-patterns/src/TweetCard/index.tsx
index bcaa26c49a1..cf10646fd2d 100644
--- a/packages/ui-patterns/src/TweetCard/index.tsx
+++ b/packages/ui-patterns/src/TweetCard/index.tsx
@@ -34,11 +34,6 @@ export function TweetCard(props: TweetCard) {
)}
{props.handle}
-