Skip to content

Commit 448863a

Browse files
committed
Clean up old stuff
1 parent 6490721 commit 448863a

11 files changed

Lines changed: 181 additions & 155 deletions

File tree

app/_patterns/search-params/page.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ const options = [
1010
{ name: 'Items Per Page', value: 'perPage', items: ['10', '25', '100'] },
1111
];
1212

13-
export const dynamic = 'force-dynamic';
14-
1513
export default async function Page(props: { searchParams: Promise<any> }) {
1614
const searchParams = await props.searchParams;
1715
return (

app/api/og/route.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ export async function GET(req: NextRequest): Promise<Response | ImageResponse> {
5858
} catch (e) {
5959
if (!(e instanceof Error)) throw e;
6060

61-
// eslint-disable-next-line no-console
62-
console.log(e.message);
61+
console.error(e.message);
6362
return new Response(`Failed to generate the image`, { status: 500 });
6463
}
6564
}

app/partial-fallbacks/[slug]/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ async function ProductDetail({ slug }: { slug: string }) {
3434

3535
await new Promise((resolve) => setTimeout(resolve, 2000));
3636

37-
const product = db.product.find({ where: { id: slug } });
37+
const productId = slug.split('-')[0];
38+
const product = db.product.find({ where: { id: productId } });
3839
if (!product) {
3940
notFound();
4041
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use client';
2+
3+
import { Product } from '#/lib/db';
4+
import { ProductCard } from '#/ui/product-card';
5+
import Link from 'next/link';
6+
import { useEffect, useState } from 'react';
7+
8+
export function RuntimeLink({ product }: { product: Product }) {
9+
const [suffix, setSuffix] = useState('');
10+
11+
useEffect(() => {
12+
setSuffix(Math.random().toString(36).slice(2, 8));
13+
}, []);
14+
15+
const slug = suffix ? `${product.id}-${suffix}` : product.id;
16+
17+
return (
18+
<Link href={`/partial-fallbacks/${slug}`} className="group">
19+
<ProductCard product={product} animateEnter={true} />
20+
<div className="mt-2 flex items-center gap-2">
21+
<span className="text-sm font-medium text-gray-300 group-hover:text-gray-100">
22+
{product.name}
23+
</span>
24+
<span className="rounded-full bg-orange-900/50 px-2 py-0.5 text-[10px] font-medium text-orange-400">
25+
runtime
26+
</span>
27+
</div>
28+
</Link>
29+
);
30+
}

app/partial-fallbacks/page.tsx

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import db from '#/lib/db';
44
import { Boundary } from '#/ui/boundary';
55
import { ProductCard } from '#/ui/product-card';
66
import Link from 'next/link';
7+
import { RuntimeLink } from './_components/runtime-link';
78

89
const PRE_RENDERED_IDS = ['1', '2', '3'];
910

@@ -22,32 +23,30 @@ export default async function Page() {
2223
<p className="text-sm text-gray-500">
2324
Products 1–3 are pre-rendered via{' '}
2425
<code className="text-gray-400">generateStaticParams</code>. Products
25-
4–9 are discovered at runtime.
26+
4–9 use a random slug so each click is a fresh cache miss.
2627
</p>
2728
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
28-
{products.map((product) => (
29-
<Link
30-
key={product.id}
31-
href={`/partial-fallbacks/${product.id}`}
32-
className="group"
33-
>
34-
<ProductCard product={product} animateEnter={true} />
35-
<div className="mt-2 flex items-center gap-2">
36-
<span className="text-sm font-medium text-gray-300 group-hover:text-gray-100">
37-
{product.name}
38-
</span>
39-
{PRE_RENDERED_IDS.includes(product.id) ? (
29+
{products.map((product) =>
30+
PRE_RENDERED_IDS.includes(product.id) ? (
31+
<Link
32+
key={product.id}
33+
href={`/partial-fallbacks/${product.id}`}
34+
className="group"
35+
>
36+
<ProductCard product={product} animateEnter={true} />
37+
<div className="mt-2 flex items-center gap-2">
38+
<span className="text-sm font-medium text-gray-300 group-hover:text-gray-100">
39+
{product.name}
40+
</span>
4041
<span className="rounded-full bg-green-900/50 px-2 py-0.5 text-[10px] font-medium text-green-400">
4142
pre-rendered
4243
</span>
43-
) : (
44-
<span className="rounded-full bg-orange-900/50 px-2 py-0.5 text-[10px] font-medium text-orange-400">
45-
runtime
46-
</span>
47-
)}
48-
</div>
49-
</Link>
50-
))}
44+
</div>
45+
</Link>
46+
) : (
47+
<RuntimeLink key={product.id} product={product} />
48+
),
49+
)}
5150
</div>
5251
</div>
5352
</Boundary>

app/partial-fallbacks/readme.mdx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ const nextConfig = {
2929

3030
- A product catalog with 9 products. Only 3 are in `generateStaticParams`.
3131
- Pre-rendered products (1–3) load instantly with no fallback.
32-
- Runtime-discovered products (4–9) show a skeleton while the page generates.
33-
- With `partialFallbacks: true`, runtime products get an instant shell and stream in. Refreshing shows the page is now fully static.
32+
- Runtime-discovered products (4–9) use a random slug on each click, guaranteeing a fresh cache miss every time.
33+
- With `partialFallbacks: true`, runtime products get an instant shell and stream in. Visiting the same URL again loads instantly from cache.
3434

3535
### Notes
3636

3737
- This demo uses the experimental `partialFallbacks` flag.
38-
- Product detail pages use `cacheLife({ revalidate: 3600 })` (1 hour) so the cache expires and the streaming behavior can be re-demonstrated.
38+
- Runtime product links generate a random suffix (e.g., `/partial-fallbacks/4-x8k2m`) so each click from the list triggers a fresh runtime discovery.
39+
- Product detail pages use `cacheLife({ revalidate: 3600 })` (1 hour) so the cache eventually expires.
3940
- This demo uses the `use cache` directive.

next.config.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ const nextConfig = {
55
cacheComponents: true,
66
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
77
experimental: {
8-
// Disabled due to font error that's causing them not to be loaded
9-
// correctly in the browser.
10-
// inlineCss: true,
8+
inlineCss: true,
119
viewTransition: true,
1210
prerenderEarlyExit: false,
1311
partialFallbacks: true,

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@
1010
"@heroicons/react": "2.2.0",
1111
"@mdx-js/loader": "3.1.0",
1212
"@mdx-js/react": "3.1.0",
13-
"@next/mdx": "16.0.0-canary.9",
13+
"@next/mdx": "16.2.2",
1414
"@types/mdx": "2.0.13",
1515
"clsx": "2.1.1",
1616
"codehike": "1.0.7",
1717
"date-fns": "4.1.0",
1818
"dinero.js": "2.0.0-alpha.10",
1919
"ms": "3.0.0-canary.1",
20-
"next": "16.2.1-canary.25",
21-
"react": "19.3.0-canary-7dc903cd-20251203",
22-
"react-dom": "19.3.0-canary-7dc903cd-20251203",
20+
"next": "16.2.2",
21+
"react": "19.2.4",
22+
"react-dom": "19.2.4",
2323
"recma-codehike": "0.0.1",
2424
"remark-codehike": "0.0.1",
2525
"server-only": "0.0.1",
@@ -33,8 +33,8 @@
3333
"@tailwindcss/typography": "0.5.16",
3434
"@types/ms": "2.1.0",
3535
"@types/node": "22.13.1",
36-
"@types/react": "19.2.2",
37-
"@types/react-dom": "19.2.2",
36+
"@types/react": "19.2.14",
37+
"@types/react-dom": "19.2.3",
3838
"postcss": "8.5.3",
3939
"prettier": "3.5.3",
4040
"prettier-plugin-tailwindcss": "0.6.12",

0 commit comments

Comments
 (0)