1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102import { headers, cookies } from "next/headers";
import Link from "next/link";
import type { Metadata } from "next";
import { addGuestbookEntry } from "../actions.js";
import { getGuestbookEntries } from "../_guestbook.js";
import { s } from "../_styles.js";
export const metadata: Metadata = {
title: "About",
description: "About page demonstrating next/headers and cookies",
};
export default async function AboutPage() {
// next/headers โ read request headers
const h = await headers();
const userAgent = h.get("user-agent") ?? "unknown";
const acceptLanguage = h.get("accept-language") ?? "unknown";
// next/headers โ read cookies
const c = await cookies();
const theme = c.get("theme")?.value ?? "not set";
const visitCount = c.get("visit-count")?.value ?? "0";
const entries = getGuestbookEntries();
return (
<main style={s.page}>
<div>
<h1 style={s.title}>About</h1>
<p style={s.subtitle}>
This page demonstrates <code>headers()</code>,{" "}
<code>cookies()</code>, and server actions.
</p>
</div>
{/* Demonstrates headers() */}
<section style={s.card}>
<h2 style={s.label}>headers()</h2>
<dl style={s.dl}>
<dt style={s.dt}>User-Agent</dt>
<dd data-testid="user-agent" style={s.dd}>
{userAgent.slice(0, 80)}
</dd>
<dt style={s.dt}>Accept-Language</dt>
<dd data-testid="accept-language" style={s.dd}>
{acceptLanguage}
</dd>
</dl>
</section>
{/* Demonstrates cookies() */}
<section style={s.card}>
<h2 style={s.label}>cookies()</h2>
<dl style={s.dl}>
<dt style={s.dt}>Theme</dt>
<dd data-testid="theme-cookie" style={s.dd}>
{theme}
</dd>
<dt style={s.dt}>Visit Count</dt>
<dd data-testid="visit-count" style={s.dd}>
{visitCount}
</dd>
</dl>
</section>
{/* Server action โ form with "use server" action */}
<section style={s.card}>
<h2 style={s.label}>Server Action</h2>
<form
action={addGuestbookEntry}
style={{ display: "flex", gap: "0.5rem" }}
>
<input
name="name"
placeholder="Sign the guestbook..."
required
data-testid="guestbook-input"
style={s.input}
/>
<button type="submit" data-testid="guestbook-submit" style={s.btn}>
Sign
</button>
</form>
{entries.length > 0 && (
<ul
data-testid="guestbook-list"
style={{ marginTop: "0.75rem", listStyle: "none", display: "flex", gap: "0.5rem", flexWrap: "wrap" }}
>
{entries.map((entry, i) => (
<li key={i} style={s.tag}>
{entry}
</li>
))}
</ul>
)}
</section>
<Link href="/">โ Back to home</Link>
</main>
);
}