chore: upgrade Next.js, next-intl, and Headless UI to latest versions

This commit is contained in:
Mauricio Siu
2025-03-02 18:50:34 -06:00
parent 06b33b6d8d
commit 9d8df9986e
11 changed files with 295 additions and 184 deletions

View File

@@ -13,3 +13,11 @@ yarn dev
```
Open http://localhost:3000 with your browser to see the result.
For Blog Page, you can use the following command to generate the static pages:
```
GHOST_URL=""
GHOST_KEY=""
```

View File

@@ -1,7 +1,7 @@
import { CopyButton } from "@/components/ui/copy-button";
import { getPost, getPosts } from "@/lib/ghost";
import type { Metadata, ResolvingMetadata } from "next";
import { getTranslations } from "next-intl/server";
import { getTranslations, setRequestLocale } from "next-intl/server";
import Image from "next/image";
import Link from "next/link";
import { notFound } from "next/navigation";
@@ -27,7 +27,8 @@ export async function generateMetadata(
{ params }: Props,
parent: ResolvingMetadata,
): Promise<Metadata> {
const post = await getPost(params.slug);
const { locale, slug } = await params;
const post = await getPost(slug);
if (!post) {
return {
@@ -36,10 +37,10 @@ export async function generateMetadata(
}
const ogUrl = new URL(
`/${params.locale}/api/og`,
`/${locale}/api/og`,
process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000",
);
ogUrl.searchParams.set("slug", params.slug);
ogUrl.searchParams.set("slug", slug);
return {
title: post.title,
@@ -69,10 +70,14 @@ export async function generateMetadata(
export async function generateStaticParams() {
const posts = await getPosts();
const locales = ["en", "fr", "zh-Hans"];
return posts.map((post) => ({
slug: post.slug,
}));
return posts.flatMap((post) =>
locales.map((locale) => ({
locale,
slug: post.slug,
})),
);
}
interface CodeProps
@@ -126,13 +131,14 @@ async function CodeBlock(props: LanguageProps) {
<CopyButton text={format} />
<div
dangerouslySetInnerHTML={{ __html: out }}
className="text-sm p-4 rounded-lg bg-[#18191F]"
className="text-sm p-4 rounded-lg bg-[#18191F] overflow-auto"
/>
</div>
);
}
export default async function BlogPostPage({ params }: Props) {
const { locale, slug } = params;
const { locale, slug } = await params;
// setRequestLocale(locale);
const t = await getTranslations({ locale, namespace: "blog" });
const post = await getPost(slug);
const allPosts = await getPosts();
@@ -164,7 +170,10 @@ export default async function BlogPostPage({ params }: Props) {
const components: Partial<Components> = {
h1: ({ node, ...props }) => (
<h1 className="text-3xl text-primary font-bold mt-8 mb-4" {...props} />
<h1
className="text-xl md:text-2xl xl:text-3xl text-primary font-bold mt-8 mb-4"
{...props}
/>
),
h2: ({ node, ...props }) => (
<h2 className="text-2xl text-primary/90 font-bold mt-6 mb-3" {...props} />
@@ -230,7 +239,7 @@ export default async function BlogPostPage({ params }: Props) {
<ZoomableImage
src={src || ""}
alt={alt || ""}
className="object-cover max-w-lg mx-auto rounded-lg border border-border"
className="object-cover max-w-lg mx-auto rounded-lg border max-lg:w-64 border-border overflow-hidden"
/>
),
code: ({ inline, className, children, ...props }: CodeProps) => {
@@ -245,7 +254,7 @@ export default async function BlogPostPage({ params }: Props) {
};
return (
<article className="container mx-auto px-4 py-12 max-w-5xl">
<article className="container mx-auto px-4 pb-12 max-w-5xl">
<Link
href="/blog"
className="inline-flex items-center mb-8 text-primary hover:text-primary/80 transition-colors"
@@ -267,7 +276,9 @@ export default async function BlogPostPage({ params }: Props) {
<div className=" rounded-lg p-8 shadow-lg border border-border">
<header className="mb-8">
<h1 className="text-4xl font-bold mb-4">{post.title}</h1>
<h1 className="text-2xl md:text-3xl xl:text-4xl font-bold mb-4">
{post.title}
</h1>
<div className="flex items-center mb-6">
{post.primary_author?.profile_image && (
<div className="relative h-12 w-12 rounded-full overflow-hidden mr-4">

View File

@@ -2,7 +2,7 @@ import { getPosts, getTags } from "@/lib/ghost";
import type { Post } from "@/lib/ghost";
import { RssIcon } from "lucide-react";
import type { Metadata } from "next";
import { getTranslations } from "next-intl/server";
import { getTranslations, setRequestLocale } from "next-intl/server";
import Link from "next/link";
import { BlogPostCard } from "./components/BlogPostCard";
import { SearchAndFilter } from "./components/SearchAndFilter";
@@ -19,19 +19,22 @@ export const metadata: Metadata = {
};
export default async function BlogPage({
params: { locale },
params,
searchParams,
}: {
params: { locale: string };
searchParams: { [key: string]: string | string[] | undefined };
}) {
const { locale } = await params;
const searchParams2 = await searchParams;
setRequestLocale(locale);
const t = await getTranslations({ locale, namespace: "blog" });
const posts = await getPosts();
const tags = (await getTags()) as Tag[];
const search =
typeof searchParams.search === "string" ? searchParams.search : "";
typeof searchParams2.search === "string" ? searchParams2.search : "";
const selectedTag =
typeof searchParams.tag === "string" ? searchParams.tag : "";
typeof searchParams2.tag === "string" ? searchParams2.tag : "";
const filteredPosts = posts.filter((post) => {
const matchesSearch =

View File

@@ -4,6 +4,7 @@ import "react-photo-view/dist/react-photo-view.css";
import { Footer } from "@/components/Footer";
import { Header } from "@/components/Header";
import type { Metadata } from "next";
import { setRequestLocale } from "next-intl/server";
export const metadata: Metadata = {
metadataBase: new URL("https://dokploy.com"),
@@ -75,6 +76,8 @@ export default async function RootLayout({
children: React.ReactNode;
params: { locale: string };
}) {
const { locale } = await params;
setRequestLocale(locale);
return (
<div className="flex h-full flex-col">
<Header />

View File

@@ -1,5 +0,0 @@
import { SlimLayout } from "@/components/SlimLayout";
export default function NotFound() {
return <SlimLayout />;
}

View File

@@ -7,8 +7,11 @@ import { Pricing } from "@/components/pricing";
import { SecondaryFeaturesSections } from "@/components/secondary-features";
import { Sponsors } from "@/components/sponsors";
import { StatsSection } from "@/components/stats";
import { setRequestLocale } from "next-intl/server";
export default function Home() {
export default async function Home({ params }: { params: { locale: string } }) {
const { locale } = await params;
setRequestLocale(locale);
return (
<div>
<main>

View File

@@ -1,20 +1,18 @@
import { Link } from "@/i18n/routing";
import { useTranslations } from "next-intl";
export function SlimLayout() {
const t = useTranslations("404");
return (
<>
<main className="flex flex-auto items-center justify-center text-center">
<div>
<h1 className="mb-4 text-6xl font-semibold text-primary">404</h1>
<p className="mb-4 text-lg text-muted-foreground">{t("title")}</p>
<p className="mb-4 text-lg text-muted-foreground">Not found.</p>
<p className="mt-4 text-muted-foreground">
{t("des")}{" "}
Go back to home
<Link href="/" className="text-primary">
{t("action")}
Go back to home
</Link>
p{" "}
.
</p>
</div>
</main>

View File

@@ -6,8 +6,6 @@ import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
import { Container } from "./Container";
import Safari from "./ui/safari";
const features = [
{

View File

@@ -1,12 +1,15 @@
import { getRequestConfig } from "next-intl/server";
import { notFound } from "next/navigation";
import { routing } from "./routing";
export default getRequestConfig(async ({ locale }) => {
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale;
// Validate that the incoming `locale` parameter is valid
if (!routing.locales.includes(locale as any)) notFound();
if (!locale || !routing.locales.includes(locale as any)) {
locale = routing.defaultLocale;
}
return {
locale,
messages: (await import(`../locales/${locale}.json`)).default,
};
});

View File

@@ -12,7 +12,7 @@
},
"browserslist": "defaults, not ie <= 11",
"dependencies": {
"@headlessui/react": "^1.7.17",
"@headlessui/react": "^2.2.0",
"@headlessui/tailwindcss": "^0.2.0",
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-avatar": "^1.1.1",
@@ -32,8 +32,8 @@
"clsx": "^2.1.0",
"framer-motion": "^11.3.19",
"lucide-react": "0.364.0",
"next": "14.2.2",
"next-intl": "^3.19.0",
"next": "15.2.0",
"next-intl": "^3.26.5",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-ga4": "^2.1.0",