Skip to content

Commit 24465b2

Browse files
committed
wip
1 parent 5015bd2 commit 24465b2

6 files changed

Lines changed: 78 additions & 2 deletions

File tree

netlify.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,29 @@
77

88
[functions]
99
directory = "netlify/functions"
10+
11+
# Cache headers for static assets
12+
[[headers]]
13+
for = "/fonts/*"
14+
[headers.values]
15+
Cache-Control = "public, max-age=31536000, immutable"
16+
17+
[[headers]]
18+
for = "/logos/*"
19+
[headers.values]
20+
Cache-Control = "public, max-age=31536000, immutable"
21+
22+
[[headers]]
23+
for = "/assets/*.js"
24+
[headers.values]
25+
Cache-Control = "public, max-age=31536000, immutable"
26+
27+
[[headers]]
28+
for = "/assets/*.css"
29+
[headers.values]
30+
Cache-Control = "public, max-age=31536000, immutable"
31+
32+
[[headers]]
33+
for = "/*.woff2"
34+
[headers.values]
35+
Cache-Control = "public, max-age=31536000, immutable"

src/components/ShowcaseCard.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export function ShowcaseCard({
4646
<img
4747
src={showcase.screenshotUrl}
4848
alt={showcase.name}
49+
loading="lazy"
4950
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
5051
/>
5152
{/* Logo overlay */}
@@ -54,6 +55,7 @@ export function ShowcaseCard({
5455
<img
5556
src={showcase.logoUrl}
5657
alt=""
58+
loading="lazy"
5759
className="w-full h-full object-cover"
5860
/>
5961
</div>

src/components/TrustedByMarquee.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export function TrustedByMarquee({
5353
key={i}
5454
src={logoSrc}
5555
alt={brand}
56+
loading="lazy"
5657
className="max-w-24 max-h-14 w-auto h-auto object-contain opacity-50 grayscale hover:opacity-100 transition-all duration-200 dark:invert dark:opacity-70 shrink-0"
5758
/>
5859
) : (

src/routes/admin/banners.$id.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import { createFileRoute, useNavigate } from '@tanstack/react-router'
22
import { useQuery } from '@tanstack/react-query'
3-
import { BannerEditor } from '~/components/admin/BannerEditor'
3+
import { lazy, Suspense } from 'react'
44
import { getBanner, type BannerWithMeta } from '~/utils/banner.functions'
55
import { useCapabilities } from '~/hooks/useCapabilities'
66
import { useCurrentUserQuery } from '~/hooks/useCurrentUser'
77
import * as v from 'valibot'
88

9+
const BannerEditor = lazy(() =>
10+
import('~/components/admin/BannerEditor').then((m) => ({
11+
default: m.BannerEditor,
12+
})),
13+
)
14+
915
export const Route = createFileRoute('/admin/banners/$id')({
1016
component: BannerEditorPage,
1117
validateSearch: (search) => v.parse(v.object({}), search),
@@ -75,11 +81,19 @@ function BannerEditorPage() {
7581
return (
7682
<div className="min-h-screen p-8">
7783
<div className="max-w-6xl mx-auto">
84+
<Suspense
85+
fallback={
86+
<div className="flex items-center justify-center p-8">
87+
<div>Loading editor...</div>
88+
</div>
89+
}
90+
>
7891
<BannerEditor
7992
banner={isNew ? null : (bannerQuery.data as BannerWithMeta)}
8093
onSave={() => navigate({ to: '/admin/banners' })}
8194
onCancel={() => navigate({ to: '/admin/banners' })}
8295
/>
96+
</Suspense>
8397
</div>
8498
</div>
8599
)

src/routes/admin/feed.$id.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
import { createFileRoute, useNavigate } from '@tanstack/react-router'
22
import { useQuery } from '@tanstack/react-query'
3-
import { FeedEntryEditor } from '~/components/admin/FeedEntryEditor'
3+
import { lazy, Suspense } from 'react'
44
import type { FeedEntry } from '~/components/FeedEntry'
55
import { useCapabilities } from '~/hooks/useCapabilities'
66
import { useCurrentUserQuery } from '~/hooks/useCurrentUser'
77
import { getFeedEntryQueryOptions } from '~/queries/feed'
88
import * as v from 'valibot'
9+
10+
const FeedEntryEditor = lazy(() =>
11+
import('~/components/admin/FeedEntryEditor').then((m) => ({
12+
default: m.FeedEntryEditor,
13+
})),
14+
)
15+
916
export const Route = createFileRoute('/admin/feed/$id')({
1017
component: FeedEditorPage,
1118
validateSearch: (search) => v.parse(v.object({}), search),
@@ -73,13 +80,21 @@ function FeedEditorPage() {
7380
return (
7481
<div className="min-h-screen p-8">
7582
<div className="max-w-4xl mx-auto">
83+
<Suspense
84+
fallback={
85+
<div className="flex items-center justify-center p-8">
86+
<div>Loading editor...</div>
87+
</div>
88+
}
89+
>
7690
<FeedEntryEditor
7791
entry={
7892
isNew ? null : ((entryQuery.data as FeedEntry | undefined) ?? null)
7993
}
8094
onSave={() => navigate({ to: '/admin/feed' })}
8195
onCancel={() => navigate({ to: '/admin/feed' })}
8296
/>
97+
</Suspense>
8398
</div>
8499
</div>
85100
)

vite.config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,24 @@ export default defineConfig({
3737
) {
3838
return 'search'
3939
}
40+
// Syntax highlighting (lazy-loaded via mermaid/shiki)
41+
if (id.includes('shiki') || id.includes('mermaid')) {
42+
return 'syntax-highlight'
43+
}
44+
// Radix UI components (used throughout)
45+
if (id.includes('@radix-ui/')) {
46+
return 'radix-ui'
47+
}
48+
// Markdown processing (unified/remark/rehype)
49+
if (
50+
id.includes('unified') ||
51+
id.includes('remark') ||
52+
id.includes('rehype') ||
53+
id.includes('hast-') ||
54+
id.includes('mdast-')
55+
) {
56+
return 'markdown-processing'
57+
}
4058
// Charting deps (only loaded on stats/admin pages)
4159
if (
4260
id.includes('@observablehq/plot') ||

0 commit comments

Comments
 (0)