Ctrl K
ComunidadGuías…

AGENTS.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# TinaCMS Monorepo

## Project Overview

TinaCMS is an open-source headless CMS with visual editing. This monorepo contains the core packages, CLI, admin app, and framework example apps.

## Security & Disclosure

This repo has a public security policy at [`SECURITY.md`](SECURITY.md). Read it before touching code that could surface a vulnerability (auth, media routes, path handling, GraphQL resolvers, anything that accepts untrusted input).

**Hard rules:**

- **Never file security vulnerabilities as public GitHub issues.** Reports go to `security@tina.io`, or as a draft GitHub Security Advisory. Public issues are explicitly forbidden by `SECURITY.md`, regardless of severity.
- **Never put bug specifics in test comments, PR descriptions, or commit messages.** That's public disclosure by a different name. If a test guards against a known-broken behaviour, use neutral wording (e.g. *"Pending upstream fix reported privately per SECURITY.md"*) and keep the internals — error messages, stack traces, affected function names, response-body specifics — out of the comment.
- **Don't commit, push, or draft a public issue if you find a potential vulnerability.** Stop, tell the user what you found and where, and let them decide the disclosure path (email, draft advisory, or public if they judge it's truly benign).

**Scope of the above rules:** every surface an agent might modify — source files, test files, inline comments, commit messages, PR descriptions, linked issue drafts, README snippets.

When writing regression tests that guard against a quietly-reported finding, mark the specific case with `test.fixme` (Playwright) or the framework equivalent, use a generic "pending upstream fix" message, and put the detail in a private channel only.

## Monorepo Structure

```
adr/v4/                # v4 architecture: ADRs, CONTEXT.md domain language, supporting docs
packages/              # Core packages (tinacms, tinacms-authjs, create-tina-app, etc.)
packages/@tinacms/     # Scoped packages (cli, app, datalayer, graphql, mdx, scripts, etc.)
examples/              # Framework example apps
  next/kitchen-sink/   # Next.js 15 — the reference kitchen-sink implementation
  next/tina-self-hosted-demo/ # Self-hosted with auth
  astro/kitchen-sink/  # Astro 6 — mirrors Next.js kitchen-sink
  hugo/kitchen-sink/   # Hugo kitchen-sink
  react/kitchen-sink/  # React kitchen-sink
  shared/              # Shared content and public assets across kitchen-sink examples
playwright/            # Playwright test infrastructure
scripts/               # Repo maintenance scripts
tests/                 # Build verification tests
```

## Build & Dev Commands

- **Install:** `pnpm install` (from repo root)
- **Build core packages:** `pnpm build` (runs `turbo run build --filter="./packages/**"`)
- **Watch mode:** `pnpm dev` (builds then watches via `@tinacms/scripts`)
- **Test:** `pnpm test` (runs `turbo run test --filter="./packages/**"`)
- **Example apps:** Each has its own `dev`, `build`, `build:local` scripts — check the example's `package.json`

## Workspace Configuration

- `pnpm-workspace.yaml` defines workspace packages and a `catalog:` section for shared dependency versions
- Example apps use `workspace:*` to reference local TinaCMS packages
- Published packages must use `workspace:^` for internal refs in `dependencies`/`peerDependencies` (`devDependencies` are exempt). pnpm publishes it as a caret range so npm can dedupe; `workspace:*` publishes an exact pin that nests duplicate dependency trees (#7207). Enforced by `tests/workspace-protocol.test.ts`.
- Because published dependents float across caret ranges, internal APIs consumed by sibling published packages are compatibility contracts within a major: an already-published `@tinacms/cli`/`@tinacms/app` may run against a newer `tinacms`. Breaking such an API requires a major bump.
- `turbo.json` defines build/test/types task dependencies

## Coding Standards

- **Comments are a last resort.** Write code that explains itself; comment only what the code cannot say (a non-obvious invariant, a documented workaround). No narrated comments, no restating what the next line does, no essay-length headers riding on a few lines of code.
- **Error narrowing is an `if`, not an expression.** Use `if (err instanceof Error) { … } else { … }` — never `(err instanceof Error && err.message) || fallback` or a ternary that smuggles narrowing into an expression. Lint enforces this in `packages/v4` only.
- **Linting/Formatting:** Biome (`biome.json` at root). Example apps extend it with `"root": false, "extends": "//"` so the root plugin paths resolve.
- **TypeScript:** Base config at `base.tsconfig.json`. Examples extend it. Strict mode enabled.
- **Package manager:** pnpm only. Never use npm or yarn. One deliberate exception: the size-baseline harness (`scripts/size-baseline.mjs` + `tests/size-fixture/`) shells out to real `npm`, because npm's nested-duplicate hoisting is exactly the regression it measures — pnpm's content-addressed store would hide it.
- **`CLAUDE.md` files** are git symlinks to the sibling `AGENTS.md`. On Windows without Developer Mode, if `git status` shows `TT` typechanges on them, run `git config --local core.symlinks false` — git then materialises them as regular pointer files. Linux/macOS clones get real symlinks automatically.

## Kitchen-Sink Examples

All kitchen-sink examples implement the **same content model** to demonstrate identical functionality across frameworks. `examples/next/kitchen-sink/` is the reference implementation.

### Unified Content Schema

| Collection | Format | Content Path | Collection File |
|------------|--------|-------------|-----------------|
| Tag | JSON | `content/tags/` | `tina/collections/tag.ts` |
| Author | MD | `content/authors/` | `tina/collections/author.tsx` |
| Post | MDX | `content/posts/` | `tina/collections/post.tsx` |
| Blog | MDX | `content/blogs/` | `tina/collections/blog.tsx` |
| Page | MDX | `content/pages/` | `tina/collections/page.tsx` |
| Global | JSON | `content/global/` | `tina/collections/global.ts` |

Note: `.tsx` collection files contain JSX for custom field components (e.g., ColorPickerInput in `global.ts` theme field). `.ts` files are pure schema definitions. This applies across all kitchen-sink examples.

### Shared Patterns Across Kitchen-Sink Apps

- TinaCMS wraps the framework dev server: `tinacms dev -c "<framework dev>"`
- Build order: `tinacms build && <framework build>`
- Content lives in `content/` with identical MDX/JSON files across examples
- Tina config at `tina/config.tsx` with collections in `tina/collections/`
- Admin UI output to `public/admin/`
- Media root: `uploads/` within `public/`

### Standardized Stack

| Tool | Choice |
|------|--------|
| Package Manager | pnpm (workspace-native) |
| Linting/Formatting | Biome (extends root config) |
| Styling | Tailwind CSS 4 (CSS-first config) |
| TypeScript | 5.7+ strict (extends `base.tsconfig.json`) |

## Filing Issues

Bug reports go through the same checklist whether they land via Discord `#ask-for-help`, the GitHub issue form, or an agent calling `gh api`. The canonical source is `.github/ISSUE_TEMPLATE/bug-report.yml`, mirrored in the Discord post guidelines and at https://tina.io/docs/contributing/bug-reports.

**Required H3 sections** (use these exact headings when formatting an issue body programmatically):

- `### Describe the bug` — what is going wrong, in prose; the literal error text belongs in its own section below
- `### Your environment` — versions, framework, **and anything non-default** (custom MediaStore, custom auth, self-hosted setup, etc.)

**Optional but encouraged:**

- `### The exact error message` — copy-pasted literal string, not paraphrased
- `### Steps to reproduce` — what the user clicked, in order
- `### What you expected vs. what actually happened`
- `### A way for us to reproduce` — link to a minimal repro repo
- `### Client ID` — for TinaCloud-related issues

If you're an agent (Claude Code, Cursor, ChatGPT, an internal bot like `ssw-yakshaver`) drafting an issue programmatically, format the body with those H3 headings before calling `POST /repos/{owner}/{repo}/issues`. Omit a section you have nothing for rather than writing `_No response_` under it: `.github/workflows/strip-empty-issue-sections.yml` strips those from a form submission, but only one carrying the `bug` label, so an issue filed through the API keeps whatever it was sent.

The non-default-setup detail in `### Your environment` is the field that most often points us straight at the root cause. Do not omit it.

## Issue Triage & Labels

This repo uses a fixed label taxonomy for backlog organisation, defined in [`.github/issue-labels.json`](.github/issue-labels.json). Read it before filing or triaging issues. Apply exactly **one** label from `primary` (the most specific that fits), plus any `program` or `scope` labels that apply.

### Triage rules

- **New issues are auto-classified.** `.github/workflows/classify-issue.yml` asks Jev for the primary category (and `onboarding`/`🤖AI`) using the same JSON file, so editing it updates both.
- **Taxonomy is fixed.** Don't invent new category labels. If nothing fits, leave the label off and surface the issue for human triage.
- **Don't apply `onboarding` or `🤖AI` to v4-program issues** — those are intentionally coordinated work.
- **Closing an issue:** always link evidence (PR number, comment URL, "fixed in version X.Y") in the closing comment. If the issue is a meta-tracker blocked on a parent epic, leave a "Triage note — do not close" comment instead.
- **Re-test pings:** when the linked PR has merged but no one has confirmed the fix sticks, comment asking the original reporter to verify on the current setup before closing.

### Useful filter URLs

- Onboarding: <https://github.com/tinacms/tinacms/labels/onboarding>
- AI-doable (one prompt): <https://github.com/tinacms/tinacms/labels/%F0%9F%A4%96AI>
- v4 program: <https://github.com/tinacms/tinacms/labels/v4.0> · <https://github.com/tinacms/tinacms/labels/For%204.1>