From 7e0406f4ec4862f1570c98f7eb00bf35b9deb02e Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 20 May 2026 14:26:09 +0900 Subject: [PATCH] fix(web): UX/a11y polish + middleware metadata route fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - footer.tsx: Discord link → canonical discord.gg/PUwSMR9XNk (was outdated invite that 404'd). - [locale]/layout.tsx: hooks count 40 → 54 (matches AGENTS.md). - lib/stats.ts:88: drop '!' non-null assertion; use '??' fallback. Removes the only '!' in packages/web (project rule). - nav-header.tsx: hamburger Button size='icon' → explicit h-11 w-11; mobile drawer links min-h-11 px-3 rounded-md. WCAG 2.5.5 tap target 44x44 minimum. - install-command.tsx: copy button h-8 w-8 → h-11 w-11 (was 32px, below WCAG). Icon stays 16x16; padding fills to 44. - middleware.ts: matcher excludes opengraph-image, twitter-image, icon, apple-icon, manifest.webmanifest, robots.txt, sitemap.xml. Previously next-intl redirected /opengraph-image → /en/opengraph-image breaking OG previews for crawlers that hit the unlocalized path. --- packages/web/app/[locale]/layout.tsx | 8 ++++---- packages/web/components/footer.tsx | 5 +++-- .../components/landing/install-command.tsx | 2 +- packages/web/components/nav-header.tsx | 19 ++++++++++--------- packages/web/lib/stats.ts | 12 ++++++++++-- packages/web/middleware.ts | 12 ++++++++++-- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/packages/web/app/[locale]/layout.tsx b/packages/web/app/[locale]/layout.tsx index 80f2cfaee..f16984d36 100644 --- a/packages/web/app/[locale]/layout.tsx +++ b/packages/web/app/[locale]/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata } from "next" -import type { JSX } from "react" +import type { JSX, ReactNode } from "react" import { notFound } from "next/navigation" import { hasLocale } from "next-intl" import { setRequestLocale } from "next-intl/server" @@ -8,10 +8,10 @@ import { routing } from "@/i18n/routing" export const metadata: Metadata = { description: - "Meet Sisyphus: The batteries-included agent that codes like you. Multi-model orchestration, background agents, 40+ lifecycle hooks.", + "Meet Sisyphus: The batteries-included agent that codes like you. Multi-model orchestration, background agents, 54+ lifecycle hooks.", } -export function generateStaticParams() { +export function generateStaticParams(): Array<{ readonly locale: string }> { return routing.locales.map((locale) => ({ locale })) } @@ -19,7 +19,7 @@ export default async function LocaleLayout({ children, params, }: { - children: React.ReactNode + children: ReactNode params: Promise<{ locale: string }> }): Promise { const { locale } = await params diff --git a/packages/web/components/footer.tsx b/packages/web/components/footer.tsx index 554a50aba..9f671f06e 100644 --- a/packages/web/components/footer.tsx +++ b/packages/web/components/footer.tsx @@ -1,7 +1,8 @@ +import type { JSX } from "react" import { getTranslations } from "next-intl/server" import { Link } from "@/i18n/routing" -export async function Footer({ locale }: { locale?: string } = {}) { +export async function Footer({ locale }: { readonly locale?: string } = {}): Promise { const t = locale ? await getTranslations({ locale, namespace: "footer" }) : await getTranslations("footer") @@ -27,7 +28,7 @@ export async function Footer({ locale }: { locale?: string } = {}) { {t("github")} diff --git a/packages/web/components/nav-header.tsx b/packages/web/components/nav-header.tsx index 39ee438aa..057a60fef 100644 --- a/packages/web/components/nav-header.tsx +++ b/packages/web/components/nav-header.tsx @@ -1,5 +1,6 @@ "use client" +import type { JSX } from "react" import { useState } from "react" import { useTranslations } from "next-intl" import { Menu, X } from "lucide-react" @@ -7,7 +8,7 @@ import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Link } from "@/i18n/routing" -function GitHubMark({ className }: { readonly className?: string }) { +function GitHubMark({ className }: { readonly className?: string }): JSX.Element { return (