import type { Metadata } from "next" import { getTranslations, getMessages, setRequestLocale } from "next-intl/server" import { Link } from "@/i18n/navigation" import Image from "next/image" import { ExternalLink, HardDrive, MonitorCog, Laptop } from "lucide-react" import { DocHeader } from "@/components/ui/doc-header" import { Callout } from "@/components/ui/callout" export async function generateMetadata({ params, }: { params: Promise<{ locale: string }> }): Promise { const { locale } = await params const t = await getTranslations({ locale, namespace: "docs.createVm.meta" }) return { title: t("title"), description: t("description"), keywords: [ "proxmox create vm", "proxmox synology vm", "proxmox windows vm", "proxmox truenas vm", "proxmox unraid vm", "proxmox openmediavault", "proxmox vm wizard", "proxmox nas vm", "proxmox dsm", "proxmenux create vm", ], alternates: { canonical: "https://proxmenux.com/docs/create-vm" }, openGraph: { title: t("ogTitle"), description: t("ogDescription"), type: "article", url: "https://proxmenux.com/docs/create-vm", images: [ { url: "/vm/vm-creation-menu.png", width: 1200, height: 630, alt: t("ogImageAlt"), }, ], }, twitter: { card: "summary_large_image", title: t("twitterTitle"), description: t("twitterDescription"), }, } } type Route = { key: string title: string icon: string href: string accent: string iconBg: string description: string bullets: string[] } type StringItem = string type ScriptRowData = { path: string; role: string } type RelatedItem = { href: string; label: string; tail?: string } const ICONS: Record> = { HardDrive, MonitorCog, Laptop, } function ScriptRow({ path, role }: { path: string; role: string }) { return ( {path} {role} ) } export default async function CreateVMOverviewPage({ params, }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) const t = await getTranslations({ locale, namespace: "docs.createVm" }) const messages = (await getMessages({ locale })) as unknown as { docs: { createVm: { families: { routes: Route[] } afterPick: { items: StringItem[] } scripts: { rows: ScriptRowData[] } related: { items: RelatedItem[] } } } } const routes = messages.docs.createVm.families.routes const afterPickItems = messages.docs.createVm.afterPick.items const scriptRows = messages.docs.createVm.scripts.rows const relatedItems = messages.docs.createVm.related.items const code = (chunks: React.ReactNode) => {chunks} const strong = (chunks: React.ReactNode) => {chunks} const em = (chunks: React.ReactNode) => {chunks} const osxLink = (chunks: React.ReactNode) => ( {chunks} ) return (
{t("intro.body")}

{t("opening.heading")}

{t.rich("opening.body", { strong })}

{t("opening.imageAlt")}

{t("families.heading")}

{t("families.intro")}

{routes.map((route) => { const Icon = ICONS[route.icon] || HardDrive return (

{route.title}

{route.description}

    {route.bullets.map((b, i) => (
  • {b}
  • ))}
) })}
{t.rich("community.intro", { em, strong })}
  • {t.rich("community.macosRich", { strong, osxLink })}
  • {t.rich("community.othersRich", { strong })}

{t("afterPick.heading")}

{t("afterPick.intro")}

    {afterPickItems.map((_, idx) => (
  1. {t.rich(`afterPick.items.${idx}`, { strong, code })}
  2. ))}
{t.rich("afterPick.tipBody", { code })}

{t("scripts.heading")}

{t("scripts.intro")}

{scriptRows.map((row) => ( ))}
{t("scripts.headerScript")} {t("scripts.headerRole")}

{t("related.heading")}

    {relatedItems.map((item) => (
  • {item.label} {item.tail}
  • ))}
) }