--- name: seo description: > SEO best practices for the Grida project across Next.js pages, blog posts, and documentation. Covers Next.js metadata API, Open Graph / Twitter cards, sitemaps, image search optimization, structured data (JSON-LD), Docusaurus frontmatter, and content writing for search. Use when creating or editing public-facing pages under editor/app/(www), writing blog posts, authoring docs, or reviewing SEO-related metadata. Trigger phrases: "SEO", "metadata", "sitemap", "open graph", "og image", "meta tags", "search ranking", "structured data", "JSON-LD". --- # SEO Guidelines for search engine optimization across the Grida project -- Next.js pages, blog posts, and documentation. ## Scope | Surface | Location | Framework | | ------------------------- | --------------------------------- | ---------- | | Marketing / product pages | `editor/app/(www)/` | Next.js 16 | | Blog | `docs/blog/` or `apps/docs/blog/` | Docusaurus | | Documentation | `docs/**` | Docusaurus | | Sitemaps | `editor/app/sitemap.ts` + others | Next.js | ## Next.js Pages (`editor/app/(www)`) ### Metadata Every public page must export metadata (static or dynamic). ```tsx // Static export const metadata: Metadata = { title: "Page Title — Grida", description: "Concise, keyword-rich description under 160 chars.", keywords: ["relevant", "keywords"], openGraph: { title: "Page Title — Grida", description: "Same or tailored OG description.", images: ["/og/page-name.png"], }, twitter: { card: "summary_large_image", }, }; // Dynamic export async function generateMetadata({ params }): Promise { ... } ``` **Rules:** - `title` should end with ` — Grida` (or use a `title.template` in the root layout). - `description` must be unique per page, under 160 characters, and include primary keywords. - Every page with OG images must set `metadataBase` or use absolute URLs so crawlers resolve them correctly. - OG images must return **200** without auth and use correct `Content-Type`. ### `metadataBase` When `openGraph.images` uses relative paths, the layout or page must set: ```tsx metadataBase: new URL("https://grida.co"), ``` Without this, crawlers may see broken OG URLs. ### Sitemap Public pages belong in `editor/app/sitemap.ts`. ```ts { url: "https://grida.co/new-page", changeFrequency: "monthly", priority: 0.5, } ``` - Use `priority: 1` only for the homepage. - Match `changeFrequency` to actual update cadence. - When adding a new public page, always add a sitemap entry. - Sitemaps are split per route group (root, `/packages`, `/library`, …). A new `sitemap.ts` is invisible to crawlers until it's added as a `Sitemap:` line in `editor/app/robots.txt` — non-root sitemaps are not auto-discovered. - Prefer deriving sitemap entries from the page's data source (see `packages/sitemap.ts`) over hand-maintained URL lists, which drift. ### Google Image Search Next.js `` renders optimized `/_next/image?url=...` URLs that Google Images indexes unreliably. **For pages where images are the search target** (brand assets, logos, press kits): - Use `` or plain `` so the rendered `src` is a stable, direct public URL (e.g. `/brand/grida-symbol-240.png`). - Include descriptive `alt` text with "Grida" + asset name + format. **Checklist for image assets:** - Returns **200** without cookies; not blocked for `Googlebot-Image` - Correct `Content-Type` (`image/png`, `image/svg+xml`, etc.) - Not blocked by `robots.txt` or `X-Robots-Tag` - `/_next/image` endpoint itself is not blocked (other pages still use it) - Stable, clean URLs under `public/` -- no query-string-only canonicals ### Structured Data (JSON-LD) Use JSON-LD for rich results where applicable: - **Product pages**: `Product` or `SoftwareApplication` - **Blog posts**: `BlogPosting` or `Article` - **FAQ sections**: `FAQPage` - **Brand/org**: `Organization` Embed via a `