Files
docs-app/AGENTS.md
2026-04-01 09:38:50 +02:00

5.1 KiB

AGENTS.md

This file provides guidance to AI coding agents working in this repository.

About TinaDocs

TinaDocs is a public starter/template — anyone can fork it and deploy their own documentation site. Keep this in mind when making changes:

  • Never hardcode deployment-specific values (URLs, org names, branding). Use environment variables or TinaCMS settings instead.
  • New features that not every user will want must be toggleable via TinaCMS settings or environment variables — don't assume all consumers want the same feature set.
  • Avoid dependencies on specific hosting providers. Support multiple deployment modes (Vercel, GitHub Pages, static export).

Architecture

TinaDocs is a documentation platform built on Next.js 15 (App Router) with TinaCMS for git-based content management, Pagefind for static search, and Tailwind CSS with a 6-theme system.

Content flow: MDX files in content/docs/ → TinaCMS schema (tina/collections/) → auto-generated GraphQL client (tina/__generated__/) → Next.js pages. Never edit files in tina/__generated__/.

Key directories

  • src/app/ — Next.js App Router pages and API routes
  • src/components/tina-markdown/ — Markdown rendering: standard-elements/ (headings, code blocks, tables) and embedded-elements/ (API refs, callouts, recipes)
  • tina/collections/ — TinaCMS collection schemas (docs, API schemas, navigation, settings)
  • tina/templates/markdown-embeds/ — Embeddable content templates (accordion, callout, code-tabs, card-grid, etc.)
  • tina/customFields/ — Custom CMS field components (theme selector, file upload, Monaco editor)
  • src/styles/global.css — Theme definitions via CSS custom properties (6 themes, light/dark)

Commands

pnpm install                    # Install deps (pnpm 9.15.2 required)
pnpm dev                        # Dev server with Turbopack (localhost:3000, CMS at /admin)
pnpm build                      # Production build (TinaCMS + Next.js + Pagefind + sitemap)
pnpm lint                       # Biome linter check
pnpm lint:fix                   # Auto-fix lint issues
pnpm test                       # Playwright E2E tests (Chromium)
pnpm test:ui                    # Playwright interactive UI
pnpm build-local-pagefind       # Rebuild search index locally
npx playwright test tests/e2e/some-test.spec.ts  # Run a single test

Coding Standards

  • Use @/ path aliases for imports: @/components, @/utils, @/app, @/tina, @/services, @/hooks, @/styles, @/content, @/lib, @/types, @/config
  • Use Biome for formatting: 2-space indent, double quotes, semicolons, trailing commas (ES5)
  • No console.log — use noConsole: error
  • No .forEach() — use for...of or .map()
  • Self-close empty JSX elements

Key Patterns

Fetching TinaCMS data in pages

import { fetchTinaData } from "@/services/tina/fetch-tina-data";
import client from "@/tina/__generated__/client";

async function getData(slug: string) {
  return await fetchTinaData(client.queries.docs, slug);
}

export default async function DocsPage({
  params,
}: {
  params: Promise<{ slug: string[] }>;
}) {
  const { slug } = await params;
  const data = await getData(slug.join("/"));

  return (
    <TinaClient
      Component={Document}
      props={{ query: data.query, variables: data.variables, data: data.data }}
    />
  );
}

Adding a new embeddable template

  1. Define template in tina/templates/markdown-embeds/my-embed.template.tsx:
export const MyEmbedTemplate = {
  name: "myEmbed",
  label: "My Embed",
  fields: [
    { type: "string", name: "title", label: "Title" },
    { type: "rich-text", name: "body", label: "Body" },
  ],
};
  1. Create component in src/components/tina-markdown/embedded-elements/my-embed.tsx:
import { tinaField } from "tinacms/dist/react";
import { TinaMarkdown, type TinaMarkdownContent } from "tinacms/dist/rich-text";
import { MarkdownComponentMapping } from "../markdown-component-mapping";

export default function MyEmbed(props: { title: string; body?: TinaMarkdownContent }) {
  return (
    <div data-tina-field={tinaField(props, "title")}>
      <h3>{props.title}</h3>
      <TinaMarkdown content={props.body as TinaMarkdownContent} components={MarkdownComponentMapping} />
    </div>
  );
}
  1. Register template in tina/collections/docs.tsx — add to the templates array in the body rich-text field
  2. Map component in src/components/tina-markdown/markdown-component-mapping.tsx:
myEmbed: (props) => <MyEmbed {...props} />,

TinaCMS component conventions

  • Use tinaField(props, "fieldName") on data-tina-field attributes for visual editing
  • Render nested rich-text with <TinaMarkdown content={...} components={MarkdownComponentMapping} />
  • Define variant/config mappings as const objects with as const

Environment

Copy .env.example. Required: NEXT_PUBLIC_TINA_CLIENT_ID, TINA_TOKEN, NEXT_PUBLIC_TINA_BRANCH (from app.tina.io). Optional: NEXT_PUBLIC_SITE_URL, NEXT_PUBLIC_GTM_ID, NEXT_PUBLIC_BASE_PATH.