بنقرة واحدة
create-page
// Scaffold a new page in apps/web/src/app following the project's established pattern. Use when creating any new page or route under the web app.
// Scaffold a new page in apps/web/src/app following the project's established pattern. Use when creating any new page or route under the web app.
Migrate a legacy page from apps/web/src/pages/ (Pages Router) to apps/web/src/app/ (App Router). Use when moving any existing page from the pages directory to the app directory.
Audit this Turborepo for stale or missing agent-reference docs, then refresh repo and app-level `AGENTS.md` and related onboarding docs using the bundled workspace inventory script. Use when apps, packages, routes, ports, or shared tooling changed and the repo needs a fresh agent-oriented context pass.
Upgrade llmtxt-generator.py by scanning apps/ for doc structure changes, then regenerate llms.txt and llms-en.txt while only adding missing sections. Use when updating the generator, adding new doc sections, or refreshing LLM text files.
| name | create-page |
| description | Scaffold a new page in apps/web/src/app following the project's established pattern. Use when creating any new page or route under the web app. |
| argument-hint | ["/route-path"] |
Scaffold a new page in apps/web/src/app/ following the project's established
pattern. All pages are created under the [locale] dynamic segment at
apps/web/src/app/[locale]/.
apps/web/src/app/Create a new page at route: $ARGUMENTS
If no route was provided, ask the user for the desired route path (e.g.
/hackathon, /universities/spring-2026).
Parse the route to derive:
apps/web/src/app/[locale]/ (e.g.
/universities/spring-2026 → universities/spring-2026/)universities.spring2026)Spring2026Page)spring-2026.tsx)Unless already specified, ask what content sections are needed (hero, timeline, CTA, cards, etc.).
page.tsx)This is the required entry point for every page.
Rules:
"use client"t() calls happen here, NOT in client componentst() for strings, t.raw() with type cast for arrays/objectsgenerateMetadata using getIndexMetadata from @/app/metadata{ params: Promise<{ locale: string }> }translations object
as its only prop<page-name>.tsx)Only create a separate client component when the page requires client-only
features such as useState, useEffect, useRef, event handlers, browser
APIs, or third-party client-only components.
Rules:
"use client" directive at toppage.tsx*PageProps interface with a typed translations object@/components/ where applicableAdd English keys to apps/web/public/locales/en/common.json:
privacyhack, universities)universities.hackathon.*)title and description are used by generateMetadatat.raw()en locale — other locales are handled by the i18n pipelineCheck for TypeScript issues to confirm the page builds without errors.
privacyhack/, universities/,
universities/hackathon-fall-2025/)page.tsx and translation keys are always requiredpage.tsx)When no client-only features are needed, everything lives in page.tsx:
import { getTranslations } from "next-intl/server";
import { getIndexMetadata } from "@/app/metadata";
type Props = { params: Promise<{ locale: string }> };
export default async function Page(_props: Props) {
const t = await getTranslations();
return (
<div className="overflow-hidden">
<h1>{t("pageName.hero.title")}</h1>
<p>{t("pageName.hero.subtitle")}</p>
</div>
);
}
export async function generateMetadata({ params }: Props) {
const { locale } = await params;
return await getIndexMetadata({
titleKey: "pageName.title",
descriptionKey: "pageName.description",
path: "/page-name",
locale,
});
}
page.tsx + <page-name>.tsxWhen client-only hooks/components are required, split into two files:
page.tsx (server component — handles i18n):
import { PageNamePage } from "./page-name";
import { getTranslations } from "next-intl/server";
import { getIndexMetadata } from "@/app/metadata";
type Props = { params: Promise<{ locale: string }> };
export default async function Page(_props: Props) {
const t = await getTranslations();
const translations = {
heroTitle: t("pageName.hero.title"),
heroSubtitle: t("pageName.hero.subtitle"),
// ... all translation keys passed as props
};
return <PageNamePage translations={translations} />;
}
export async function generateMetadata({ params }: Props) {
const { locale } = await params;
return await getIndexMetadata({
titleKey: "pageName.title",
descriptionKey: "pageName.description",
path: "/page-name",
locale,
});
}
<page-name>.tsx (client component — uses hooks/browser APIs):
"use client";
import React from "react";
interface PageNamePageProps {
translations: {
heroTitle: string;
heroSubtitle: string;
// ... typed translation props
};
}
export function PageNamePage({ translations }: PageNamePageProps) {
return (
<div className="overflow-hidden">{/* Sections using translations.* */}</div>
);
}
apps/web/public/locales/en/common.json)"pageName": {
"title": "Page Title | Solana",
"description": "Meta description for SEO",
"hero": {
"title": "...",
"subtitle": "..."
}
}