Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,29 @@

[functions]
directory = "netlify/functions"

# Cache headers for static assets
[[headers]]
for = "/fonts/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
for = "/logos/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
for = "/assets/*.js"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
for = "/assets/*.css"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
for = "/*.woff2"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
2 changes: 2 additions & 0 deletions src/components/ShowcaseCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export function ShowcaseCard({
<img
src={showcase.screenshotUrl}
alt={showcase.name}
loading="lazy"
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
/>
{/* Logo overlay */}
Expand All @@ -54,6 +55,7 @@ export function ShowcaseCard({
<img
src={showcase.logoUrl}
alt=""
loading="lazy"
className="w-full h-full object-cover"
/>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/components/TrustedByMarquee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export function TrustedByMarquee({
key={i}
src={logoSrc}
alt={brand}
loading="lazy"
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"
/>
) : (
Expand Down
26 changes: 20 additions & 6 deletions src/routes/admin/banners.$id.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { createFileRoute, useNavigate } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { BannerEditor } from '~/components/admin/BannerEditor'
import { lazy, Suspense } from 'react'
import { getBanner, type BannerWithMeta } from '~/utils/banner.functions'
import { useCapabilities } from '~/hooks/useCapabilities'
import { useCurrentUserQuery } from '~/hooks/useCurrentUser'
import * as v from 'valibot'

const BannerEditor = lazy(() =>
import('~/components/admin/BannerEditor').then((m) => ({
default: m.BannerEditor,
})),
)

export const Route = createFileRoute('/admin/banners/$id')({
component: BannerEditorPage,
validateSearch: (search) => v.parse(v.object({}), search),
Expand Down Expand Up @@ -75,11 +81,19 @@ function BannerEditorPage() {
return (
<div className="min-h-screen p-8">
<div className="max-w-6xl mx-auto">
<BannerEditor
banner={isNew ? null : (bannerQuery.data as BannerWithMeta)}
onSave={() => navigate({ to: '/admin/banners' })}
onCancel={() => navigate({ to: '/admin/banners' })}
/>
<Suspense
fallback={
<div className="flex items-center justify-center p-8">
<div>Loading editor...</div>
</div>
}
>
<BannerEditor
banner={isNew ? null : (bannerQuery.data as BannerWithMeta)}
onSave={() => navigate({ to: '/admin/banners' })}
onCancel={() => navigate({ to: '/admin/banners' })}
/>
</Suspense>
</div>
</div>
)
Expand Down
31 changes: 24 additions & 7 deletions src/routes/admin/feed.$id.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { createFileRoute, useNavigate } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { FeedEntryEditor } from '~/components/admin/FeedEntryEditor'
import { lazy, Suspense } from 'react'
import type { FeedEntry } from '~/components/FeedEntry'
import { useCapabilities } from '~/hooks/useCapabilities'
import { useCurrentUserQuery } from '~/hooks/useCurrentUser'
import { getFeedEntryQueryOptions } from '~/queries/feed'
import * as v from 'valibot'

const FeedEntryEditor = lazy(() =>
import('~/components/admin/FeedEntryEditor').then((m) => ({
default: m.FeedEntryEditor,
})),
)

export const Route = createFileRoute('/admin/feed/$id')({
component: FeedEditorPage,
validateSearch: (search) => v.parse(v.object({}), search),
Expand Down Expand Up @@ -73,13 +80,23 @@ function FeedEditorPage() {
return (
<div className="min-h-screen p-8">
<div className="max-w-4xl mx-auto">
<FeedEntryEditor
entry={
isNew ? null : ((entryQuery.data as FeedEntry | undefined) ?? null)
<Suspense
fallback={
<div className="flex items-center justify-center p-8">
<div>Loading editor...</div>
</div>
}
onSave={() => navigate({ to: '/admin/feed' })}
onCancel={() => navigate({ to: '/admin/feed' })}
/>
>
<FeedEntryEditor
entry={
isNew
? null
: ((entryQuery.data as FeedEntry | undefined) ?? null)
}
onSave={() => navigate({ to: '/admin/feed' })}
onCancel={() => navigate({ to: '/admin/feed' })}
/>
</Suspense>
</div>
</div>
)
Expand Down
18 changes: 18 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ export default defineConfig({
) {
return 'search'
}
// Syntax highlighting (lazy-loaded via mermaid/shiki)
if (id.includes('shiki') || id.includes('mermaid')) {
return 'syntax-highlight'
}
// Radix UI components (used throughout)
if (id.includes('@radix-ui/')) {
return 'radix-ui'
}
// Markdown processing (unified/remark/rehype)
if (
id.includes('unified') ||
id.includes('remark') ||
id.includes('rehype') ||
id.includes('hast-') ||
id.includes('mdast-')
) {
return 'markdown-processing'
}
// Charting deps (only loaded on stats/admin pages)
if (
id.includes('@observablehq/plot') ||
Expand Down
Loading