Skip to content

Commit a2343f0

Browse files
committed
feat: refresh landing page for Fresh 2.3 release
Update HelloBar to announce Fresh 2.3 with feature highlights. Add new sections: View Transitions, API Routes/Handlers, WebSockets, <Head> element, and OpenTelemetry. Fix syntax highlighting in Simple section, fix broken Deco showcase image, update RenderingSection to use Temporal API, fix cursor styles on interactive demos, and move WebSocket docs from Examples to Advanced.
1 parent 0ab5a2a commit a2343f0

14 files changed

Lines changed: 441 additions & 36 deletions
File renamed without changes.

docs/toc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const toc: RawTableOfContents = {
6161
["environment-variables", "Environment Variables", "link:latest"],
6262
["head", "<head> element", "link:latest"],
6363
["vite", "Vite Plugin Options", "link:latest"],
64+
["websockets", "WebSockets", "link:latest"],
6465
["opentelemetry", "OpenTelemetry", "link:latest"],
6566
["api-reference", "API Reference", "link:latest"],
6667
["troubleshooting", "Troubleshooting", "link:latest"],
@@ -107,7 +108,6 @@ const toc: RawTableOfContents = {
107108
],
108109
["active-links", "Active links", "link:latest"],
109110
["session-management", "Session management", "link:latest"],
110-
["websockets", "WebSockets", "link:latest"],
111111
["common-patterns", "Common Patterns", "link:latest"],
112112
],
113113
},
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { CodeBlock } from "../../components/CodeBlock.tsx";
2+
import { CodeWindow } from "../../components/CodeWindow.tsx";
3+
import { PageSection } from "../../components/PageSection.tsx";
4+
import { SideBySide } from "../../components/SideBySide.tsx";
5+
import { SectionHeading } from "../../components/homepage/SectionHeading.tsx";
6+
import { FancyLink } from "../../components/FancyLink.tsx";
7+
8+
const apiCode = `import { createDefine } from "fresh";
9+
const define = createDefine();
10+
11+
export const handlers = define.handlers({
12+
GET(ctx) {
13+
const user = db.getUser(ctx.params.id);
14+
return Response.json(user);
15+
},
16+
POST(ctx) {
17+
const body = await ctx.req.json();
18+
const user = db.updateUser(ctx.params.id, body);
19+
return Response.json(user);
20+
},
21+
DELETE(ctx) {
22+
db.deleteUser(ctx.params.id);
23+
return new Response(null, { status: 204 });
24+
},
25+
});`;
26+
27+
export function APIRoutesSection() {
28+
return (
29+
<PageSection>
30+
<SideBySide mdColSplit="3/2" lgColSplit="3/2" reverseOnDesktop class="!items-start">
31+
<div class="flex flex-col gap-4 md:sticky md:top-4">
32+
<svg
33+
aria-hidden="true"
34+
xmlns="http://www.w3.org/2000/svg"
35+
class="icon icon-tabler icon-tabler-api text-fresh"
36+
width="4rem"
37+
height="4rem"
38+
viewBox="0 0 24 24"
39+
stroke-width="1.5"
40+
stroke="currentColor"
41+
fill="none"
42+
stroke-linecap="round"
43+
stroke-linejoin="round"
44+
>
45+
<title>API routes icon</title>
46+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
47+
<path d="M4 13h5" />
48+
<path d="M12 16v-8h3a2 2 0 0 1 2 2v1a2 2 0 0 1 -2 2h-3" />
49+
<path d="M20 8v8" />
50+
<path d="M9 16v-5.5a2.5 2.5 0 0 0 -5 0v5.5" />
51+
</svg>
52+
<SectionHeading>Handlers for every method</SectionHeading>
53+
<p>
54+
Define{" "}
55+
<code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono">
56+
GET
57+
</code>,{" "}
58+
<code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono">
59+
POST
60+
</code>,{" "}
61+
<code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono">
62+
DELETE
63+
</code>{" "}
64+
— any HTTP method as a named handler on your route. Fresh maps
65+
requests to the right function automatically, with full type safety.
66+
</p>
67+
<FancyLink href="/docs/concepts/routing" class="mt-2">
68+
Learn about handlers
69+
</FancyLink>
70+
</div>
71+
<div class="flex flex-col gap-4">
72+
<CodeWindow name="routes/users/[id].tsx">
73+
<CodeBlock code={apiCode} lang="js" />
74+
</CodeWindow>
75+
</div>
76+
</SideBySide>
77+
</PageSection>
78+
);
79+
}

www/components/homepage/FormsSection.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { ExampleArrow } from "../homepage/ExampleArrow.tsx";
88
import { FancyLink } from "../FancyLink.tsx";
99
import { FormSubmitDemo } from "../../islands/FormSubmitDemo.tsx";
1010

11-
const routingCode = `import { define } from "../utils.ts";
11+
const routingCode = `import { createDefine } from "fresh";
12+
const define = createDefine();
1213
1314
export const handler = define.handlers({
1415
async POST(ctx) {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { CodeBlock } from "../../components/CodeBlock.tsx";
2+
import { CodeWindow } from "../../components/CodeWindow.tsx";
3+
import { PageSection } from "../../components/PageSection.tsx";
4+
import { SideBySide } from "../../components/SideBySide.tsx";
5+
import { SectionHeading } from "../../components/homepage/SectionHeading.tsx";
6+
import { FancyLink } from "../../components/FancyLink.tsx";
7+
8+
const headCode = `import { Head } from "fresh/runtime";
9+
10+
export default function MyPage() {
11+
return (
12+
<>
13+
<Head>
14+
<title>My Page</title>
15+
<meta name="description" content="..." />
16+
<link rel="stylesheet" href="/styles.css" />
17+
</Head>
18+
<h1>Hello, world!</h1>
19+
</>
20+
);
21+
}`;
22+
23+
export function HeadSection() {
24+
return (
25+
<PageSection>
26+
<SideBySide
27+
mdColSplit="3/2"
28+
lgColSplit="3/2"
29+
reverseOnDesktop
30+
class="!items-start"
31+
>
32+
<div class="flex flex-col gap-4 md:sticky md:top-4">
33+
<svg
34+
aria-hidden="true"
35+
xmlns="http://www.w3.org/2000/svg"
36+
class="icon icon-tabler icon-tabler-file-code text-fresh"
37+
width="4rem"
38+
height="4rem"
39+
viewBox="0 0 24 24"
40+
stroke-width="1.5"
41+
stroke="currentColor"
42+
fill="none"
43+
stroke-linecap="round"
44+
stroke-linejoin="round"
45+
>
46+
<title>Head element icon</title>
47+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
48+
<path d="M14 3v4a1 1 0 0 0 1 1h4" />
49+
<path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z" />
50+
<path d="M10 13l-1 2l1 2" />
51+
<path d="M14 13l1 2l-1 2" />
52+
</svg>
53+
<SectionHeading>
54+
Full control of{" "}
55+
<span dangerouslySetInnerHTML={{ __html: "&lt;head&gt;" }} />
56+
</SectionHeading>
57+
<p>
58+
Use the{" "}
59+
<code
60+
class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono"
61+
dangerouslySetInnerHTML={{ __html: "&lt;Head&gt;" }}
62+
/>{" "}
63+
component from any page or island to set titles, meta tags,
64+
stylesheets, and scripts — no hoisting hacks or side channels
65+
needed.
66+
</p>
67+
<FancyLink href="/docs/advanced/head" class="mt-2">
68+
<span dangerouslySetInnerHTML={{ __html: "Learn about &lt;Head&gt;" }} />
69+
</FancyLink>
70+
</div>
71+
<div class="flex flex-col gap-4">
72+
<CodeWindow name="routes/my-page.tsx">
73+
<CodeBlock code={headCode} lang="jsx" />
74+
</CodeWindow>
75+
</div>
76+
</SideBySide>
77+
</PageSection>
78+
);
79+
}

www/components/homepage/RecipeDemo.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ export const RecipeDemo = () => (
66
class="w-full grid grid-cols-1 md:grid-cols-[auto_1fr] text-left gap-6 items-stretch min-h-64"
77
>
88
<aside class="flex flex-col gap-2 underline p-6 pl-0 border-b md:border-r md:border-b-0 border-current text-left items-start justify-center">
9-
<button type="button" f-partial="/recipes/lemonade">
9+
<button type="button" f-partial="/recipes/lemonade" class="cursor-pointer">
1010
Lemonade
1111
</button>
12-
<button type="button" f-partial="/recipes/lemon-honey-tea">
12+
<button type="button" f-partial="/recipes/lemon-honey-tea" class="cursor-pointer">
1313
Lemon-honey tea
1414
</button>
15-
<button type="button" f-partial="/recipes/lemondrop">
15+
<button type="button" f-partial="/recipes/lemondrop" class="cursor-pointer">
1616
Lemondrop Martini
1717
</button>
1818
</aside>

www/components/homepage/RenderingSection.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { DemoBox } from "../../components/homepage/DemoBox.tsx";
77
import { ExampleArrow } from "../../components/homepage/ExampleArrow.tsx";
88

99
const serverCode = `export default function HomePage() {
10-
const time = new Date().toLocaleString();
10+
const now = Temporal.Now.plainDateTimeISO()
11+
.toLocaleString("en-US");
1112
return (
12-
<p>Freshly server-rendered {time}</p>
13+
<p>Freshly server-rendered {now}</p>
1314
);
1415
}`;
1516

@@ -56,10 +57,8 @@ export function RenderingSection() {
5657
<ExampleArrow class="ml-[55%]" />{" "}
5758
<DemoBox>
5859
<p>
59-
Freshly server-rendered {new Date().toLocaleString("default", {
60-
dateStyle: "medium",
61-
timeStyle: "medium",
62-
})} UTC
60+
Freshly server-rendered{" "}
61+
{Temporal.Now.plainDateTimeISO().toLocaleString("en-US")}
6362
</p>
6463
</DemoBox>
6564
</div>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { CodeBlock } from "../../components/CodeBlock.tsx";
2+
import { CodeWindow } from "../../components/CodeWindow.tsx";
3+
import { PageSection } from "../../components/PageSection.tsx";
4+
import { SideBySide } from "../../components/SideBySide.tsx";
5+
import { SectionHeading } from "../../components/homepage/SectionHeading.tsx";
6+
import { FancyLink } from "../../components/FancyLink.tsx";
7+
8+
const otelCode = `import { App } from "fresh";
9+
10+
const app = new App({
11+
// When OpenTelemetry is active, Fresh
12+
// auto-injects a <meta name="traceparent">
13+
// tag — connecting browser traces to
14+
// server spans, zero config required
15+
otel: true,
16+
});
17+
18+
app.listen();`;
19+
20+
export function SecuritySection() {
21+
return (
22+
<PageSection>
23+
<SideBySide mdColSplit="2/3" lgColSplit="2/3" class="!items-start">
24+
<div class="flex flex-col gap-4 md:sticky md:top-4">
25+
<svg
26+
aria-hidden="true"
27+
xmlns="http://www.w3.org/2000/svg"
28+
class="icon icon-tabler icon-tabler-telescope text-fresh"
29+
width="4rem"
30+
height="4rem"
31+
viewBox="0 0 24 24"
32+
stroke-width="1.5"
33+
stroke="currentColor"
34+
fill="none"
35+
stroke-linecap="round"
36+
stroke-linejoin="round"
37+
>
38+
<title>Observability icon</title>
39+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
40+
<path d="M6 21l6 -5l6 5" />
41+
<path d="M12 13v8" />
42+
<path d="M3.294 13.678l.166 .281c.52 .88 1.624 1.265 2.605 .91l14.242 -5.165a1.023 1.023 0 0 0 .565 -1.456l-2.62 -4.705a1.024 1.024 0 0 0 -1.462 -.394l-13.397 7.719c-1.038 .598 -1.272 1.783 -.594 2.692" />
43+
<path d="M8 11.5l5.5 -3.2" />
44+
<path d="M12.602 8.3l-2.552 4.6" />
45+
</svg>
46+
<SectionHeading>OpenTelemetry, built in</SectionHeading>
47+
<p>
48+
When OpenTelemetry is active, Fresh automatically injects a{" "}
49+
<code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono">
50+
traceparent
51+
</code>{" "}
52+
meta tag into every page — connecting your browser traces to server
53+
spans end-to-end, zero config required.
54+
</p>
55+
<p>
56+
Get full-stack observability across your entire request lifecycle
57+
with a single flag.
58+
</p>
59+
<FancyLink href="/docs/advanced/opentelemetry" class="mt-2">
60+
Learn about OpenTelemetry
61+
</FancyLink>
62+
</div>
63+
<div class="flex flex-col gap-6">
64+
<CodeWindow name="main.ts">
65+
<CodeBlock code={otelCode} lang="js" />
66+
</CodeWindow>
67+
</div>
68+
</SideBySide>
69+
</PageSection>
70+
);
71+
}

www/components/homepage/Simple.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
11
import { PageSection } from "../../components/PageSection.tsx";
2+
import { CodeBlock } from "../../components/CodeBlock.tsx";
23

34
const ONE_FILE_EXAMPLE = `import { App } from "fresh";
45
56
const app = new App()
6-
.get("/", () => new Response("Hello, World!"));
7+
.get("/", () =>
8+
new Response("Hello!")
9+
);
710
811
app.listen();`;
912

1013
const ADD_JSX_EXAMPLE = `import { App } from "fresh";
1114
1215
const app = new App()
13-
.get("/", (ctx) => ctx.render(<h1>Hello!</h1>));
16+
.get("/", (ctx) =>
17+
ctx.render(<h1>Hello!</h1>)
18+
);
1419
1520
app.listen();`;
1621

17-
const ADD_ISLAND_EXAMPLE = `// islands/Counter.tsx
18-
import { useSignal } from "@preact/signals";
22+
const ADD_ISLAND_EXAMPLE = `import { useSignal } from
23+
"@preact/signals";
1924
2025
export function Counter() {
2126
const count = useSignal(0);
2227
return (
23-
<button onClick={() => count.value++}>
28+
<button
29+
onClick={() => count.value++}
30+
>
2431
Count: {count}
2532
</button>
2633
);
@@ -40,7 +47,7 @@ export function Simple() {
4047
</p>
4148
</div>
4249

43-
<div class="grid md:grid-cols-3 gap-6 mt-8">
50+
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6 mt-8">
4451
<StepCard
4552
step="1"
4653
title="One file. That's it."
@@ -76,9 +83,9 @@ function StepCard(
7683
<h3 class="font-bold text-lg">{props.title}</h3>
7784
</div>
7885
<p class="text-gray-600 text-sm">{props.description}</p>
79-
<pre class="bg-slate-800 text-green-100 rounded-md p-4 text-sm overflow-x-auto flex-1">
80-
<code>{props.code}</code>
81-
</pre>
86+
<div class="text-sm flex-1 [&>pre]:!m-0 [&>pre]:h-full">
87+
<CodeBlock code={props.code} lang="jsx" />
88+
</div>
8289
</div>
8390
);
8491
}

www/components/homepage/SocialProof.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ export function SocialProof() {
1616
eCommerce platform
1717
</p>
1818
</div>
19-
<a href="https://deno.com/blog/deco-cx-subhosting-serve-their-clients-storefronts-fast">
20-
<img
21-
src="/showcase/deco.webp"
22-
alt="Deco CX"
23-
class="mx-auto"
24-
loading="lazy"
25-
/>
19+
<a
20+
href="https://deno.com/blog/deco-cx-subhosting-serve-their-clients-storefronts-fast"
21+
class="block mx-auto text-center"
22+
>
23+
<div class="mx-auto max-w-screen-md bg-gradient-to-br from-green-50 to-yellow-50 border border-green-200 rounded-lg p-12 flex items-center justify-center">
24+
<span class="text-4xl sm:text-5xl md:text-6xl font-extrabold text-green-700 tracking-tight">
25+
deco.cx
26+
</span>
27+
</div>
2628
</a>
2729
<div class="flex flex-col gap-8 items-center justify-center -mt-8 md:-mt-16 lg:-mt-32">
2830
<DemoBox flip>

0 commit comments

Comments
 (0)