diff --git a/.github/workflows/docs-self-healing.yml b/.github/workflows/docs-self-healing.yml index 70dd93ccb3..54f64f0422 100644 --- a/.github/workflows/docs-self-healing.yml +++ b/.github/workflows/docs-self-healing.yml @@ -273,7 +273,7 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_SELF_HEALING_DOCS_API_KEY }} github_token: ${{ secrets.PAT_TOKEN_PIWI }} prompt: ${{ steps.load-triage-prompt.outputs.prompt }} - claude_args: '--model claude-haiku-4-5-20251001 --max-turns 10 --allowedTools "Bash,Read"' + claude_args: '--model claude-haiku-4-5-20251001 --max-turns 20 --allowedTools "Bash,Read"' show_full_output: true env: FILTERED_PRS: ${{ steps.check-prs.outputs.pr_list }} @@ -484,7 +484,7 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_SELF_HEALING_DOCS_API_KEY }} github_token: ${{ secrets.PAT_TOKEN_PIWI }} prompt: ${{ steps.load-drafter-prompt.outputs.prompt }} - claude_args: '--model claude-sonnet-4-6 --max-turns 25 --allowedTools "Bash,Read,Write,Edit,Glob,Grep"' + claude_args: '--model claude-sonnet-4-6 --max-turns 50 --allowedTools "Bash,Read,Write,Edit,Glob,Grep"' show_full_output: true env: DOC_REPO: ${{ github.workspace }} diff --git a/.github/workflows/sync-content-to-next.yml b/.github/workflows/sync-content-to-next.yml index 2e73645a2e..3ab0c85c23 100644 --- a/.github/workflows/sync-content-to-next.yml +++ b/.github/workflows/sync-content-to-next.yml @@ -11,6 +11,9 @@ on: pull_request: types: [labeled, closed] +env: + TARGET_BRANCH: repo/redesign-v7-cutover + jobs: # Job for debugging purposes debug-event: @@ -91,17 +94,17 @@ jobs: PR_TITLE="${{ github.event.pull_request.title }}" SOURCE_BRANCH="${{ github.event.pull_request.head.ref }}" SOURCE_REPO="${{ github.event.pull_request.head.repo.full_name }}" - TARGET_BRANCH="next-port-pr$PR_NUMBER" - + HEAD_BRANCH="next-port-pr$PR_NUMBER" + echo "Source Branch: $SOURCE_BRANCH" echo "Source Repo: $SOURCE_REPO" - echo "Target Branch: $TARGET_BRANCH" - - # Fetch next branch - git fetch origin next - - # Create new branch based on next - git checkout -b $TARGET_BRANCH origin/next + echo "Head Branch: $HEAD_BRANCH" + + # Fetch sync target branch + git fetch origin "$TARGET_BRANCH" + + # Create new branch based on the sync target branch + git checkout -b $HEAD_BRANCH "origin/$TARGET_BRANCH" # Fetch source branch if [ "$SOURCE_REPO" != "${{ github.repository }}" ]; then @@ -162,15 +165,15 @@ jobs: run: | # Commit changes - force commit even if git thinks there are no changes git add . - git commit --allow-empty -m "Port PR #${{ github.event.pull_request.number }}: ${{ github.event.pull_request.title }} to next branch" + git commit --allow-empty -m "Port PR #${{ github.event.pull_request.number }}: ${{ github.event.pull_request.title }} to the redesign branch" # Push branch git push origin next-port-pr${{ github.event.pull_request.number }} # Create PR with a special tag in the body to identify it later - PR_CMD="gh pr create --base next --head next-port-pr${{ github.event.pull_request.number }} \ + PR_CMD="gh pr create --base \"$TARGET_BRANCH\" --head next-port-pr${{ github.event.pull_request.number }} \ --title \"${{ steps.load-config.outputs.title_prefix }} ${{ github.event.pull_request.title }}\" \ - --body \"Automatic port of PR #${{ github.event.pull_request.number }} to next branch.\n\nOriginal PR: #${{ github.event.pull_request.number }}\nCreated automatically after adding the 'temp - port to docs-next' label.\n\n\" \ + --body \"Automatic port of PR #${{ github.event.pull_request.number }} to the redesign branch.\n\nOriginal PR: #${{ github.event.pull_request.number }}\nCreated automatically after adding the 'temp - port to docs-next' label.\n\n\" \ --assignee ${{ steps.load-config.outputs.assignee }}" # Add labels if configured @@ -238,7 +241,7 @@ jobs: PR_NUMBER="${{ github.event.pull_request.number }}" # Check if there's an existing PR - EXISTING_PR_NUMBER=$(gh pr list --base next --head "next-port-pr$PR_NUMBER" --state open --json number --jq '.[0].number') + EXISTING_PR_NUMBER=$(gh pr list --base "$TARGET_BRANCH" --head "next-port-pr$PR_NUMBER" --state open --json number --jq '.[0].number') if [ -n "$EXISTING_PR_NUMBER" ]; then echo "Existing PR found: #$EXISTING_PR_NUMBER" @@ -287,15 +290,15 @@ jobs: echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT fi - # Create branch from next - git fetch origin next - + # Create branch from the sync target branch + git fetch origin "$TARGET_BRANCH" + if [ "${{ steps.check-existing.outputs.strategy }}" = "update" ]; then echo "Checking out existing branch $BRANCH_NAME" - git checkout $BRANCH_NAME || git checkout -b $BRANCH_NAME origin/next + git checkout $BRANCH_NAME || git checkout -b $BRANCH_NAME "origin/$TARGET_BRANCH" else echo "Creating new branch $BRANCH_NAME" - git checkout -b $BRANCH_NAME origin/next + git checkout -b $BRANCH_NAME "origin/$TARGET_BRANCH" fi # Try to cherry-pick @@ -329,16 +332,16 @@ jobs: PR_TITLE="${{ github.event.pull_request.title }}" # Create the new PR first - PR_CMD="gh pr create --base next --head $BRANCH_NAME \ + PR_CMD="gh pr create --base \"$TARGET_BRANCH\" --head $BRANCH_NAME \ --title \"${{ steps.load-config.outputs.title_prefix }} $PR_TITLE\" \ - --body \"Synchronization of merged PR #${{ github.event.pull_request.number }} to next branch. This PR contains the final state of the changes as they were merged to main.\" \ + --body \"Synchronization of merged PR #${{ github.event.pull_request.number }} to the redesign branch. This PR contains the final state of the changes as they were merged to main.\" \ --assignee ${{ steps.load-config.outputs.assignee }}" - + # Add labels if configured if [ -n "${{ steps.load-config.outputs.labels }}" ]; then PR_CMD="$PR_CMD --label ${{ steps.load-config.outputs.labels }}" fi - + NEW_PR=$(eval "$PR_CMD --json number --jq '.number'") # Now close the existing PR with a reference to the new one @@ -352,10 +355,10 @@ jobs: BRANCH_NAME="${{ steps.create-branch.outputs.branch_name }}" PR_TITLE="${{ github.event.pull_request.title }}" - # Create new PR - PR_CMD="gh pr create --base next --head $BRANCH_NAME \ + # Create new PR + PR_CMD="gh pr create --base \"$TARGET_BRANCH\" --head $BRANCH_NAME \ --title \"${{ steps.load-config.outputs.title_prefix }} $PR_TITLE\" \ - --body \"Synchronization of merged PR #${{ github.event.pull_request.number }} to next branch. This PR contains the final state of the changes as they were merged to main.\" \ + --body \"Synchronization of merged PR #${{ github.event.pull_request.number }} to the redesign branch. This PR contains the final state of the changes as they were merged to main.\" \ --assignee ${{ steps.load-config.outputs.assignee }}" # Add labels if configured @@ -430,18 +433,18 @@ jobs: exit 0 fi - # Create branch from next + # Create branch from the sync target branch BRANCH_NAME="sync-push-$(date +%Y%m%d-%H%M%S)" - - git fetch origin next - git checkout -b $BRANCH_NAME origin/next + + git fetch origin "$TARGET_BRANCH" + git checkout -b $BRANCH_NAME "origin/$TARGET_BRANCH" # Try to cherry-pick if git cherry-pick $COMMIT_HASH; then git push origin $BRANCH_NAME # Create PR - PR_CMD="gh pr create --base next --head $BRANCH_NAME \ + PR_CMD="gh pr create --base \"$TARGET_BRANCH\" --head $BRANCH_NAME \ --title \"${{ steps.load-config.outputs.title_prefix }} $COMMIT_MSG\" \ --body \"Automatic sync of commit from main\" \ --assignee ${{ steps.load-config.outputs.assignee }}" diff --git a/.gitignore b/.gitignore index 6fb3b4fc69..f547ab8787 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ docs/superpowers/ # Inki plugin run logs, in case a user points --log-dir at a local .inki/ folder. # By default logs go to ~/.inki/logs/ (outside any repo); this is a safety net. .inki/ + +# Playwright MCP local artifacts (snapshots, screenshots, console logs) created +# during local visual QA. Never tracked. +.playwright-mcp/ diff --git a/AGENTS.md b/AGENTS.md index 133f428eac..dbf7d4d410 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,7 +77,7 @@ Path‑based policy (applies to folders and all subfolders): ### Key files - AI toolbar: `docusaurus/src/components/AiToolbar/openLLM.js`, `.../config/aiToolsConfig.js`, `.../config/aiPromptTemplates.js` - Generators/validators: `docusaurus/scripts/generate-llms-code.js`, `docusaurus/scripts/generate-llms.js`, `docusaurus/scripts/validate-prompts.js` -- Authoring templates: `claude-plugins/inki/references/templates/*.md` (see `claude-plugins/inki/references/templates/INDEX.md`) +- Authoring templates: `claude-plugins/inki/references/templates/*.md` (see `claude-plugins/inki/references/templates/README.md`) - Agent prompts: `claude-plugins/inki/references/prompts/` (see table in Documentation Review System section) - Components guidance: `claude-plugins/inki/references/templates/components/tabs.md` (Tabs/TabItem rules) - Configuration: `docusaurus.config.js`, `sidebars.js`, `package.json` diff --git a/claude-plugins/inki/references/authoring/AGENTS.cms.api.md b/claude-plugins/inki/references/authoring/AGENTS.cms.api.md index f520cfdc09..c31ef064e3 100644 --- a/claude-plugins/inki/references/authoring/AGENTS.cms.api.md +++ b/claude-plugins/inki/references/authoring/AGENTS.cms.api.md @@ -15,7 +15,7 @@ Frontmatter (mandatory) Templates - Start from `claude-plugins/inki/references/templates/api-template.md` to align sections and example layout. -- See `claude-plugins/inki/references/templates/INDEX.md` for a quick catalog of available templates with paths and purposes. +- See `claude-plugins/inki/references/templates/README.md` for a quick catalog of available templates with paths and purposes. API Overview Pages (e.g., Content API) 1) H1 title — matches `title` frontmatter. @@ -50,13 +50,26 @@ Heading Conventions Component Patterns by Page Type -API pages use custom MDX components that vary by sub-section. When editing an existing page, always match the page's established patterns: +API pages use custom MDX components that vary by sub-section. When editing an existing page, always match the page's established patterns. `` is the current component for all reference endpoints. See `claude-plugins/inki/references/templates/components/endpoint.md` for the full `` contract and copy-pasteable examples. -- **Document Service API pages** use `` with `` / `` for code examples. The `noSideBySide` prop is used for longer examples. Response code blocks use JS object literal notation (not JSON). -- **REST API pages** use `` wrapping ``, a `
` block for the `qs.stringify` equivalent, and ``. Snippet imports (`QsForQueryBody`, `QsForQueryTitle`, `QsIntroFull`) are used inside the `
` blocks. Response code blocks use JSON. +``, ``, and `` are registered as global MDX components in `docusaurus/src/theme/MDXComponents.js` (like ``, ``, and ``), so they are used directly with no import line. + +- **Document Service API pages** use ``. `path` is the JS method signature (e.g. `strapi.documents().findOne()`). `params={[{ name, type, required, description }]}`, where the `description` may contain inline HTML (``, ``). `codeTabs={[{ label: 'Request', code: \`...\` }]}` holds the example(s); multiple example tabs are idiomatic. `responses` render under a "Returns" label rather than an HTTP status. The final block on the page uses `isLast={true}`. Admonitions go INSIDE the block as children: use a closing `` tag instead of self-closing `/>`, open with `>`, leave a blank line, write the `:::tip` / `:::note`, leave a blank line, then ``. +- **REST API pages** use `` with `kind="http"` (the default, so it can be omitted): `method`, `path` with `:params` (e.g. `/api/:pluralApiId/:documentId`), `codePath` + `codePathHighlights` for the URL bar shown in the code panel, and `codeTabs` (e.g. cURL + JavaScript). `responses` take `{ status, statusText, time?, body: JSON.stringify(..., null, 2) }`; multiple responses render as colored status tabs (e.g. 200 + 404). A DELETE endpoint with no response body uses `responses={[]}` together with `isLast`. The snippet imports `QsForQueryBody`, `QsForQueryTitle`, and `QsIntroFull` remain valid and are used alongside `` on migrated REST pages (they are NOT legacy). - **GraphQL API pages** use plain code blocks with `graphql` language identifier for query examples. -Do not mix patterns across page types (e.g., do not use `
` on a Document Service page, or plain code blocks where `` is expected). +Do not mix patterns across page types: use `` for all new, REST, and Document Service reference endpoints. The legacy ``/``/`` trio is an exception that applies ONLY to the not-yet-migrated pages listed below. + +Legacy (not-yet-migrated) pages +- The legacy `` / `` / `` trio (plus the `noSideBySide` prop and the `
` block wrapping the `qs.stringify` equivalent) is DEPRECATED for new content. Match it ONLY when patching these specific not-yet-migrated pages: + - `docs/cms/api/graphql.md` + - `docs/cms/api/graphql/**` (e.g. `graphql/locale.md`) + - `docs/cms/api/rest/upload.md` + - `docs/cms/api/rest/relations.md` + - `docs/cms/features/users-permissions/rest-api.md` + - `docs/cms/plugins/graphql.md` +- Never introduce the ``/``/`` trio on new, REST, or Document Service reference pages. +- NOTE: `QsForQueryBody` / `QsForQueryTitle` / `QsIntroFull` are NOT legacy: they are snippet imports still used alongside `` on migrated REST pages. Cross‑linking - Link to neighboring APIs (Content API, Query Engine), relevant features, and migration notes. diff --git a/claude-plugins/inki/references/authoring/AGENTS.cms.md b/claude-plugins/inki/references/authoring/AGENTS.cms.md index c2299cc5c3..977813ef5a 100644 --- a/claude-plugins/inki/references/authoring/AGENTS.cms.md +++ b/claude-plugins/inki/references/authoring/AGENTS.cms.md @@ -15,7 +15,7 @@ Frontmatter and structure Templates - CMS authoring templates live in `claude-plugins/inki/references/templates/` (guide, API, configuration, feature, migration, plugin). Start from a template to ensure structure and frontmatter are correct. -- For a quick overview of available templates (paths and purposes), see `claude-plugins/inki/references/templates/INDEX.md`. +- For a quick overview of available templates (paths and purposes), see `claude-plugins/inki/references/templates/README.md`. MDX and code blocks - Use MDX Tabs for language variants (JS/TS) under the same example. diff --git a/claude-plugins/inki/references/authoring/AGENTS.snippets.md b/claude-plugins/inki/references/authoring/AGENTS.snippets.md index ef9b38caa3..cdc74b0d60 100644 --- a/claude-plugins/inki/references/authoring/AGENTS.snippets.md +++ b/claude-plugins/inki/references/authoring/AGENTS.snippets.md @@ -41,4 +41,4 @@ Quality Checklist (before commit) Templates - When a snippet evolves into a full page, prefer starting from a suitable CMS template: -- For a compact overview of all templates with paths and purposes, see `claude-plugins/inki/references/templates/INDEX.md`. +- For a compact overview of all templates with paths and purposes, see `claude-plugins/inki/references/templates/README.md`. diff --git a/claude-plugins/inki/references/prompts/drafter.md b/claude-plugins/inki/references/prompts/drafter.md index 60a3a6c75a..1fd05f7381 100644 --- a/claude-plugins/inki/references/prompts/drafter.md +++ b/claude-plugins/inki/references/prompts/drafter.md @@ -203,13 +203,15 @@ If `existing_content` is not already provided: If `target.existing_section` is set, locate that section in the fetched content and focus on it. Keep the surrounding context available for reference. After fetching, analyze the page's **component patterns** before deriving edits: -- What components wrap code examples? (``, ``, plain code blocks?) -- What snippet imports does the page use? (e.g., ``) -- How are Request/Response pairs structured? (side-by-side vs. stacked, with or without titles?) -- Does the page use `
` blocks? If so, are they standalone or nested inside ``? +- What components wrap code examples? (`` for API reference pages; ``; plain code blocks; the legacy ``/``/`` trio ONLY on not-yet-migrated GraphQL/upload/relations/users-permissions pages?) +- What snippet imports does the page use? (e.g., ``, ``, ``; these are still current and are used alongside `` on migrated REST pages.) +- How are Request/Response pairs structured? On migrated pages they are expressed through ``'s `codeTabs`/`responses` model; on legacy pages they may still appear as side-by-side or stacked ``/`` blocks (with or without titles). +- Does the page use `
` blocks? If so, are they standalone, expressed as a `
` slot inside ``, or nested inside a legacy `` (for example, the `qs.stringify` block)? New content must replicate these patterns exactly. Do not introduce component patterns that the page does not already use, unless explicitly instructed otherwise by the user. +**Always use `` for new API reference content and for any REST or Document Service page** (`kind="http"` for REST, `kind="js"` for Document Service). Never introduce the legacy ``/``/`` trio on new, REST, or Document Service reference pages. + ### Step 3: Read reference materials If `template` and/or `guide` paths are provided: @@ -618,7 +620,7 @@ For Patch mode, metadata is embedded in the output header (File, Section, Edits 16. **Patch: never invent context.** When deriving instructions, only produce edits that are directly supported by the source material. If `target.notes` suggests a change but the source material does not contain the technical details to write it, produce the instruction with a `` placeholder in the content rather than guessing. -17. **Match component patterns exactly.** In Patch mode, study the existing page's MDX component structure before writing. Pay attention to how the page wraps code examples (for instance, ``, ``, `
`), which snippet imports it uses (``, etc.), and how Request/Response pairs are structured. Replicate these patterns in new content. Generic Markdown (plain code blocks, standalone `
`) should not be used when the page already uses custom components for the same purpose. +17. **Match component patterns exactly.** In Patch mode, study the existing page's MDX component structure before writing. Pay attention to how the page wraps code examples (for instance, ``, ``, `
`), which snippet imports it uses (``, etc.), and how Request/Response pairs are structured. Replicate these patterns in new content. Generic Markdown (plain code blocks, standalone `
`) should not be used when the page already uses custom components for the same purpose. **Carve-out for deprecated API markup:** the legacy ``/``/`` trio (along with `noSideBySide` and the `
` `qs.stringify` block) is DEPRECATED. Do NOT replicate it when patching a migrated page or creating new content; use `` instead. Replicate the trio ONLY when patching one of these specific not-yet-migrated pages: `docs/cms/api/graphql.md`, `docs/cms/api/graphql/**` (e.g. `graphql/locale.md`), `docs/cms/api/rest/upload.md`, `docs/cms/api/rest/relations.md`, `docs/cms/features/users-permissions/rest-api.md`, `docs/cms/plugins/graphql.md`. The `QsForQueryBody` / `QsForQueryTitle` / `QsIntroFull` snippet imports are NOT legacy and remain in use alongside `` on migrated REST pages. 18. **Preserve structural coherence.** When adding a new section at a given heading level, check whether parallel content at the same level also has explicit headings. If the new section introduces an H2 but existing content of comparable scope sits directly under the H1 without its own H2, wrap the existing content in a matching H2 to maintain symmetry. Similarly, update the H1 title if the page's scope has expanded (e.g., from covering `status` to covering both `status` and `hasPublishedVersion`). diff --git a/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md b/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md index e57f09555f..78939614a4 100644 --- a/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md +++ b/claude-plugins/inki/references/prompts/integrity-known-pitfalls.md @@ -50,6 +50,7 @@ These are not code hallucinations but recurring Strapi-docs formatting mistakes. | `**Timestamp**` in a table cell | `Timestamp` (plain text) | Bold is reserved for UI button names only. Table cell labels and headers must be plain text. | | `*Error*`, `*Warning*`, `*Info*` (log levels / values in italic) | `Error`, `Warning`, `Info` (plain text) | Italic is reserved for admin panel section, window, tab, and field names. Values, enum members, and log levels are not UI section names. | | `:::caution` for non-destructive informational content | `:::note` | `:::caution` is for mistake prevention / unstable behavior; `:::warning` for data loss or crashes. Neutral side information with nothing risky is a `:::note`. | +| ``/``/`` trio (or `noSideBySide`) on a REST or Document Service reference page | `` (`kind="http"` for REST, `kind="js"` for Document Service) | The redesign replaced the legacy trio with ``. The trio is valid ONLY on these not-yet-migrated pages: `docs/cms/api/graphql.md`, `docs/cms/api/graphql/**`, `docs/cms/api/rest/upload.md`, `docs/cms/api/rest/relations.md`, `docs/cms/features/users-permissions/rest-api.md`, `docs/cms/plugins/graphql.md`. Flag the trio anywhere else. Do NOT flag bare `QsForQueryBody` (it is still used alongside `` on migrated REST pages). | --- diff --git a/claude-plugins/inki/references/templates/README.md b/claude-plugins/inki/references/templates/README.md index ee4f17fce9..9d6a54b9a2 100644 --- a/claude-plugins/inki/references/templates/README.md +++ b/claude-plugins/inki/references/templates/README.md @@ -23,7 +23,7 @@ How to use | `plugin-template.md` | `docusaurus/docs/cms/plugins/` | Plugin pages: identity details, install steps, configuration (admin UI and code), usage tasks | `claude-plugins/inki/references/authoring/AGENTS.cms.plugins.md` | | `configuration-template.md` | `docusaurus/docs/cms/configurations/` | Configuration pages: file location, available options, env variables, per‑environment overrides | `claude-plugins/inki/references/authoring/AGENTS.cms.configurations.md` | | `guide-template.md` | `docusaurus/docs/cms/` (varies) | How‑to guides: prerequisites, numbered steps, validation, troubleshooting | `claude-plugins/inki/references/authoring/AGENTS.cms.guides.md` | -| `api-template.md` | `docusaurus/docs/cms/api/` | API reference pages: endpoints, auth, parameters, example requests/responses | `claude-plugins/inki/references/authoring/AGENTS.cms.api.md` | +| `api-template.md` | `docusaurus/docs/cms/api/` | API reference pages: endpoints, auth, parameters, and the `` 2‑column API block (HTTP request on one side, response/JS client on the other) | `claude-plugins/inki/references/authoring/AGENTS.cms.api.md` | | `breaking-change-template.md` | `docusaurus/docs/cms/migration/**/breaking-changes/` | Breaking‑change pages: BreakingChangeIdCard, v4/v5 comparison, migration notes | — | ## What every template provides @@ -35,6 +35,9 @@ How to use - **Placeholder comments** (``) explaining what content to write in each section. - **Multi‑language patterns** using Tabs where applicable (see `claude-plugins/inki/references/templates/components/tabs.md` for Tabs/TabItem rules). - **Progressive disclosure** using ExpandableContent where applicable (see `claude-plugins/inki/references/templates/components/expandable-content.md` for usage rules). +- **API request/response blocks** using the `` 2‑column component where applicable (see `claude-plugins/inki/references/templates/components/endpoint.md` for `kind` `http`/`js` usage rules). +- **Tutorial steps** using the `` component where applicable (see `claude-plugins/inki/references/templates/components/step-details.md` for usage rules). +- **"What's next?" navigation** using the `` component where applicable (see `claude-plugins/inki/references/templates/components/next-steps.md` for usage rules). ## References @@ -42,4 +45,7 @@ How to use - Authoring area guides: `claude-plugins/inki/references/authoring/AGENTS.*.md` - Tabs/TabItem rules: `claude-plugins/inki/references/templates/components/tabs.md` - ExpandableContent rules: `claude-plugins/inki/references/templates/components/expandable-content.md` -- Annotation rules: `claude-plugins/inki/references/templates/components/annotation.md` \ No newline at end of file +- Annotation rules: `claude-plugins/inki/references/templates/components/annotation.md` +- Endpoint (2‑column API block, `kind` `http`/`js`) rules: `claude-plugins/inki/references/templates/components/endpoint.md` +- StepDetails (tutorial step) rules: `claude-plugins/inki/references/templates/components/step-details.md` +- NextSteps ("What's next?" block) rules: `claude-plugins/inki/references/templates/components/next-steps.md` \ No newline at end of file diff --git a/claude-plugins/inki/references/templates/api-template.md b/claude-plugins/inki/references/templates/api-template.md index 5bd4912b78..1e4b823847 100644 --- a/claude-plugins/inki/references/templates/api-template.md +++ b/claude-plugins/inki/references/templates/api-template.md @@ -12,52 +12,195 @@ Briefly describe the endpoint(s), authentication, and typical use. ## Endpoints -### GET /path -- Purpose: … -- Auth: … -- Query params: … -```bash title="Example" -curl -H "Authorization: Bearer …" https://example.com/path +Document each endpoint with an `` block. This is the primary pattern for all new REST and Document Service reference pages. Use `kind="http"` (the default) for REST endpoints and `kind="js"` for Document Service methods. + +Do not add an import line. ``, ``, and `` are registered as global MDX components in `docusaurus/src/theme/MDXComponents.js` (alongside ``, ``, and ``), so they are used directly with no import. + +### GET /path (REST, `kind="http"`) + +Full REST skeleton: `method`, `path` with `:params`, a `paramTitle`, a `params` array, `codePath` + `codePathHighlights` for the URL bar, `codeTabs` (cURL + JavaScript), and multiple `responses` built with `JSON.stringify(obj, null, 2)`. + +```mdx +restaurants)' }, + { name: 'documentId', type: 'string', required: true, description: 'Unique document identifier' }, + ]} + codePath="/api/restaurants/znrlzntu9ei5onjvwfaalu2v" + codePathHighlights={['restaurants', 'znrlzntu9ei5onjvwfaalu2v']} + codeTabs={[ + { + label: 'cURL', + code: `curl 'http://localhost:1337/api/restaurants/znrlzntu9ei5onjvwfaalu2v' \\ + -H 'Authorization: Bearer '`, + }, + { + label: 'JavaScript', + code: `const response = await fetch( + 'http://localhost:1337/api/restaurants/znrlzntu9ei5onjvwfaalu2v', + { + headers: { + Authorization: 'Bearer ', + }, + } +); +const data = await response.json();`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + time: '12ms', + body: JSON.stringify({ + data: { + id: 6, + documentId: "znrlzntu9ei5onjvwfaalu2v", + Name: "Biscotte Restaurant", + // ... trimmed: model fields + createdAt/updatedAt/publishedAt/locale ... + }, + meta: {} + }, null, 2), + }, + { + status: 404, + statusText: 'Not Found', + body: JSON.stringify({ + error: { status: 404, name: 'NotFoundError', message: 'Document not found' } + }, null, 2), + }, + ]} +/> ``` -### POST /path -- Purpose: … -- Auth: … +### findOne() (Document Service, `kind="js"`) -```json title="Request body" -{ - "example": true -} +Document Service skeleton: `kind="js"`, `path` written as a JS method signature, a `params` array (descriptions may contain HTML such as `` and ``), a single `codeTabs` tab labelled `'Request'`, and one `response`. There is no `method`, no `codePath`, and no `codePathHighlights` — the verb is hidden and the result renders as "Returns". + +```mdx +See locale docs.' }, + { name: 'status', type: "'published' | 'draft'", required: false, description: 'If Draft & Publish is enabled: publication status. Can be published or draft. Default: draft.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return.' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ + { + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').findOne({ + documentId: 'a1b2c3d4e5f6g7h8i9j0klmn' +})`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "Biscotte Restaurant", + publishedAt: null, + locale: "en", + }, null, 2), + }, + ]} +/> ``` -## Responses -```json title="200 OK" -{ "ok": true } +### Admonitions around and inside `` + +Admonitions can sit **between** blocks (in the normal MDX flow, between the `### heading` and the ``) or **inside** an `` as children. To pass children, close the block with `` instead of self-closing `/>`; the content renders in the left column under the params. + +MDX rule: leave a blank line **after** the opening `>` and a blank line **before** `` so the children parse as Markdown. + +```mdx + + +:::tip +If the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled on the content-type, you can automatically publish a document while creating it. +::: + + +``` + +### GraphQL pages + +GraphQL pages use plain code blocks with the `graphql` language identifier (no `` component). + +```graphql +query { + restaurants { + documentId + name + } +} ``` ## Notes and Limits Versioning, deprecations, rate limits, or pagination. - - • Document Service pages: - wrapping and . - Use `noSideBySide` prop for longer examples. - Responses use JS object literal notation (not JSON). + \ No newline at end of file diff --git a/claude-plugins/inki/references/templates/components/endpoint.md b/claude-plugins/inki/references/templates/components/endpoint.md new file mode 100644 index 0000000000..e9cf6b5553 --- /dev/null +++ b/claude-plugins/inki/references/templates/components/endpoint.md @@ -0,0 +1,204 @@ +# Endpoint component (API reference blocks) + +Use `` to document a single API operation on a reference page: one HTTP request (REST) or one method call (Document Service / other JS APIs). Each block renders a self-contained, anchorable two-column layout — operation header and parameters on the left, code examples and responses on the right. + +No import line +- Do NOT add an import for ``. It is registered as a global MDX component in `docusaurus/src/theme/MDXComponents.js`, exactly like ``, ``, and ``. Use it directly. +- The same is true for `` and ``: they are globally registered too, so never import them either. +- Adding a redundant `import ... from '@site/src/components/...'` line is a mistake; remove it if you see it on a migrated page. + +When to use +- One `` per API operation on a reference page (one HTTP route, or one method signature). +- `kind="http"` (the default) for REST endpoints; `kind="js"` for Document Service and other programmatic APIs. +- Put shared context (intro prose, admonitions that apply to the operation) immediately before the block, or pass operation-specific admonitions as children (see "Admonitions as children" below). +- Do not use `` outside API reference pages, and do not nest one inside another. + +Prop contract (from `docusaurus/src/components/ApiReference/Endpoint.jsx`) +- `id` — string. Anchor id for the block; registered via `useBrokenLinks().collectAnchor(id)` so deep links and cross-references resolve. Required for linkable operations. +- `kind` — `'http'` (default) | `'js'`. `'js'` hides the method pill and URL bar, renders `path` as a JS signature, and labels the result "Returns". +- `method` — `'GET'` (default) | `'POST'` | `'PUT'` | `'DELETE'`. HTTP only; ignored when `kind="js"`. `DELETE` renders as the pill label `DEL`. +- `path` — string. For `kind="http"`, the HTTP path with `:params` (e.g. `/api/:pluralApiId/:documentId`). For `kind="js"`, the JS method signature (e.g. `strapi.documents().findOne()`). +- `title` — string. Short operation name shown in the header. +- `description` — string. Rendered as a paragraph under the header. +- `params` — array of `{ name, type, required, description }`. `description` may contain inline HTML such as `...` and `...`. +- `paramTitle` — string. Heading above the parameter table (default `'Parameters'`). REST pages use `'Query Parameters'`, `'Path Parameters'`, or `'Body Parameters'`. +- `codeTabs` — array of `{ label, code }`. `label` is the tab name (e.g. `'cURL'`, `'JavaScript'`, `'Request'`); `code` is a template-literal string. Multiple tabs are idiomatic on JS pages (e.g. `'Generic example'`, `'With filters'`). +- `codePath` — string. Path shown in the code panel URL bar (falls back to `path`). HTTP only; visual. +- `codePathHighlights` — `string[]`. Substrings of `codePath` to highlight in the URL bar. +- `responses` — array of `{ status, statusText, time?, body }`. `body` is a **string**; build it with `JSON.stringify(obj, null, 2)`. `time` (e.g. `'12ms'`) is typical on REST and usually omitted for JS. An empty array `responses={[]}` is valid (e.g. DELETE). +- `isLast` — boolean. Removes the bottom border on the final block of a page. Both `isLast` (bare) and `isLast={true}` are accepted. +- `children` — node. Extra MDX rendered in the left column under the parameters; this is where operation-specific admonitions and notes go. + +Two-column layout rule +- The block renders as two columns **only when** `(params OR children) AND (codeTabs OR responses)`. +- If there are params/children but no code/responses, or code/responses but no params/children, the block falls back to a stacked single-column layout. Provide both sides when you want the side-by-side reference look. + +`kind="js"` behavior +- Hides the `MethodPill` and the URL bar. +- Renders `path` as a JS method signature in code, not as an HTTP route. +- Labels the result panel "Returns" instead of "200 OK"; there are no HTTP status tabs, status dot, or response time. +- `method`, `codePath`, and `codePathHighlights` are not used. + +Canonical examples + +## REST / HTTP endpoint (`kind="http"`) + +```mdx +restaurants)' }, + { name: 'documentId', type: 'string', required: true, description: 'Unique document identifier' }, + ]} + codePath="/api/restaurants/znrlzntu9ei5onjvwfaalu2v" + codePathHighlights={['restaurants', 'znrlzntu9ei5onjvwfaalu2v']} + codeTabs={[ + { + label: 'cURL', + code: `curl 'http://localhost:1337/api/restaurants/znrlzntu9ei5onjvwfaalu2v' \\ + -H 'Authorization: Bearer '`, + }, + { + label: 'JavaScript', + code: `const response = await fetch( + 'http://localhost:1337/api/restaurants/znrlzntu9ei5onjvwfaalu2v', + { + headers: { + Authorization: 'Bearer ', + }, + } +); +const data = await response.json();`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + time: '12ms', + body: JSON.stringify({ + data: { + id: 6, + documentId: "znrlzntu9ei5onjvwfaalu2v", + Name: "Biscotte Restaurant", + // ... trimmed: model fields + createdAt/updatedAt/publishedAt/locale ... + }, + meta: {} + }, null, 2), + }, + { + status: 404, + statusText: 'Not Found', + body: JSON.stringify({ + error: { status: 404, name: 'NotFoundError', message: 'Document not found' } + }, null, 2), + }, + ]} +/> +``` + +## Document Service / JS method (`kind="js"`) + +```mdx +See locale docs.' }, + { name: 'status', type: "'published' | 'draft'", required: false, description: 'If Draft & Publish is enabled: publication status. Can be published or draft. Default: draft.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return.' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ + { + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').findOne({ + documentId: 'a1b2c3d4e5f6g7h8i9j0klmn' +})`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "Biscotte Restaurant", + publishedAt: null, + locale: "en", + }, null, 2), + }, + ]} +/> +``` + +Notes on the examples +- Trim long JSON bodies to the shape that matters; keep `JSON.stringify(obj, null, 2)`. +- `time` appears on REST responses and is usually dropped on JS. +- On JS pages, multiple `codeTabs` (e.g. `'Generic example'`, `'With filters'`) pair with multiple `responses` whose `statusText` matches each tab. +- The last block on a page takes `isLast` (REST writes it bare; JS pages tend to write `isLast={true}`). + +Admonitions as children +- When `` has a closing tag `` (not self-closing `/>`), everything between the tags becomes `children` and renders in the left column, under the parameters. +- Put operation-specific admonitions (`:::tip`, `:::note`) and short prose there. +- MDX rule: leave a blank line after the opening `>` and before ``, so MDX parses the children as Markdown. + +```mdx + + +:::tip +If the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled on the content-type, you can automatically publish a document while creating it (see [`status` documentation](/cms/api/document-service/status#create)). +::: + + +``` + +- Admonitions that introduce the operation (rather than annotate the params) stay in the normal MDX flow, between the `### heading` and the `` block, instead of as children. + +Internal sub-components (never authored directly) +- `` composes `MethodPill`, `ParamTable`, `CodePanel`, and `ResponsePanel` internally; the page chrome is built from `ApiHeader`, `ApiSidebar`, and `ApiReferencePage`, and code blocks use `CopyCodeButton`. +- Never write any of these in MDX. Always express an operation through `` props; the sub-components are implementation details of the component. + +Legacy pages +- The legacy `` / `` / `` trio (plus the `noSideBySide` prop and the `
` `qs.stringify` block) is **DEPRECATED** for new content. +- Match this trio **only** when patching these specific, not-yet-migrated pages: + - `docs/cms/api/graphql.md` + - `docs/cms/api/graphql/**` (e.g. `graphql/locale.md`) + - `docs/cms/api/rest/upload.md` + - `docs/cms/api/rest/relations.md` + - `docs/cms/features/users-permissions/rest-api.md` + - `docs/cms/plugins/graphql.md` +- Never introduce the trio on new pages, on migrated REST pages, or on Document Service reference pages — use `` instead. +- NOTE: `QsForQueryBody`, `QsForQueryTitle`, and `QsIntroFull` are NOT legacy. They are snippet imports still used alongside `` on migrated REST pages; keep them. + +Extraction +- llms-code extracts each `codeTabs` entry as a code example for the operation; keep one operation per `` and keep `code` strings runnable. +- Provide both cURL and JavaScript tabs on REST endpoints when applicable so both variants are captured. diff --git a/claude-plugins/inki/references/templates/components/next-steps.md b/claude-plugins/inki/references/templates/components/next-steps.md new file mode 100644 index 0000000000..bff65ca8f4 --- /dev/null +++ b/claude-plugins/inki/references/templates/components/next-steps.md @@ -0,0 +1,49 @@ +# NextSteps component ("What's next?" navigation) + +Use NextSteps for the closing navigation block at the end of a tutorial or quick-start page: a short, numbered list of where the reader should go next. Each step is a single onward link with a one-line description. Keep it to a handful of steps and put it last on the page. + +When to use +- The end of a tutorial, quick-start, or any page that walks the reader through a task and should hand them off to the next thing to read. +- Each step points to one place worth going next (a feature page, an API reference, a deployment guide). +- Do not use it as a general link list mid-page, or for unordered "see also" references (use prose links or a bullet list instead). + +No import line +- `` and `` are registered as global MDX components in `docusaurus/src/theme/MDXComponents.js` (like ``, ``, and ``). +- Use them directly. Do NOT add an `import` line for `NextSteps` at the top of the page. + +Props + +`` +- `title` — heading shown above the steps. Defaults to `What's next?`. Pass `title=""` to hide the built-in heading when you want to write your own `## What's next?` heading above the block (this is the canonical pattern, so the heading lands in the table of contents). + +`` (self-closing) +- `title` — the step label. Required. +- `description` — optional one-line explanation under the title. Omit it for a bare link. +- `link` — optional href. When present, the whole step becomes a clickable link with a trailing arrow. Omit it for a non-clickable step. +- `index` — auto-injected by the parent `` (it numbers the steps 1, 2, 3…). Never set it manually. + +Canonical example + +Write your own `## What's next?` heading so it appears in the table of contents, then pass `title=""` on the wrapper to avoid a duplicate heading. Each step is self-closing. + +```mdx +## What's next? + + + + + + +``` diff --git a/claude-plugins/inki/references/templates/components/step-details.md b/claude-plugins/inki/references/templates/components/step-details.md new file mode 100644 index 0000000000..e4686960eb --- /dev/null +++ b/claude-plugins/inki/references/templates/components/step-details.md @@ -0,0 +1,73 @@ +# StepDetails component (collapsible numbered steps) + +Use `` on tutorial and quick-start pages to wrap a single numbered step as a collapsible block. Each step gets a clickable header (the step title) and a body that readers can expand or collapse. The block also carries a completion checkmark so readers can track progress through the tutorial. + +When to use +- One `` wraps exactly one step. Use a sequence of them for a step-by-step procedure (Step 1, Step 2, …), not for general prose. +- Reserve it for tutorial / quick-start flows. Do not use it as a generic accordion — for collapsible reference content that is not a step, use a plain `
`. + +No import +- Do NOT add an import line for ``. It is registered as a global MDX component in `docusaurus/src/theme/MDXComponents.js` (alongside ``, ``, ``, ``), so it is available directly in any `.md`/`.mdx` page with no import. +- Likewise, never add `import StepDetails from '@site/src/components/StepDetails/StepDetails'`. A page may still carry that line for historical reasons, but it is redundant and being removed — do not reintroduce it. + +Props +- `title` (string, required) — the step header text. It is slugified with `github-slugger` (the same slugger Docusaurus uses for heading anchors) into the block's anchor `id`, so a `#step-...` deep link resolves to the block. The id is registered via `useBrokenLinks().collectAnchor`, so the broken-anchor checker knows the anchor exists. Keep the title stable: changing it changes the anchor and breaks inbound links. +- `defaultOpen` (boolean, bare) — when present, the step renders expanded on load. Write it bare (`defaultOpen`), not `defaultOpen={true}`. Omit it for steps that should start collapsed. Typically only the first step is `defaultOpen`. +- `children` — the step content (normal MDX: prose, numbered lists, images, code blocks, an inner `
`). + +Nesting rule +- Leave a blank line after the opening `` tag and a blank line before the closing `` so MDX parses the children as Markdown. Without the blank lines, lists and fenced code blocks inside the step will not render correctly. + +Inner details vs. step wrapper +- Only the outer step wrapper is ``. An inner collapsible that is not itself a step — for example, an example API response tucked away under the step — stays a plain `
`/``. Do not nest one `` inside another. + +Title with quotes +- A title may contain a double-quoted attribute value with single quotes inside (`title='Step 1: Create a "Restaurant" collection type'`), or use HTML entities for the quotes (`title="…"Restaurant"…"`). Pick whichever keeps the attribute valid; both render the same. + +Canonical examples + +## Sequence of steps (first one expanded) + +`defaultOpen` on the first step renders it expanded; later steps start collapsed. + + + +... step content (prose, numbered lists, images) ... + + + + + +... content ... + + + + + +... content ... + + + +## Step with an inner plain `
` + +The step wrapper is ``; the example API response stays a plain `
`. Note the blank lines around both the inner content and the fenced code block. + + + +There you are: the list of restaurants should be accessible by visiting the `/api/restaurants` path ... + +
+Click me to view an example of API response: + +```json +{ + "data": [ + { "id": 3, "documentId": "wf7m1n3g8g22yr5k50hsryhk", "Name": "Biscotte Restaurant" /* ...trimmed... */ } + ], + "meta": { "pagination": { "page": 1, "pageSize": 25, "pageCount": 1, "total": 1 } } +} +``` + +
+ +
diff --git a/docusaurus/docs/cloud/account/account-billing.md b/docusaurus/docs/cloud/account/account-billing.md index baaba31c12..b3fd37a9d2 100644 --- a/docusaurus/docs/cloud/account/account-billing.md +++ b/docusaurus/docs/cloud/account/account-billing.md @@ -1,5 +1,5 @@ --- -title: Account billing details +title: Cloud account billing details displayed_sidebar: cloudSidebar description: Manage billing details for Strapi Cloud account. canonicalUrl: https://docs.strapi.io/cloud/account/account-billing.html @@ -14,7 +14,7 @@ tags: import InvoiceStatus from '/docs/snippets/invoices-statuses.md' -# Account billing & invoices +# Cloud account billing & invoices Billing details and invoices are managed on the Profile page, where payment methods are updated and invoice history is available. diff --git a/docusaurus/docs/cloud/account/account-settings.md b/docusaurus/docs/cloud/account/account-settings.md index 281df6b47a..fbff1d618b 100644 --- a/docusaurus/docs/cloud/account/account-settings.md +++ b/docusaurus/docs/cloud/account/account-settings.md @@ -1,5 +1,5 @@ --- -title: Profile settings +title: Cloud profile settings displayed_sidebar: cloudSidebar description: Manage Strapi Cloud account settings. canonicalUrl: https://docs.strapi.io/cloud/account/account-settings.html @@ -13,7 +13,7 @@ tags: pagination_next: cloud/account/account-billing --- -# Profile settings +# Cloud profile settings Settings of the Profile page include account details, connected accounts, and account deletion options. diff --git a/docusaurus/docs/cloud/advanced/database.md b/docusaurus/docs/cloud/advanced/database.md index 868f63de1a..60c2bbb69f 100644 --- a/docusaurus/docs/cloud/advanced/database.md +++ b/docusaurus/docs/cloud/advanced/database.md @@ -1,5 +1,5 @@ --- -title: Database +title: Cloud database configuration displayed_sidebar: cloudSidebar description: Configure your own database on Strapi Cloud. canonicalUrl: https://docs.strapi.io/cloud/advanced/database.html @@ -13,7 +13,7 @@ tags: pagination_next: cloud/advanced/email --- -# Database +# Cloud database configuration Default PostgreSQL can be swapped for any supported SQL database by aligning configuration and environment variables. diff --git a/docusaurus/docs/cloud/advanced/email.md b/docusaurus/docs/cloud/advanced/email.md index 97f9e8cd39..86656da8c6 100644 --- a/docusaurus/docs/cloud/advanced/email.md +++ b/docusaurus/docs/cloud/advanced/email.md @@ -1,5 +1,5 @@ --- -title: Email Provider +title: Cloud email provider displayed_sidebar: cloudSidebar description: Configure Strapi Cloud to use a third-party email provider. canonicalUrl: https://docs.strapi.io/cloud/advanced/email.html diff --git a/docusaurus/docs/cloud/getting-started/caching.md b/docusaurus/docs/cloud/getting-started/caching.md index 1228290c6a..29a4fe6539 100644 --- a/docusaurus/docs/cloud/getting-started/caching.md +++ b/docusaurus/docs/cloud/getting-started/caching.md @@ -9,7 +9,7 @@ tags: - Strapi Cloud --- -# Caching & Performance +# Cloud caching & performance Edge caching via Cache-Control headers reduces latency and server load for heavy static content. diff --git a/docusaurus/docs/cloud/getting-started/cloud-fundamentals.md b/docusaurus/docs/cloud/getting-started/cloud-fundamentals.md index 265e1ffba6..04bfe5dfad 100644 --- a/docusaurus/docs/cloud/getting-started/cloud-fundamentals.md +++ b/docusaurus/docs/cloud/getting-started/cloud-fundamentals.md @@ -10,6 +10,13 @@ tags: # Strapi Cloud fundamentals + + +Strapi Cloud is a PaaS hosting platform for deploying Strapi CMS projects, offering four pricing plans with different features and support levels, two user roles (owners and maintainers), and REST/GraphQL APIs that behave identically to self-hosted servers. + + + + Before going any further into this Strapi Cloud documentation, we recommend you to acknowledge the main concepts below. They will help you to understand how Strapi Cloud works, and ensure a smooth Strapi Cloud experience. - **Hosting Platform**
Strapi Cloud is a hosting platform that allows to deploy already existing Strapi projects created with Strapi CMS (Content Management System). Strapi Cloud is *not* the SaaS () version of Strapi CMS and should rather be considered as a PaaS (). Feel free to refer to the [CMS documentation](https://docs.strapi.io/cms/intro) to learn more about Strapi CMS. diff --git a/docusaurus/docs/cloud/getting-started/deployment-cli.md b/docusaurus/docs/cloud/getting-started/deployment-cli.md index 3f52eb6a8b..b6c3e73ed5 100644 --- a/docusaurus/docs/cloud/getting-started/deployment-cli.md +++ b/docusaurus/docs/cloud/getting-started/deployment-cli.md @@ -13,6 +13,13 @@ tags: # Project deployment with the Command Line Interface (CLI) + + +Deploy a Strapi project to Strapi Cloud using the `strapi login` and `strapi deploy` CLI commands, with optional automatic deployment on git repository commits. + + + + This is a step-by-step guide for deploying your project on Strapi Cloud for the first time, using the Command Line Interface. :::prerequisites @@ -90,7 +97,7 @@ Another option is to enable automatic deployment through a git repository. To do Automatic deployment is compatible with all other deployment methods, so once a git repository is connected, you can trigger a new deployment to Strapi Cloud [from the Cloud dashboard](/cloud/projects/deploys), [from the CLI](/cloud/cli/cloud-cli#strapi-deploy), or by pushing new commits to your connected repository. ::: -## ⏩ What to do next? +## What to do next? Now that you have deployed your project via the Command Line Interface, we encourage you to explore the following ideas to have an even more complete Strapi Cloud experience: diff --git a/docusaurus/docs/cloud/getting-started/deployment-options.md b/docusaurus/docs/cloud/getting-started/deployment-options.md index b74d6cbd90..302e91cb06 100644 --- a/docusaurus/docs/cloud/getting-started/deployment-options.md +++ b/docusaurus/docs/cloud/getting-started/deployment-options.md @@ -1,5 +1,5 @@ --- -title: Project deployment +title: Cloud project deployment displayed_sidebar: cloudSidebar description: Learn how to deploy your Strapi application on Strapi Cloud, via the Cloud dashboard or the CLI. canonicalUrl: https://docs.strapi.io/cloud/getting-started/deployment-options.html @@ -11,6 +11,13 @@ tags: # Project deployment with Strapi Cloud + + +Deploy your Strapi application on Strapi Cloud using either the Cloud dashboard or the CLI, with step-by-step guides provided for both methods. + + + + You have 2 options to deploy your project with Strapi Cloud: - either with the user interface (UI), meaning that you will perform all the actions directly on the Strapi Cloud dashboard, diff --git a/docusaurus/docs/cloud/getting-started/deployment.md b/docusaurus/docs/cloud/getting-started/deployment.md index 343b57df81..76585f9abd 100644 --- a/docusaurus/docs/cloud/getting-started/deployment.md +++ b/docusaurus/docs/cloud/getting-started/deployment.md @@ -17,6 +17,13 @@ tags: # Project deployment with the Cloud dashboard + + +Deploy your Strapi project on Strapi Cloud using the dashboard by choosing a plan, connecting a Git repository, configuring your project settings, and setting up billing details. + + + + This is a step-by-step guide for deploying your project on Strapi Cloud for the first time, using the Cloud dashboard. :::prerequisites diff --git a/docusaurus/docs/cloud/getting-started/intro.md b/docusaurus/docs/cloud/getting-started/intro.md index f6792a0d74..c32f452243 100644 --- a/docusaurus/docs/cloud/getting-started/intro.md +++ b/docusaurus/docs/cloud/getting-started/intro.md @@ -13,6 +13,13 @@ pagination_next: cloud/getting-started/cloud-fundamentals # Welcome to the Strapi Cloud Documentation! + + +Strapi Cloud is a fully managed hosting platform for deploying Strapi applications, abstracting infrastructure complexity while enabling content management, collaboration, and compliance features. + + + + - - - - + ### `create()` -Creates a drafted document and returns it. - -Pass fields for the content to create in a `data` object. - Syntax: `create(parameters: Params) => Document` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| [`locale`](/cms/api/document-service/locale#create) | Locale of the documents to create. | Default locale | String or `undefined` | -| [`fields`](/cms/api/document-service/fields#create) | [Select fields](/cms/api/document-service/fields#create) to return | All fields
(except those not populated by default) | Object | -| [`status`](/cms/api/document-service/status#create) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:
Can be set to `'published'` to automatically publish the draft version of a document while creating it | -| `'published'` | -| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object | - -#### Example - -If no `locale` parameter is passed, `create()` creates the draft version of the document for the default locale: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').create({ +See locale docs.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return. Defaults to all fields (except those not populated by default).' }, + { name: 'status', type: "'published'", required: false, description: 'If Draft & Publish is enabled: can be set to published to automatically publish the draft version of a document while creating it. See status docs.' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ + { + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').create({ data: { name: 'Restaurant B' } -}) -``` - - - - - -```js -{ - documentId: "ln1gkzs6ojl9d707xn6v86mw", - name: "Restaurant B", - publishedAt: null, - locale: "en", -} -``` - - - +})`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "Restaurant B", + publishedAt: null, + locale: "en", + }, null, 2), + }, + ]} +> :::tip If the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled on the content-type, you can automatically publish a document while creating it (see [`status` documentation](/cms/api/document-service/status#create)). ::: -### `update()` + -Updates document versions and returns them. +### `update()` Syntax: `update(parameters: Params) => Promise` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| `documentId` | Document id | | `ID` | -| [`locale`](/cms/api/document-service/locale#update) | Locale of the document to update. | Default locale | String or `null` | -| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object | -| [`fields`](/cms/api/document-service/fields#update) | [Select fields](/cms/api/document-service/fields#update) to return | All fields
(except those not populate by default) | Object | -| [`status`](/cms/api/document-service/status#update) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:
Can be set to `'published'` to automatically publish the draft version of a document while updating it | - | `'published'` | -| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object | +See locale docs.' }, + { name: 'filters', type: 'Object', required: false, description: 'Filters to use. Default: null.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return. Defaults to all fields (except those not populated by default).' }, + { name: 'status', type: "'published'", required: false, description: 'If Draft & Publish is enabled: can be set to published to automatically publish the draft version of a document while updating it. See status docs.' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ + { + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').update({ + documentId: 'a1b2c3d4e5f6g7h8i9j0klmn', + data: { name: "New restaurant name" } +})`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "New restaurant name", + locale: "en", + publishedAt: null, + }, null, 2), + }, + ]} +> :::tip Published versions are read-only, so you can not technically update the published version of a document. @@ -452,137 +373,72 @@ To update a document and publish the new version right away, you can: It's not recommended to update repeatable components with the Document Service API (see the related [breaking change entry](/cms/migration/v4-to-v5/breaking-changes/do-not-update-repeatable-components-with-document-service-api.md) for more details). ::: -#### Example - -If no `locale` parameter is passed, `update()` updates the document for the default locale: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').update({ - documentId: 'a1b2c3d4e5f6g7h8i9j0klm', - data: { name: "New restaurant name" } -}) -``` - - - - - -```js {3} -{ - documentId: 'a1b2c3d4e5f6g7h8i9j0klm', - name: "New restaurant name", - locale: "en", - publishedAt: null, // draft - // … -} -``` - - - - - - - + ### `delete()` -Deletes one document, or a specific locale of it. - Syntax: `delete(parameters: Params): Promise<{ documentId: ID, entries: Number }>` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| `documentId`| Document id | | `ID`| -| [`locale`](/cms/api/document-service/locale#delete) | Locale version of the document to delete. | `null`
(deletes only the default locale) | String, `'*'`, or `null` | -| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object | -| [`fields`](/cms/api/document-service/fields#delete) | [Select fields](/cms/api/document-service/fields#delete) to return | All fields
(except those not populate by default) | Object | -| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object | - -#### Example - -If no `locale` parameter is passed, `delete()` only deletes the default locale version of a document. This deletes both the draft and published versions: - - - -```js -await strapi.documents('api::restaurant.restaurant').delete({ - documentId: 'a1b2c3d4e5f6g7h8i9j0klm', // documentId, -}) -``` - - - - - - -```js {6} -{ - documentId: "a1b2c3d4e5f6g7h8i9j0klm", - entries: [ +null (deletes only the default locale). See locale docs.' }, + { name: 'filters', type: 'Object', required: false, description: 'Filters to use. Default: null.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return. Defaults to all fields (except those not populated by default).' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ { - "documentId": "a1b2c3d4e5f6g7h8i9j0klm", - "name": "Biscotte Restaurant", - "publishedAt": "2024-03-14T18:30:48.870Z", - "locale": "en" - // … - } - ] -} -``` - - - - - + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').delete({ + documentId: 'a1b2c3d4e5f6g7h8i9j0klmn', +})`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + entries: [ + { + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "Biscotte Restaurant", + publishedAt: "2024-03-14T18:30:48.870Z", + locale: "en", + } + ] + }, null, 2), + }, + ]} +/> ### `deleteMany()` -Delete multiple documents matching filters and relation parameters. - Syntax: `deleteMany(parameters: Params): Promise<{ documentId: ID, entries: Number }>` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| [`locale`](/cms/api/document-service/locale#delete) | Locale version of documents to delete. | `null`
(deletes only the default locale) | String, `'*'`, or `null` | -| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object | -| [`fields`](/cms/api/document-service/fields#delete) | [Select fields](/cms/api/document-service/fields#delete) to return | All fields
(except those not populate by default) | Object | -| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object | - -#### Example - -Delete multiple documents matching filters, including filters on related fields: - - - -```js -await strapi.documents('api::restaurant.restaurant').deleteMany({ +See locale docs.' }, + { name: 'filters', type: 'Object', required: false, description: 'Filters to use. Default: null.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return. Defaults to all fields (except those not populated by default).' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ + { + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').deleteMany({ filters: { city: { name: { @@ -590,210 +446,189 @@ await strapi.documents('api::restaurant.restaurant').deleteMany({ } } } -}) -``` - - - - - -```js -{ - documentId: "multiple_documents", - entries: 3 -} -``` - - +});`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "multiple_documents", + entries: 3 + }, null, 2), + }, + ]} +/> ### `publish()` -Publishes one or multiple locales of a document. - -This method is only available if [Draft & Publish](/cms/features/draft-and-publish) is enabled on the content-type. - Syntax: `publish(parameters: Params): Promise<{ documentId: ID, entries: Number }>` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| `documentId`| Document id | | `ID`| -| [`locale`](/cms/api/document-service/locale#publish) | Locale of the documents to publish. | Only the default locale | String, `'*'`, or `null` | -| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object | -| [`fields`](/cms/api/document-service/fields#publish) | [Select fields](/cms/api/document-service/fields#publish) to return | All fields
(except those not populate by default) | Object | -| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object | - -#### Example - -If no `locale` parameter is passed, `publish()` only publishes the default locale version of the document: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').publish({ - documentId: 'a1b2c3d4e5f6g7h8i9j0klm', -}); -``` - - - - - -```js {6} -{ - documentId: "a1b2c3d4e5f6g7h8i9j0klm", - entries: [ +See locale docs.' }, + { name: 'filters', type: 'Object', required: false, description: 'Filters to use. Default: null.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return. Defaults to all fields (except those not populated by default).' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ { - "documentId": "a1b2c3d4e5f6g7h8i9j0klm", - "name": "Biscotte Restaurant", - "publishedAt": "2024-03-14T18:30:48.870Z", - "locale": "en" - // … - } - ] -} -``` - - - - - - - + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').publish({ + documentId: 'a1b2c3d4e5f6g7h8i9j0klmn', +});`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + entries: [ + { + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "Biscotte Restaurant", + publishedAt: "2024-03-14T18:30:48.870Z", + locale: "en", + } + ] + }, null, 2), + }, + ]} +/> ### `unpublish()` -Unpublishes one or all locale versions of a document, and returns how many locale versions were unpublished. - -This method is only available if [Draft & Publish](/cms/features/draft-and-publish) is enabled on the content-type. - Syntax: `unpublish(parameters: Params): Promise<{ documentId: ID, entries: Number }>` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| `documentId`| Document id | | `ID`| -| [`locale`](/cms/api/document-service/locale#unpublish) | Locale of the documents to unpublish. | Only the default locale | String, `'*'`, or `null` | -| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object | -| [`fields`](/cms/api/document-service/fields#unpublish) | [Select fields](/cms/api/document-service/fields#unpublish) to return | All fields
(except those not populate by default) | Object | -| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object | - -#### Example - -If no `locale` parameter is passed, `unpublish()` only unpublishes the default locale version of the document: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').unpublish({ - documentId: 'a1b2c3d4e5f6g7h8i9j0klm' -}); -``` - - - - - -```js -{ - documentId: "lviw819d5htwvga8s3kovdij", - entries: [ +See locale docs.' }, + { name: 'filters', type: 'Object', required: false, description: 'Filters to use. Default: null.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return. Defaults to all fields (except those not populated by default).' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ { - documentId: "lviw819d5htwvga8s3kovdij", - name: "Biscotte Restaurant", - publishedAt: null, - locale: "en" - // … - } - ] -} -``` - - - - + label: 'Request', + code: `await strapi.documents('api::restaurant.restaurant').unpublish({ + documentId: 'a1b2c3d4e5f6g7h8i9j0klmn' +});`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + entries: [ + { + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "Biscotte Restaurant", + publishedAt: null, + locale: "en", + } + ] + }, null, 2), + }, + ]} +/> ### `discardDraft()` -Discards draft data and overrides it with the published version. - -This method is only available if [Draft & Publish](/cms/features/draft-and-publish) is enabled on the content-type. - Syntax: `discardDraft(parameters: Params): Promise<{ documentId: ID, entries: Number }>` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| `documentId`| Document id | | `ID`| -| [`locale`](/cms/api/document-service/locale#discard-draft) | Locale of the documents to discard. | Only the default locale. | String, `'*'`, or `null` | -| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object | -| [`fields`](/cms/api/document-service/fields#discarddraft) | [Select fields](/cms/api/document-service/fields#discarddraft) to return | All fields
(except those not populate by default) | Object | -| [`populate`](/cms/api/document-service/populate) | [Populate](/cms/api/document-service/populate) results with additional fields. | `null` | Object | - -#### Example - -If no `locale` parameter is passed, `discardDraft()` discards draft data and overrides it with the published version only for the default locale: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').discardDraft({ - documentId: 'a1b2c3d4e5f6g7h8i9j0klm', -}); -``` - - - - - -```js -{ - documentId: "lviw819d5htwvga8s3kovdij", - entries: [ +See locale docs.' }, + { name: 'filters', type: 'Object', required: false, description: 'Filters to use. Default: null.' }, + { name: 'fields', type: 'Object', required: false, description: 'Select fields to return. Defaults to all fields (except those not populated by default).' }, + { name: 'populate', type: 'Object', required: false, description: 'Populate results with additional fields. Default: null.' }, + ]} + codeTabs={[ { - documentId: "lviw819d5htwvga8s3kovdij", - name: "Biscotte Restaurant", - publishedAt: null, - locale: "en" - // … - } - ] -} -``` - - - - + label: 'Request', + code: `strapi.documents('api::restaurant.restaurant').discardDraft({ + documentId: 'a1b2c3d4e5f6g7h8i9j0klmn', +});`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + entries: [ + { + documentId: "a1b2c3d4e5f6g7h8i9j0klmn", + name: "Biscotte Restaurant", + publishedAt: null, + locale: "en", + } + ] + }, null, 2), + }, + ]} +/> ### `count()` -Count the number of documents that match the provided parameters. - Syntax: `count(parameters: Params) => number` -#### Parameters - -| Parameter | Description | Default | Type | -|-----------|-------------|---------|------| -| [`locale`](/cms/api/document-service/locale#count) | Locale of the documents to count | Default locale | String or `null` | -| [`status`](/cms/api/document-service/status#count) | _If [Draft & Publish](/cms/features/draft-and-publish) is enabled for the content-type_:
Publication status, can be:
  • `'published'` to find only published documents
  • `'draft'` to find draft documents (will return all documents)
| `'draft'` | `'published'` or `'draft'` | -| [`filters`](/cms/api/document-service/filters) | [Filters](/cms/api/document-service/filters) to use | `null` | Object | +See locale docs.' }, + { name: 'status', type: "'published' | 'draft'", required: false, description: 'If Draft & Publish is enabled: publication status. published to count only published documents, draft to count draft documents (returns all documents). Default: draft. See status docs.' }, + { name: 'filters', type: 'Object', required: false, description: 'Filters to use. Default: null.' }, + ]} + codeTabs={[ + { + label: 'Generic example', + code: `await strapi.documents('api::restaurant.restaurant').count()`, + }, + { + label: 'Count published', + code: `strapi.documents('api::restaurant.restaurant').count({ status: 'published' })`, + }, + { + label: 'With filters', + code: `/** + * Count number of draft documents (default if status is omitted) + * in English (default locale) + * whose name starts with 'Pizzeria' + */ +strapi.documents('api::restaurant.restaurant').count({ filters: { name: { $startsWith: "Pizzeria" }}})`, + }, + ]} + isLast={true} +> :::note Since published documents necessarily also have a draft counterpart, a published document is still counted as having a draft version. @@ -801,50 +636,4 @@ Since published documents necessarily also have a draft counterpart, a published This means that counting with the `status: 'draft'` parameter still returns the total number of documents matching other parameters, even if some documents have already been published and are not displayed as "draft" or "modified" in the Content Manager anymore. There currently is no way to prevent already published documents from being counted. ::: -#### Examples - -
- -##### Generic example - -If no parameter is passed, the `count()` method returns the total number of documents for the default locale: - - - - -```js -await strapi.documents('api::restaurant.restaurant').count() -``` - - - - - -##### Count published documents - -To count only published documents, pass `status: 'published'` along with other parameters to the `count()` method. - -If no `locale` parameter is passed, documents are counted for the default locale. - - - -```js -strapi.documents('api::restaurant.restaurant').count({ status: 'published' }) -``` - - - -##### Count documents with filters - -Any [filters](/cms/api/document-service/filters) can be passed to the `count()` method. - -If no `locale` and no `status` parameter is passed, draft documents (which is the total of available documents for the locale since even published documents are counted as having a draft version) are counted only for the default locale: - -```js -/** - * Count number of draft documents (default if status is omitted) - * in English (default locale) - * whose name starts with 'Pizzeria' - */ -strapi.documents('api::restaurant.restaurant').count({ filters: { name: { $startsWith: "Pizzeria" }}}) -``` +
diff --git a/docusaurus/docs/cms/api/document-service/fields.md b/docusaurus/docs/cms/api/document-service/fields.md index a98e5e2555..84b67d24fb 100644 --- a/docusaurus/docs/cms/api/document-service/fields.md +++ b/docusaurus/docs/cms/api/document-service/fields.md @@ -13,16 +13,22 @@ tags: - findOne() - findMany() - findFirst() -- publish() - fields - update() - unpublishing content --- - + import IdsInResponse from '/docs/snippets/id-in-responses.md' # Document Service API: Selecting fields + + +Use the `fields` parameter in Document Service API queries to select specific fields to return with your results, reducing data payload across `findOne()`, `findMany()`, `create()`, `update()`, `delete()`, `publish()`, and other document operations. + + + + By default the [Document Service API](/cms/api/document-service) returns all the fields of a document but does not populate any fields. This page describes how to use the `fields` parameter to return only specific fields with the query results. :::tip @@ -33,176 +39,177 @@ You can also use the `populate` parameter to populate relations, media fields, c ## Select fields with `findOne()` queries {#findone} -To select fields to return while [finding a specific document](/cms/api/document-service#findone) with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").findOne({ + - - - -```js -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant", description: "Welcome to Biscotte restaurant! …" -} -``` - - - +}` + } + ]} +/> ## Select fields with `findFirst()` queries {#findfirst} -To select fields to return while [finding the first document](/cms/api/document-service#findfirst) matching the parameters with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").findFirst({ + - - - -```js -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant", description: "Welcome to Biscotte restaurant! …" -} -``` - - - +}` + } + ]} +/> ## Select fields with `findMany()` queries {#findmany} -To select fields to return while [finding documents](/cms/api/document-service#findmany) with the Document Service API: - - - - -```js -const documents = await strapi.documents("api::restaurant.restaurant").findMany({ + - - - -```js -[ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `[ { documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant", description: "Welcome to Biscotte restaurant! …" } // ... -] -``` - - - +]` + } + ]} +/> ## Select fields with `create()` queries {#create} -To select fields to return while [creating documents](/cms/api/document-service#create) with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").create({ + - - - -```js -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ id: 4, documentId: 'fmtr6d7ktzpgrijqaqgr6vxs', name: 'Restaurant B', description: 'Description for the restaurant' -} -``` - - - +}` + } + ]} +/> ## Select fields with `update()` queries {#update} -To select fields to return while [updating documents](/cms/api/document-service#update) with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").update({ + - - - -```js -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ documentId: 'fmtr6d7ktzpgrijqaqgr6vxs', name: 'Restaurant C' -} -``` - - - +}` + } + ]} +/> ## Select fields with `delete()` queries {#delete} -To select fields to return while [deleting documents](/cms/api/document-service#delete) with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").delete({ + - - - -```js - documentId: 'fmtr6d7ktzpgrijqaqgr6vxs', +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: ` documentId: 'fmtr6d7ktzpgrijqaqgr6vxs', // All of the deleted document's versions are returned entries: [ { @@ -212,32 +219,32 @@ const document = await strapi.documents("api::restaurant.restaurant").delete({ // … } ] -} -``` - - - +}` + } + ]} +/> ## Select fields with `publish()` queries {#publish} -To select fields to return while [publishing documents](/cms/api/document-service#publish) with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").publish({ + - - - -```js -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ documentId: 'fmtr6d7ktzpgrijqaqgr6vxs', // All of the published locale entries are returned entries: [ @@ -246,32 +253,32 @@ const document = await strapi.documents("api::restaurant.restaurant").publish({ name: 'Restaurant B' } ] -} -``` - - - +}` + } + ]} +/> ## Select fields with `unpublish()` queries {#unpublish} -To select fields to return while [unpublishing documents](/cms/api/document-service#unpublish) with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").unpublish({ + - - - -```js -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ documentId: 'fmtr6d7ktzpgrijqaqgr6vxs', // All of the published locale entries are returned entries: [ @@ -280,32 +287,32 @@ const document = await strapi.documents("api::restaurant.restaurant").unpublish( name: 'Restaurant B' } ] -} -``` - - - +}` + } + ]} +/> ## Select fields with `discardDraft()` queries {#discarddraft} -To select fields to return while [discarding draft versions of documents](/cms/api/document-service#discarddraft) with the Document Service API: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").discardDraft({ + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ documentId: "fmtr6d7ktzpgrijqaqgr6vxs", // All of the discarded draft entries are returned entries: [ @@ -313,8 +320,8 @@ const document = await strapi.documents("api::restaurant.restaurant").discardDra "name": "Restaurant B" } ] -} -``` - - - +}` + } + ]} + isLast +/> diff --git a/docusaurus/docs/cms/api/document-service/filters.md b/docusaurus/docs/cms/api/document-service/filters.md index 6c05e02ff3..b07eade60e 100644 --- a/docusaurus/docs/cms/api/document-service/filters.md +++ b/docusaurus/docs/cms/api/document-service/filters.md @@ -15,6 +15,13 @@ import DeepFilteringBlogLink from '/docs/snippets/deep-filtering-blog.md' # Document Service API: Filters + + +The Document Service API provides attribute operators (`$eq`, `$lt`, `$contains`, etc.) and logical operators (`$and`, `$or`, `$not`) to filter query results with support for case-sensitive and case-insensitive matching. + + + + The [Document Service API](/cms/api/document-service) offers the ability to filter results. The following operators are available: @@ -52,14 +59,16 @@ The following operators are available:
-### `$not` - -Negates the nested condition(s). - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ + + + + + + + + + + + + + + + + + + + + + + +Attribute is between the 2 input values, boundaries included (e.g., $between[1, 3] will also return 1 and 3).} + codeTabs={[ + { + label: 'JavaScript', + code: `const entries = await strapi.documents('api::article.article').findMany({ filters: { rating: { $between: [1, 20], }, }, -}); -``` - -### `$contains` - -Attribute contains the input value (case-sensitive). - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ +});` + } + ]} +/> + + + + + +$containsi is not case-sensitive, while $contains is.} + codeTabs={[ + { + label: 'JavaScript', + code: `const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $containsi: 'hello', }, }, -}); -``` - -### `$notContainsi` - -Attribute does not contain the input value. `$notContainsi` is not case-sensitive, while [$notContains](#notcontains) is. - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ +});` + } + ]} +/> + +$notContainsi is not case-sensitive, while $notContains is.} + codeTabs={[ + { + label: 'JavaScript', + code: `const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $notContainsi: 'hello', }, }, -}); -``` - -### `$startsWith` - -Attribute starts with input value (case-sensitive). - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ +});` + } + ]} +/> + + + + + + + + + +Attribute is null.} + codeTabs={[ + { + label: 'JavaScript', + code: `const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $null: true, }, }, -}); -``` - -### `$notNull` - -Attribute is not `null`. - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ +});` + } + ]} +/> + +Attribute is not null.} + codeTabs={[ + { + label: 'JavaScript', + code: `const entries = await strapi.documents('api::article.article').findMany({ filters: { title: { $notNull: true, }, }, -}); -``` +});` + } + ]} +/> ## Logical operators -### `$and` - -All nested conditions must be `true`. - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ +All nested conditions must be true.} + codeTabs={[ + { + label: 'JavaScript', + code: `const entries = await strapi.documents('api::article.article').findMany({ filters: { $and: [ { @@ -447,28 +541,31 @@ const entries = await strapi.documents('api::article.article').findMany({ }, ], }, -}); -``` - -`$and` will be used implicitly when passing an object with nested conditions: - -```js +});` + }, + { + label: 'Implicit $and', + code: `// $and will be used implicitly when passing an object with nested conditions: const entries = await strapi.documents('api::article.article').findMany({ filters: { title: 'Hello World', createdAt: { $gt: '2021-11-17T14:28:25.843Z' }, }, -}); -``` - -### `$or` - -One or many nested conditions must be `true`. - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ +});` + } + ]} +/> + +One or many nested conditions must be true.} + codeTabs={[ + { + label: 'JavaScript', + code: `const entries = await strapi.documents('api::article.article').findMany({ filters: { $or: [ { @@ -479,30 +576,36 @@ const entries = await strapi.documents('api::article.article').findMany({ }, ], }, -}); -``` - -### `$not` - -Negates the nested conditions. - -**Example** - -```js -const entries = await strapi.documents('api::article.article').findMany({ +});` + } + ]} +/> + + :::note `$not` can be used as: -- a logical operator (e.g. in `filters: { $not: { // conditions… }}`) -- [an attribute operator](#not) (e.g. in `filters: { attribute-name: $not: { … } }`). +- a logical operator (e.g. in `filters: { $not: { // conditions... }}`) +- [an attribute operator](#not) (e.g. in `filters: { attribute-name: $not: { ... } }`). ::: :::tip diff --git a/docusaurus/docs/cms/api/document-service/locale.md b/docusaurus/docs/cms/api/document-service/locale.md index 4d7a7acbdf..c79bc4ff4d 100644 --- a/docusaurus/docs/cms/api/document-service/locale.md +++ b/docusaurus/docs/cms/api/document-service/locale.md @@ -22,93 +22,99 @@ tags: # Document Service API: Using the `locale` parameter -By default the [Document Service API](/cms/api/document-service) returns the default locale version of documents (which is 'en', i.e. the English version, unless another default locale has been set for the application, see [Internationalization (i18n) feature](/cms/features/internationalization)). This page describes how to use the `locale` parameter to get or manipulate data only for specific locales. + -## Get a locale version with `findOne()` {#find-one} +The `locale` parameter in the Document Service API lets you query, create, update, delete, publish, and unpublish documents for specific language versions using methods like `findOne()`, `findMany()`, `update()`, and `delete()`. -If a `locale` is passed, the [`findOne()` method](/cms/api/document-service#findone) of the Document Service API returns the version of the document for this locale: + - - +By default the [Document Service API](/cms/api/document-service) returns the default locale version of documents (which is 'en', i.e. the English version, unless another default locale has been set for the application, see [Internationalization (i18n) feature](/cms/features/internationalization)). This page describes how to use the `locale` parameter to get or manipulate data only for specific locales. -```js -await strapi.documents('api::restaurant.restaurant').findOne({ +## Get a locale version with `findOne()` {#find-one} + + - - - -```js {5} -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant", publishedAt: null, // draft version (default) locale: "fr", // as asked from the parameters // … -} -``` - - - - +}` + } + ]} +/> If no `status` parameter is passed, the `draft` version is returned by default. ## Get a locale version with `findFirst()` {#find-first} -To return a specific locale while [finding the first document](/cms/api/document-service#findfirst) matching the parameters with the Document Service API: - - - - -```js -const document = await strapi.documents('api::article.article').findFirst({ + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "documentId": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article" // … -} -``` - - - +}` + } + ]} +/> If no `status` parameter is passed, the `draft` version is returned by default. ## Get locale versions with `findMany()` {#find-many} -When a `locale` is passed to the [`findMany()` method](/cms/api/document-service#findmany) of the Document Service API, the response will return all documents that have this locale available. - If no `status` parameter is passed, the `draft` versions are returned by default. - - - -```js -// Defaults to status: draft -await strapi.documents('api::restaurant.restaurant').findMany({ locale: 'fr' }); -``` - - - - - -```js {6} -[ + - +]` + } + ]} +/>
Explanation: @@ -141,76 +146,72 @@ Given the following 4 documents that have various locales: - `fr` - it -`findMany({ locale: 'fr' })` would only return the draft version of the documents that have a `‘fr’` locale version, that is documents A, C, and D. +`findMany({ locale: 'fr' })` would only return the draft version of the documents that have a `'fr'` locale version, that is documents A, C, and D.
## `create()` a document for a locale {#create} -To create a document for specific locale, pass the `locale` as a parameter to the [`create` method](/cms/api/document-service#create) of the Document Service API: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').create({ + - - - -```js -{ +})` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ documentId: "pw2s0nh5ub1zmnk0d80vgqrh", name: "Restaurante B", publishedAt: null, locale: "es" // … -} -``` - - - - +}` + } + ]} +/> ## `update()` a locale version {#update} -To update only a specific locale version of a document, pass the `locale` parameter to the [`update()` method](/cms/api/document-service#update) of the Document Service API: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').update({ + - - - -```js {3} -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Nuevo nombre del restaurante", locale: "es", publishedAt: null, // … -} -``` - - - - +}` + } + ]} +/> ## `delete()` locale versions {#delete} @@ -218,39 +219,45 @@ Use the `locale` parameter with the [`delete()` method](/cms/api/document-servic ### Delete a locale version -To delete a specific locale version of a document: - - - -```js -await strapi.documents('api::restaurant.restaurant').delete({ + +});` + } + ]} +/> ### Delete all locale versions -The `*` wildcard is supported by the `locale` parameter and can be used to delete all locale versions of a document: - - - - -```js -await strapi.documents('api::restaurant.restaurant').delete({ + - - - -```json -{ +}); // for all existing locales` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "documentId": "a1b2c3d4e5f6g7h8i9j0klm", // All of the deleted locale versions are returned "versions": [ @@ -258,11 +265,10 @@ await strapi.documents('api::restaurant.restaurant').delete({ "title": "Test Article" } ] -} -``` - - - +}` + } + ]} +/> ## `publish()` locale versions {#publish} @@ -270,25 +276,26 @@ To publish only specific locale versions of a document with the [`publish()` met ### Publish a locale version -To publish a specific locale version of a document: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').publish({ + - - - -```js -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ versions: [ { documentId: 'a1b2c3d4e5f6g7h8i9j0klm', @@ -297,34 +304,33 @@ await strapi.documents('api::restaurant.restaurant').publish({ locale: 'fr', // … }, - ]; -} -``` - - - - + ] +}` + } + ]} +/> ### Publish all locale versions -The `*` wildcard is supported by the `locale` parameter to publish all locale versions of a document: - - - - - -```js -await strapi + - - - -```js -{ + .publish({ documentId: 'a1b2c3d4e5f6g7h8i9j0klm', locale: '*' });` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "versions": [ { "documentId": "a1b2c3d4e5f6g7h8i9j0klm", @@ -345,12 +351,10 @@ await strapi // … } ] -} -``` - - - - +}` + } + ]} +/> ## `unpublish()` locale versions {#unpublish} @@ -358,76 +362,78 @@ To publish only specific locale versions of a document with the [`unpublish()` m ### Unpublish a locale version -To unpublish a specific locale version of a document, pass the `locale` as a parameter to `unpublish()`: - - - - - -```js -await strapi + - - - -```js -{ - versions: 1; -} -``` - - - - + .unpublish({ documentId: 'a1b2c3d4e5f6g7h8i9j0klm', locale: 'fr' });` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ + versions: 1 +}` + } + ]} +/> ### Unpublish all locale versions -The `*` wildcard is supported by the `locale` parameter, to unpublish all locale versions of a document: - - - - - -```js -await strapi + - - - -```js -{ - versions: 3; -} -``` - - - - - - - - -```js -const document = await strapi.documents('api::article.article').unpublish({ + .unpublish({ documentId: 'a1b2c3d4e5f6g7h8i9j0klm', locale: '*' });` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ + versions: 3 +}` + } + ]} +/> + + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "documentId": "cjld2cjxh0000qzrmn831i7rn", // All of the unpublished locale versions are returned "versions": [ @@ -435,11 +441,10 @@ const document = await strapi.documents('api::article.article').unpublish({ "title": "Test Article" } ] -} -``` - - - +}` + } + ]} +/> ## `discardDraft()` for locale versions {#discard-draft} @@ -447,24 +452,25 @@ To discard draft data only for some locales versions of a document with the [`di ### Discard draft for a locale version -To discard draft data for a specific locale version of a document and override it with data from the published version for this locale, pass the `locale` as a parameter to `discardDraft()`: - - - - - -```js -await strapi + - - - -```js -{ + .discardDraft({ documentId: 'a1b2c3d4e5f6g7h8i9j0klm', locale: 'fr' });` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ versions: [ { documentId: 'a1b2c3d4e5f6g7h8i9j0klm', @@ -473,34 +479,33 @@ await strapi locale: 'fr', // … }, - ]; -} -``` - - - - + ] +}` + } + ]} +/> ### Discard drafts for all locale versions -The `*` wildcard is supported by the `locale` parameter, to discard draft data for all locale versions of a document and replace them with the data from the published versions: - - - - - -```js -await strapi + - - - -```js -{ + .discardDraft({ documentId: 'a1b2c3d4e5f6g7h8i9j0klm', locale: '*' });` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ versions: [ { documentId: 'a1b2c3d4e5f6g7h8i9j0klm', @@ -523,13 +528,11 @@ await strapi locale: 'es', // … }, - ]; -} -``` - - - - + ] +}` + } + ]} +/> ## `count()` documents for a locale {#count} diff --git a/docusaurus/docs/cms/api/document-service/middlewares.md b/docusaurus/docs/cms/api/document-service/middlewares.md index 9403df0a6d..5500469d36 100644 --- a/docusaurus/docs/cms/api/document-service/middlewares.md +++ b/docusaurus/docs/cms/api/document-service/middlewares.md @@ -8,6 +8,13 @@ displayed_sidebar: cmsSidebar # Document Service API: Middlewares + + +Document Service middlewares allow you to perform actions before and after Document Service methods run by registering middleware functions via `strapi.documents.use()` with access to content type context and method parameters. + + + + The [Document Service API](/cms/api/document-service) offers the ability to extend its behavior thanks to middlewares. Document Service middlewares allow you to perform actions before and/or after a method runs. diff --git a/docusaurus/docs/cms/api/document-service/populate.md b/docusaurus/docs/cms/api/document-service/populate.md index f846860557..7fd271f42a 100644 --- a/docusaurus/docs/cms/api/document-service/populate.md +++ b/docusaurus/docs/cms/api/document-service/populate.md @@ -16,6 +16,13 @@ tags: # Document Service API: Populating fields + + +Use the `populate` parameter with the Document Service API to explicitly load relations, media fields, components, and dynamic zones at one or multiple levels deep, and within `create()`, `update()`, `publish()`, and `delete()` operations. + + + + By default the [Document Service API](/cms/api/document-service) does not populate any relations, media fields, components, or dynamic zones. This page describes how to use the `populate` parameter to populate specific fields. :::tip @@ -34,23 +41,25 @@ Queries can accept a `populate` parameter to explicitly define which fields to p ### Populate 1 level for all relations -To populate one-level deep for all relations, use the `*` wildcard in combination with the `populate` parameter: - - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ [ { "id": "cjld2cjxh0000qzrmn831i7rn", @@ -80,31 +89,32 @@ const documents = await strapi.documents("api::article.article").findMany({ } // ... ] -} -``` - - - +}` + } + ]} +/> ### Populate 1 level for specific relations -To populate specific relations one-level deep, pass the relation names in a `populate` array: - - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `[ { "id": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", @@ -118,35 +128,36 @@ const documents = await strapi.documents("api::article.article").findMany({ } } // ... -] -``` - - - +]` + } + ]} +/> ### Populate several levels deep for specific relations -To populate specific relations several levels deep, use the object format with `populate`: - - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `[ { "id": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", @@ -172,36 +183,40 @@ const documents = await strapi.documents("api::article.article").findMany({ } } // ... -] -``` - - - +]` + } + ]} +/> ### Sort populated relations Use the `sort` parameter inside a `populate` object to order related entries by an attribute. For many-to-many and other join-table relations, an explicit `sort` takes precedence over the default connect order. - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `[ { "id": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", @@ -220,11 +235,10 @@ const documents = await strapi.documents("api::article.article").findMany({ ] } // ... -] -``` - - - +]` + } + ]} +/> :::note Omit `sort` from a `populate` object to preserve the default connect order (the order in which entries were associated). @@ -234,21 +248,25 @@ Omit `sort` from a `populate` object to preserve the default connect order (the Components are populated the same way as relations: - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `[ { "id": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", @@ -262,21 +280,25 @@ const documents = await strapi.documents("api::article.article").findMany({ } } // ... -] -``` - - - +]` + } + ]} +/> Dynamic zones are highly dynamic content structures by essence. Standard populate queries (like `populate: '*'` or `populate: ['testDZ']`) will only retrieve the default, non-relational scalar fields (e.g., strings, numbers) of components within a dynamic zone. They will **not** automatically fetch nested relations, media fields, or nested components. To populate component-specific nested relations, media fields, or components within a dynamic zone, you must define per-component populate queries using the `on` property (fragment population syntax). - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `[ { "id": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", @@ -315,21 +336,23 @@ const documents = await strapi.documents("api::article.article").findMany({ ] } // ... -] -``` - - - +]` + } + ]} +/> ## Populating with `create()` -To populate while creating documents: - - - - -```js -strapi.documents("api::article.article").create({ + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "id": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", "slug": "test-article", @@ -355,35 +377,36 @@ strapi.documents("api::article.article").create({ "name": "17520.jpg" // ... } -} -``` - - - +}` + } + ]} +/> ## Populating with `update()` -To populate while updating documents: - - - - -```js -strapi.documents("api::article.article").update({ + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "id": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article Update", "slug": "test-article", @@ -393,32 +416,35 @@ strapi.documents("api::article.article").update({ "name": "17520.jpg" // ... } -} -``` - - - +}` + } + ]} +/> ## Populating with `publish()` -To populate while publishing documents (same behavior with `unpublish()` and `discardDraft()`): +Same behavior applies with `unpublish()` and `discardDraft()`. - - - -```js -strapi.documents("api::article.article").publish({ + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "id": "cjld2cjxh0000qzrmn831i7rn", "versions": [ { @@ -432,32 +458,35 @@ strapi.documents("api::article.article").publish({ } } ] -} -``` - - - +}` + } + ]} +/> ## Populating with `delete()` To populate while deleting documents: - - - -```js -strapi.documents("api::article.article").delete({ + - - - -```json -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "documentId": "cjld2cjxh0000qzrmn831i7rn", "entries": [ { @@ -473,8 +502,7 @@ strapi.documents("api::article.article").delete({ // ... } ] -} -``` - - - +}` + } + ]} +/> diff --git a/docusaurus/docs/cms/api/document-service/sort-pagination.md b/docusaurus/docs/cms/api/document-service/sort-pagination.md index 27020d6f65..354fab310b 100644 --- a/docusaurus/docs/cms/api/document-service/sort-pagination.md +++ b/docusaurus/docs/cms/api/document-service/sort-pagination.md @@ -4,15 +4,22 @@ description: Use Strapi's Document Service API to sort and paginate query result displayed_sidebar: cmsSidebar sidebar_label: Sort & Pagination tags: -- API -- Content API -- Document Service API +- API +- Content API +- Document Service API - sort - pagination --- # Document Service API: Sorting and paginating results + + +Use the Document Service API's `sort` and pagination parameters to order query results by single or multiple fields and control result limits with `limit` and `start`. + + + + The [Document Service API](/cms/api/document-service) offers the ability to sort and paginate query results. ## Sort @@ -21,121 +28,114 @@ To sort results returned by the Document Service API, include the `sort` paramet ### Sort on a single field -To sort results based on a single field: - - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `[ { "documentId": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", "slug": "test-article", "body": "Test 1" - // ... }, { "documentId": "cjld2cjxh0001qzrm5q1j5q7m", "title": "Test Article 2", "slug": "test-article-2", "body": "Test 2" - // ... } - // ... -] -``` - - - +]`, + }, + ]} +/> ### Sort on multiple fields -To sort on multiple fields, pass them all in an array: - - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `[ { "documentId": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", "slug": "test-article", "body": "Test 1" - // ... }, { "documentId": "cjld2cjxh0001qzrm5q1j5q7m", "title": "Test Article 2", "slug": "test-article-2", "body": "Test 2" - // ... } - // ... -] -``` - - - +]`, + }, + ]} +/> ## Pagination -To paginate results, pass the `limit` and `start` parameters: - - - - -```js -const documents = await strapi.documents("api::article.article").findMany({ + - - - -```json -[ +});`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `[ { "documentId": "cjld2cjxh0000qzrmn831i7rn", "title": "Test Article", "slug": "test-article", "body": "Test 1" - // ... }, { "documentId": "cjld2cjxh0001qzrm5q1j5q7m", "title": "Test Article 2", "slug": "test-article-2", "body": "Test 2" - // ... } - // ... (8 more) -] -``` - - - +]`, + }, + ]} +/> diff --git a/docusaurus/docs/cms/api/document-service/status.md b/docusaurus/docs/cms/api/document-service/status.md index efb7042581..a7d82ec2e4 100644 --- a/docusaurus/docs/cms/api/document-service/status.md +++ b/docusaurus/docs/cms/api/document-service/status.md @@ -19,10 +19,17 @@ tags: # Document Service API: Usage with Draft & Publish + + +Use the `status` parameter with the Document Service API to retrieve published or draft versions of documents, count documents by status, and directly publish documents during creation or updates. + + + + By default the [Document Service API](/cms/api/document-service) returns the draft version of a document when the [Draft & Publish](/cms/features/draft-and-publish) feature is enabled. This page describes how to use the `status` parameter to: - return the published version of a document, -- count documents depending on their status, +- count documents depending on their status, - and directly publish a document while creating it or updating it. :::note @@ -31,92 +38,85 @@ Passing `{ status: 'draft' }` to a Document Service API query returns the same r ## Get the published version with `findOne()` {#find-one} -`findOne()` queries return the draft version of a document by default. - -To return the published version while [finding a specific document](/cms/api/document-service#findone) with the Document Service API, pass `status: 'published'`: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').findOne({ + - - - -```js {4} -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant", publishedAt: "2024-03-14T15:40:45.330Z", locale: "en", // default locale // … -} -``` - - - - +}` + } + ]} +/> ## Get the published version with `findFirst()` {#find-first} -`findFirst()` queries return the draft version of a document by default. - -To return the published version while [finding the first document](/cms/api/document-service#findfirst) with the Document Service API, pass `status: 'published'`: - - - - -```js -const document = await strapi.documents("api::restaurant.restaurant").findFirst({ + - - - -```js {4} -{ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant", publishedAt: "2024-03-14T15:40:45.330Z", locale: "en", // default locale // … -} -``` - - - +}` + } + ]} +/> ## Get the published version with `findMany()` {#find-many} -`findMany()` queries return the draft version of documents by default. - -To return the published version while [finding documents](/cms/api/document-service#findmany) with the Document Service API, pass `status: 'published'`: - - - - -```js -const documents = await strapi.documents("api::restaurant.restaurant").findMany({ + - - - -```js {5} -[ +});` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `[ { documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant", @@ -125,11 +125,10 @@ const documents = await strapi.documents("api::restaurant.restaurant").findMany( // … } // … -] -``` - - - +]` + } + ]} +/> ## `count()` only draft or published versions {#count} @@ -157,70 +156,67 @@ This means that counting with the `status: 'draft'` parameter still returns the ## Create a draft and publish it {#create} -To automatically publish a document while creating it, add `status: 'published'` to parameters passed to `create()`: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').create({ + - - - -```js {5} -{ +})` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ documentId: "d41r46wac4xix5vpba7561at", name: "New Restaurant", publishedAt: "2024-03-14T17:29:03.399Z", locale: "en" // default locale // … -} -``` - - - +}` + } + ]} +/> ## Update a draft and publish it {#update} -To automatically publish a document while updating it, add `status: 'published'` to parameters passed to `update()`: - - - - - -```js -await strapi.documents('api::restaurant.restaurant').update({ + - - - -```js {4} -{ +})` + } + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ documentId: "a1b2c3d4e5f6g7h8i9j0klm", name: "Biscotte Restaurant (closed)", publishedAt: "2024-03-14T17:29:03.399Z", locale: "en" // default locale // … -} -``` - - - - +}` + } + ]} +/> diff --git a/docusaurus/docs/cms/api/document.md b/docusaurus/docs/cms/api/document.md index 92eaf7c83c..4e27f0f97b 100644 --- a/docusaurus/docs/cms/api/document.md +++ b/docusaurus/docs/cms/api/document.md @@ -18,6 +18,13 @@ tags: # Documents + + +A document is an API-only concept representing all content variations (locales, draft/published versions) for a single content-type entry. Use the Document Service API to manipulate documents on the back-end. + + + + A **document** in Strapi 5 is an API-only concept. A document represents all the different variations of content for a given entry of a content-type. A single type contains a unique document, and a collection type can contain several documents. diff --git a/docusaurus/docs/cms/api/entity-service.md b/docusaurus/docs/cms/api/entity-service.md index 0cc5e7297e..573337bf86 100644 --- a/docusaurus/docs/cms/api/entity-service.md +++ b/docusaurus/docs/cms/api/entity-service.md @@ -11,6 +11,13 @@ import ESdeprecated from '/docs/snippets/entity-service-deprecated.md' # Entity Service API + + +The Entity Service API is a backend layer that handles complex content structures like components and dynamic zones, providing CRUD operations, filtering, populating relations, and pagination via `strapi.entityService`. + + + + :::prerequisites diff --git a/docusaurus/docs/cms/api/entity-service/components-dynamic-zones.md b/docusaurus/docs/cms/api/entity-service/components-dynamic-zones.md index f65b2a59e2..f4bb556a08 100644 --- a/docusaurus/docs/cms/api/entity-service/components-dynamic-zones.md +++ b/docusaurus/docs/cms/api/entity-service/components-dynamic-zones.md @@ -9,6 +9,13 @@ import ESdeprecated from '/docs/snippets/entity-service-deprecated.md' # Creating components and dynamic zones with the Entity Service API + + +Use the Entity Service API to create and update components and dynamic zones while creating or updating entries. Components are single objects while dynamic zones are lists of components with a `__component` type identifier. + + + + The [Entity Service](/cms/api/entity-service) is the layer that handles [components](/cms/backend-customization/models#components-json) and [dynamic zones](/cms/backend-customization/models#dynamic-zones) logic. With the Entity Service API, components and dynamic zones can be [created](#creation) and [updated](#update) while creating or updating entries. diff --git a/docusaurus/docs/cms/api/entity-service/crud.md b/docusaurus/docs/cms/api/entity-service/crud.md index 8d81f447db..ea9301f161 100644 --- a/docusaurus/docs/cms/api/entity-service/crud.md +++ b/docusaurus/docs/cms/api/entity-service/crud.md @@ -9,6 +9,13 @@ import ESdeprecated from '/docs/snippets/entity-service-deprecated.md' # CRUD operations with the Entity Service API + + +The Entity Service API performs CRUD operations on content through `findOne()`, `findMany()`, `create()`, `update()`, and `delete()` methods, supporting filtering, pagination, relations, and localization. + + + + The [Entity Service API](/cms/api/entity-service) is built on top of the the [Query Engine API](/cms/api/query-engine) and uses it to perform CRUD operations on entities. diff --git a/docusaurus/docs/cms/api/entity-service/filter.md b/docusaurus/docs/cms/api/entity-service/filter.md index 0ac2e5f456..0ad9545ac0 100644 --- a/docusaurus/docs/cms/api/entity-service/filter.md +++ b/docusaurus/docs/cms/api/entity-service/filter.md @@ -10,6 +10,13 @@ import DeepFilteringBlogLink from '/docs/snippets/deep-filtering-blog.md' # Filtering with the Entity Service API + + +Filter Entity Service API query results using logical operators (`$and`, `$or`, `$not`) and attribute operators (`$eq`, `$contains`, `$gt`, `$between`, etc.) with the `filters` parameter in `findMany()`. + + + + The [Entity Service API](/cms/api/entity-service) offers the ability to filter results found with its [findMany()](/cms/api/entity-service/crud#findmany) method. diff --git a/docusaurus/docs/cms/api/entity-service/order-pagination.md b/docusaurus/docs/cms/api/entity-service/order-pagination.md index 6018ac1a4b..0b37a5b848 100644 --- a/docusaurus/docs/cms/api/entity-service/order-pagination.md +++ b/docusaurus/docs/cms/api/entity-service/order-pagination.md @@ -9,6 +9,13 @@ import ESdeprecated from '/docs/snippets/entity-service-deprecated.md' # Ordering and Paginating with the Entity Service API + + +Order and paginate Entity Service API query results using `sort`, `start`/`limit`, or `page`/`pageSize` parameters to control result ordering and retrieve specific data subsets. + + + + The [Entity Service API](/cms/api/entity-service) offers the ability to [order](#ordering) and [paginate](#pagination) results found with its [findMany()](/cms/api/entity-service/crud#findmany) method. diff --git a/docusaurus/docs/cms/api/entity-service/populate.md b/docusaurus/docs/cms/api/entity-service/populate.md index d60ce6f841..ff080b1da7 100644 --- a/docusaurus/docs/cms/api/entity-service/populate.md +++ b/docusaurus/docs/cms/api/entity-service/populate.md @@ -9,6 +9,13 @@ import ESdeprecated from '/docs/snippets/entity-service-deprecated.md' # Populating with the Entity Service API + + +The Entity Service API's `populate` parameter retrieves relations, components, and dynamic zones. Use `populate: '*'` for all root-level relations, arrays for specific fields, objects for advanced queries with filters and nested populating, or fragments for polymorphic content structures. + + + + The [Entity Service API](/cms/api/entity-service) does not populate relations, components or dynamic zones by default, which means an Entity Service API query that does not use the `populate` parameter will not return information about relations, components, or dynamic zones. diff --git a/docusaurus/docs/cms/api/graphql.md b/docusaurus/docs/cms/api/graphql.md index fd49c12cca..ab238b2cbb 100644 --- a/docusaurus/docs/cms/api/graphql.md +++ b/docusaurus/docs/cms/api/graphql.md @@ -19,6 +19,13 @@ import DeepFilteringBlogLink from '/docs/snippets/deep-filtering-blog.md' # GraphQL API + + +The GraphQL API allows querying and mutating content-types with filtering, sorting, and pagination. It uses `documentId` as the unique identifier and provides singular and plural queries with support for relations, media fields, components, dynamic zones, and localization. + + + + The GraphQL API allows performing queries and mutations to interact with the [content-types](/cms/backend-customization/models#content-types) through Strapi's [GraphQL plugin](/cms/plugins/graphql). Results can be [filtered](#filters), [sorted](#sorting) and [paginated](#pagination). :::prerequisites diff --git a/docusaurus/docs/cms/api/graphql/advanced-policies.md b/docusaurus/docs/cms/api/graphql/advanced-policies.md index 6f42fc2a1a..dcbc143e3c 100644 --- a/docusaurus/docs/cms/api/graphql/advanced-policies.md +++ b/docusaurus/docs/cms/api/graphql/advanced-policies.md @@ -8,6 +8,13 @@ tags: # Advanced policies for the GraphQL API + + +Policies can be attached to GraphQL resolvers to implement complex authorization rules, such as limiting results for unauthenticated users or restricting access based on group membership. + + + + Requests sent to the [GraphQL API](/cms/api/graphql) pass through Strapi's [middlewares](/cms/backend-customization/middlewares.md) and [policies](/cms/backend-customization/policies.md) system. Policies can be attached to resolvers to implement complex authorization rules, as shown in the present short guide. For additional information on GraphQL policies, please refer to the [GraphQL plugin configuration](/cms/plugins/graphql#extending-the-schema) documentation. diff --git a/docusaurus/docs/cms/api/graphql/advanced-queries.md b/docusaurus/docs/cms/api/graphql/advanced-queries.md index b94063cd0c..d2ee3723a6 100644 --- a/docusaurus/docs/cms/api/graphql/advanced-queries.md +++ b/docusaurus/docs/cms/api/graphql/advanced-queries.md @@ -7,6 +7,13 @@ tags: # Advanced queries for the GraphQL API + + +Advanced queries in Strapi's GraphQL API use nested selection sets to fetch multi-level relations and custom resolver chains to reuse logic across resolvers and apply context-specific behavior. + + + + Strapi's [GraphQL API](/cms/api/graphql) resolves many queries automatically, but complex data access can require deeper relation fetching or chaining resolvers. The present short guide explains how to handle such advanced scenarios. For additional information, please refer to the [GraphQL customization](/cms/plugins/graphql#extending-the-schema) documentation. diff --git a/docusaurus/docs/cms/api/graphql/locale.md b/docusaurus/docs/cms/api/graphql/locale.md index e555c40b9a..39a1be494c 100644 --- a/docusaurus/docs/cms/api/graphql/locale.md +++ b/docusaurus/docs/cms/api/graphql/locale.md @@ -1,5 +1,25 @@ +--- +title: Using the locale parameter with the GraphQL API +description: Use the locale field and argument with Strapi's GraphQL API to query and mutate documents for a specific locale. +displayed_sidebar: cmsSidebar +sidebar_label: Locale +tags: +- API +- GraphQL API +- i18n +- internationalization +- locale +--- + # Use `locale` with the GraphQL API {#graphql} + + +Use the `locale` argument with the GraphQL API to query, create, update, and delete documents for a specific locale. + + + + The i18n feature adds new features to the [GraphQL API](/cms/api/graphql): - The `locale` field is added to the GraphQL schema. diff --git a/docusaurus/docs/cms/api/openapi.md b/docusaurus/docs/cms/api/openapi.md index 26bb21b286..0feb15d35e 100644 --- a/docusaurus/docs/cms/api/openapi.md +++ b/docusaurus/docs/cms/api/openapi.md @@ -2,8 +2,8 @@ title: OpenAPI specification description: Learn how to generate OpenAPI specifications for your Strapi applications using the @strapi/openapi package displayed_sidebar: cmsSidebar -pagination_prev: cms/api/document -pagination_next: cms/api/rest +pagination_prev: cms/api/client +pagination_next: cms/api/graphql tags: - OpenAPI - API @@ -11,6 +11,13 @@ tags: # OpenAPI specification generation + + +Strapi provides a CLI tool to automatically generate OpenAPI 3.1.0 specifications documenting all API endpoints, parameters, and responses. The generated specification can be integrated with Swagger UI for interactive API documentation. + + + + Strapi provides a command-line tool to generate specifications for your applications. The CLI tool automatically creates comprehensive API documentation that describes all available endpoints, parameters, and response formats in your Strapi application's Content API. Among the possible use cases, the generated specification can then be easily integrated into documentation tools like . diff --git a/docusaurus/docs/cms/api/query-engine.md b/docusaurus/docs/cms/api/query-engine.md index a7d5602125..74c72a4090 100644 --- a/docusaurus/docs/cms/api/query-engine.md +++ b/docusaurus/docs/cms/api/query-engine.md @@ -17,6 +17,13 @@ import QueryEnginePrereqs from '/docs/snippets/query-engine-prereqs.md' # Query Engine API + + +The Query Engine API provides low-level, unrestricted backend access to Strapi's database layer through `strapi.db.query`, supporting single and bulk operations with filtering, populating, ordering, and pagination. + + + + The Strapi backend provides a Query Engine API to interact with the database layer at a lower level. diff --git a/docusaurus/docs/cms/api/query-engine/bulk-operations.md b/docusaurus/docs/cms/api/query-engine/bulk-operations.md index 3076222cbc..a43116d67e 100644 --- a/docusaurus/docs/cms/api/query-engine/bulk-operations.md +++ b/docusaurus/docs/cms/api/query-engine/bulk-operations.md @@ -18,6 +18,13 @@ import QueryEnginePrereqs from '/docs/snippets/query-engine-prereqs.md' # Bulk Operations with the Query Engine API + + +Bulk Operations with the Query Engine API enable you to create, update, delete, and count multiple entries at once using `createMany()`, `updateMany()`, `deleteMany()`, and `count()` methods. + + + + diff --git a/docusaurus/docs/cms/api/query-engine/filtering.md b/docusaurus/docs/cms/api/query-engine/filtering.md index ecb67af088..e5f5a00e60 100644 --- a/docusaurus/docs/cms/api/query-engine/filtering.md +++ b/docusaurus/docs/cms/api/query-engine/filtering.md @@ -17,6 +17,13 @@ import QueryEnginePrereqs from '/docs/snippets/query-engine-prereqs.md' # Filtering with the Query Engine API + + +The Query Engine API filters query results using the `where` parameter with logical operators (`$and`, `$or`, `$not`) and attribute operators (comparison, string matching, range) prefixed with `$`. + + + + diff --git a/docusaurus/docs/cms/api/query-engine/order-pagination.md b/docusaurus/docs/cms/api/query-engine/order-pagination.md index c4000dde92..2427dd992a 100644 --- a/docusaurus/docs/cms/api/query-engine/order-pagination.md +++ b/docusaurus/docs/cms/api/query-engine/order-pagination.md @@ -16,6 +16,13 @@ import QueryEnginePrereqs from '/docs/snippets/query-engine-prereqs.md' # Ordering and Paginating with the Query Engine API + + +The Query Engine API supports ordering results with the `orderBy` parameter on single or multiple attributes, including relational ordering, and pagination with `offset` and `limit` parameters. + + + + diff --git a/docusaurus/docs/cms/api/query-engine/populating.md b/docusaurus/docs/cms/api/query-engine/populating.md index 074821db0a..2dc1058cbd 100644 --- a/docusaurus/docs/cms/api/query-engine/populating.md +++ b/docusaurus/docs/cms/api/query-engine/populating.md @@ -16,6 +16,13 @@ import QueryEnginePrereqs from '/docs/snippets/query-engine-prereqs.md' # Populating with the Query Engine API + + +The Query Engine API's `populate` parameter loads related data in queries, supporting basic population, selective attributes, filtering nested relations, and polymorphic structures via populate fragments. + + + + diff --git a/docusaurus/docs/cms/api/query-engine/single-operations.md b/docusaurus/docs/cms/api/query-engine/single-operations.md index 73dea517a1..d49c6e12d8 100644 --- a/docusaurus/docs/cms/api/query-engine/single-operations.md +++ b/docusaurus/docs/cms/api/query-engine/single-operations.md @@ -20,6 +20,13 @@ import QueryEnginePrereqs from '/docs/snippets/query-engine-prereqs.md' # Single Operations with the Query Engine API + + +The Query Engine API provides methods to find, create, update, and delete individual entries with filtering, selection, pagination, and relation population options. + + + + diff --git a/docusaurus/docs/cms/api/rest.md b/docusaurus/docs/cms/api/rest.md index 5f257c1d57..d3c5fae46d 100644 --- a/docusaurus/docs/cms/api/rest.md +++ b/docusaurus/docs/cms/api/rest.md @@ -1,4 +1,4 @@ ---- +--- title: REST API reference description: Interact with your Content-Types using the REST API endpoints Strapi generates for you. displayed_sidebar: cmsSidebar @@ -14,12 +14,19 @@ tags: # REST API reference + + +Strapi's REST API automatically generates endpoints for content-types to fetch, create, update, and delete documents using GET, POST, PUT, and DELETE methods, with support for filtering, sorting, field selection, and relation population. + + + + The REST API allows accessing the [content-types](/cms/backend-customization/models) through API endpoints. Strapi automatically creates [API endpoints](#endpoints) when a content-type is created. [API parameters](/cms/api/rest/parameters) can be used when querying API endpoints to refine the results. This section of the documentation is for the REST API reference for content-types. We also have [guides](/cms/api/rest/guides/intro) available for specific use cases. :::prerequisites -All content types are private by default and need to be either made public or queries need to be authenticated with the proper permissions. See the [Quick Start Guide](/cms/quick-start#step-4-set-roles--permissions), the user guide for the [Users & Permissions feature](/cms/features/users-permissions#roles), and [API tokens configuration documentation](/cms/features/api-tokens) for more details. +All content types are private by default and need to be either made public or queries need to be authenticated with the proper permissions. See the [Quick Start Guide](/cms/quick-start#step-8-set-roles--permissions), the user guide for the [Users & Permissions feature](/cms/features/users-permissions#roles), and [API tokens configuration documentation](/cms/features/api-tokens) for more details. ::: :::note @@ -39,7 +46,6 @@ The [Strapi Client](/cms/api/client) library simplifies interactions with your S For each Content-Type, the following endpoints are automatically generated:
- Plural API ID vs. Singular API ID: In the following tables: @@ -63,67 +69,28 @@ sources={{
- | Method | URL | Description | | -------- | ------------------------------- | ------------------------------------- | -| `GET` | `/api/:pluralApiId` | [Get a list of document](#get-all) | -| `POST` | `/api/:pluralApiId` | [Create a document](#create) | -| `GET` | `/api/:pluralApiId/:documentId` | [Get a document](#get) | -| `PUT` | `/api/:pluralApiId/:documentId` | [Update a document](#update) | -| `DELETE` | `/api/:pluralApiId/:documentId` | [Delete a document](#delete) | +| `GET` | `/api/:pluralApiId` | [Get a list of documents](#get-all) | +| `POST` | `/api/:pluralApiId` | [Create a document](#create) | +| `GET` | `/api/:pluralApiId/:documentId` | [Get a document](#get) | +| `PUT` | `/api/:pluralApiId/:documentId` | [Update a document](#update) | +| `DELETE` | `/api/:pluralApiId/:documentId` | [Delete a document](#delete) | - | Method | URL | Description | | -------- | --------------------- | ------------------------------------------ | -| `GET` | `/api/:singularApiId` | [Get a document](#get) | -| `PUT` | `/api/:singularApiId` | [Update/Create a document](#update) | -| `DELETE` | `/api/:singularApiId` | [Delete a document](#delete) | +| `GET` | `/api/:singularApiId` | [Get a document](#get) | +| `PUT` | `/api/:singularApiId` | [Update/Create a document](#update) | +| `DELETE` | `/api/:singularApiId` | [Delete a document](#delete) | - -
- -Real-world examples of endpoints: - -The following endpoint examples are taken from the example application. - - - - - -`Restaurant` **Content type** - -| Method | URL | Description | -| ------ | ------------------------ | ------------------------- | -| GET | `/api/restaurants` | Get a list of restaurants | -| POST | `/api/restaurants` | Create a restaurant | -| GET | `/api/restaurants/:documentId` | Get a specific restaurant | -| DELETE | `/api/restaurants/:documentId` | Delete a restaurant | -| PUT | `/api/restaurants/:documentId` | Update a restaurant | - - - - - -`Homepage` **Content type** - -| Method | URL | Description | -| ------ | --------------- | ---------------------------------- | -| GET | `/api/homepage` | Get the homepage content | -| PUT | `/api/homepage` | Update/create the homepage content | -| DELETE | `/api/homepage` | Delete the homepage content | - - - -
- :::strapi Upload API The Upload package (which powers the [Media Library feature](/cms/features/media-library)) has a specific API accessible through its [`/api/upload` endpoints](/cms/api/rest/upload). ::: @@ -162,126 +129,165 @@ Some plugins (including Users & Permissions and Upload) may not follow this resp ### Get documents {#get-all} -Returns documents matching the query filters (see [API parameters](/cms/api/rest/parameters) documentation). - :::tip Tip: Strapi 5 vs. Strapi 4 In Strapi 5 the response format has been flattened, and attributes are directly accessible from the `data` object instead of being nested in `data.attributes`. You can pass an optional header while you're migrating to Strapi 5 (see the [related breaking change](/cms/migration/v4-to-v5/breaking-changes/new-response-format)). ::: - - - - -`GET http://localhost:1337/api/restaurants` - - - - - -```json -{ - "data": [ +field:asc
or field:desc' }, + { name: 'filters', type: 'object', required: false, description: 'Filter with operators: $eq, $contains, $gt, $lt. See filtering.' }, + { name: 'populate', type: 'string | object', required: false, description: 'Relations and components to include. Use * for all. See populate.' }, + { name: 'fields', type: 'string[]', required: false, description: 'Select specific fields to return. See field selection.' }, + { name: 'pagination[page]', type: 'integer', required: false, description: 'Page number. Default: 1' }, + { name: 'pagination[pageSize]', type: 'integer', required: false, description: 'Items per page. Default 25, max 100' }, + { name: 'locale', type: 'string', required: false, description: 'Locale of the documents to fetch. See locale.' }, + { name: 'status', type: 'string', required: false, description: 'published or draft. See status.' }, + ]} + codePath="/api/restaurants" + codePathHighlights={['restaurants']} + codeTabs={[ { - "id": 2, - "documentId": "hgv1vny5cebq2l3czil1rpb3", - "Name": "BMK Paris Bamako", - "Description": null, - "createdAt": "2024-03-06T13:42:05.098Z", - "updatedAt": "2024-03-06T13:42:05.098Z", - "publishedAt": "2024-03-06T13:42:05.103Z", - "locale": "en" + label: 'cURL', + code: `curl 'http://localhost:1337/api/restaurants' \\ + -H 'Authorization: Bearer '`, }, { - "id": 4, - "documentId": "znrlzntu9ei5onjvwfaalu2v", - "Name": "Biscotte Restaurant", - "Description": [ - { - "type": "paragraph", - "children": [ - { - "type": "text", - "text": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers." - } - ] - } - ], - "createdAt": "2024-03-06T13:43:30.172Z", - "updatedAt": "2024-03-06T13:43:30.172Z", - "publishedAt": "2024-03-06T13:43:30.175Z", - "locale": "en" - } - ], - "meta": { - "pagination": { - "page": 1, - "pageSize": 25, - "pageCount": 1, - "total": 2 - } + label: 'JavaScript', + code: `const response = await fetch( + 'http://localhost:1337/api/restaurants', + { + headers: { + Authorization: 'Bearer ', + }, } -} -``` - - - - +); +const data = await response.json();`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + time: '23ms', + body: JSON.stringify({ + data: [ + { + id: 2, + documentId: "hgv1vny5cebq2l3czil1rpb3", + Name: "BMK Paris Bamako", + Description: null, + createdAt: "2024-03-06T13:42:05.098Z", + updatedAt: "2024-03-06T13:42:05.098Z", + publishedAt: "2024-03-06T13:42:05.103Z", + locale: "en" + }, + { + id: 4, + documentId: "znrlzntu9ei5onjvwfaalu2v", + Name: "Biscotte Restaurant", + Description: [ + { + type: "paragraph", + children: [{ type: "text", text: "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products, often local, organic when possible, and always produced by passionate producers." }] + } + ], + createdAt: "2024-03-06T13:43:30.172Z", + updatedAt: "2024-03-06T13:43:30.172Z", + publishedAt: "2024-03-06T13:43:30.175Z", + locale: "en" + } + ], + meta: { + pagination: { page: 1, pageSize: 25, pageCount: 1, total: 2 } + } + }, null, 2), + }, + ]} +/> ### Get a document {#get} -Returns a document by `documentId`. - :::strapi Strapi 5 vs. Strapi v4 In Strapi 5, a specific document is reached by its `documentId`. ::: - - - - -`GET http://localhost:1337/api/restaurants/znrlzntu9ei5onjvwfaalu2v` - - - - - -```json -{ - "data": { - "id": 6, - "documentId": "znrlzntu9ei5onjvwfaalu2v", - "Name": "Biscotte Restaurant", - "Description": [ - { - "type": "paragraph", - "children": [ - { - "type": "text", - "text": "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine bassics, such as 4 Formaggi or Calzone, and our original creations such as Do Luigi or Nduja." - } - ] - } - ], - "createdAt": "2024-02-27T10:19:04.953Z", - "updatedAt": "2024-03-05T15:52:05.591Z", - "publishedAt": "2024-03-05T15:52:05.600Z", - "locale": "en" - }, - "meta": {} -} - -``` - - - - +restaurants)' }, + { name: 'documentId', type: 'string', required: true, description: 'Unique document identifier' }, + ]} + codePath="/api/restaurants/znrlzntu9ei5onjvwfaalu2v" + codePathHighlights={['restaurants', 'znrlzntu9ei5onjvwfaalu2v']} + codeTabs={[ + { + label: 'cURL', + code: `curl 'http://localhost:1337/api/restaurants/znrlzntu9ei5onjvwfaalu2v' \\ + -H 'Authorization: Bearer '`, + }, + { + label: 'JavaScript', + code: `const response = await fetch( + 'http://localhost:1337/api/restaurants/znrlzntu9ei5onjvwfaalu2v', + { + headers: { + Authorization: 'Bearer ', + }, + } +); +const data = await response.json();`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + time: '12ms', + body: JSON.stringify({ + data: { + id: 6, + documentId: "znrlzntu9ei5onjvwfaalu2v", + Name: "Biscotte Restaurant", + Description: [ + { + type: "paragraph", + children: [{ type: "text", text: "Welcome to Biscotte restaurant! Restaurant Biscotte offers a cuisine based on fresh, quality products." }] + } + ], + createdAt: "2024-02-27T10:19:04.953Z", + updatedAt: "2024-03-05T15:52:05.591Z", + publishedAt: "2024-03-05T15:52:05.600Z", + locale: "en" + }, + meta: {} + }, null, 2), + }, + { + status: 404, + statusText: 'Not Found', + body: JSON.stringify({ + error: { status: 404, name: 'NotFoundError', message: 'Document not found' } + }, null, 2), + }, + ]} +/> ### Create a document {#create} -Creates a document and returns its value. - If the [Internationalization (i18n) plugin](/cms/features/internationalization) is installed, it's possible to use POST requests to the REST API to [create localized documents](/cms/api/rest/locale#rest-delete). :::note @@ -292,70 +298,91 @@ While creating a document, you can define its relations and their order (see [Ma When you POST a document, each object inside a dynamic zone array must include `__component` with that variant's UID (for example `shared.slider`). Put `__component` on the object that represents one row in the dynamic zone. Nested fields inside that object should mirror the JSON you get back when the same document is fetched with `populate` so you do not place `__component` on inner objects unless the schema treats that level as another discriminated structure. ::: - - - - -`POST http://localhost:1337/api/restaurants` - -```json -{ - "data": { - "Name": "Restaurant D", - "Description": [ // uses the "Rich text (blocks)" field type - { - "type": "paragraph", - "children": [ +' \\ + -H 'Content-Type: application/json' \\ + -d '{ + "data": { + "Name": "Restaurant D", + "Description": [ + { + "type": "paragraph", + "children": [{ "type": "text", "text": "A very short description goes here." }] + } + ] + } + }'`, + }, + { + label: 'JavaScript', + code: `const response = await fetch( + 'http://localhost:1337/api/restaurants', + { + method: 'POST', + headers: { + Authorization: 'Bearer ', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: { + Name: 'Restaurant D', + Description: [ { - "type": "text", - "text": "A very short description goes here." - } - ] - } - ] + type: 'paragraph', + children: [{ type: 'text', text: 'A very short description goes here.' }], + }, + ], + }, + }), } -} -``` - - - - - -```json -{ - "data": { - "documentId": "bw64dnu97i56nq85106yt4du", - "Name": "Restaurant D", - "Description": [ - { - "type": "paragraph", - "children": [ - { - "type": "text", - "text": "A very short description goes here." - } - ] - } - ], - "createdAt": "2024-03-05T16:44:47.689Z", - "updatedAt": "2024-03-05T16:44:47.689Z", - "publishedAt": "2024-03-05T16:44:47.687Z", - "locale": "en" - }, - "meta": {} -} -``` - - - - +); +const data = await response.json();`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + time: '45ms', + body: JSON.stringify({ + data: { + documentId: "bw64dnu97i56nq85106yt4du", + Name: "Restaurant D", + Description: [ + { + type: "paragraph", + children: [{ type: "text", text: "A very short description goes here." }] + } + ], + createdAt: "2024-03-05T16:44:47.689Z", + updatedAt: "2024-03-05T16:44:47.689Z", + publishedAt: "2024-03-05T16:44:47.687Z", + locale: "en" + }, + meta: {} + }, null, 2), + }, + ]} +/> ### Update a document {#update} -Partially updates a document by `documentId` and returns its value. - -Send a `null` value to clear fields. - :::note NOTES * Even with the [Internationalization (i18n) plugin](/cms/features/internationalization) installed, it's currently not possible to [update the locale of a document](/cms/api/rest/locale#rest-update). * While updating a document, you can define its relations and their order (see [Managing relations through the REST API](/cms/api/rest/relations) for more details). @@ -365,77 +392,125 @@ Send a `null` value to clear fields. Each entry you send for a [dynamic zone](/cms/backend-customization/models#dynamic-zones) must include `__component` with the target component's UID (for example `shared.media`). Strapi uses that field to pick the component schema when you create or update items in the zone; without it, writes can fail validation or return success without changing data. Use the UID shown in the Content-Type Builder for each component in the zone. ::: - - - - -`PUT http://localhost:1337/api/restaurants/hgv1vny5cebq2l3czil1rpb3` - -```json -{ - "data": { - "Name": "BMK Paris Bamako", // we didn't change this field but still need to include it - "Description": [ // uses the "Rich text (blocks)" field type - { - "type": "paragraph", - "children": [ +' \\ + -H 'Content-Type: application/json' \\ + -d '{ + "data": { + "Name": "BMK Paris Bamako", + "Description": [ + { + "type": "paragraph", + "children": [{ "type": "text", "text": "A very short description goes here." }] + } + ] + } + }'`, + }, + { + label: 'JavaScript', + code: `const response = await fetch( + 'http://localhost:1337/api/restaurants/hgv1vny5cebq2l3czil1rpb3', + { + method: 'PUT', + headers: { + Authorization: 'Bearer ', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: { + Name: 'BMK Paris Bamako', + Description: [ { - "type": "text", - "text": "A very short description goes here." - } - ] - } - ] + type: 'paragraph', + children: [{ type: 'text', text: 'A very short description goes here.' }], + }, + ], + }, + }), } -} -``` - - - - - -```json -{ - "data": { - "id": 9, - "documentId": "hgv1vny5cebq2l3czil1rpb3", - "Name": "BMK Paris Bamako", - "Description": [ - { - "type": "paragraph", - "children": [ - { - "type": "text", - "text": "A very short description goes here." - } - ] - } - ], - "createdAt": "2024-03-06T13:42:05.098Z", - "updatedAt": "2024-03-06T14:16:56.883Z", - "publishedAt": "2024-03-06T14:16:56.895Z", - "locale": "en" - }, - "meta": {} -} -``` - - - - +); +const data = await response.json();`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + time: '34ms', + body: JSON.stringify({ + data: { + id: 9, + documentId: "hgv1vny5cebq2l3czil1rpb3", + Name: "BMK Paris Bamako", + Description: [ + { + type: "paragraph", + children: [{ type: "text", text: "A very short description goes here." }] + } + ], + createdAt: "2024-03-06T13:42:05.098Z", + updatedAt: "2024-03-06T14:16:56.883Z", + publishedAt: "2024-03-06T14:16:56.895Z", + locale: "en" + }, + meta: {} + }, null, 2), + }, + ]} +/> ### Delete a document {#delete} -Deletes a document. - -`DELETE` requests only send a 204 HTTP status code on success and do not return any data in the response body. - - - - - -`DELETE http://localhost:1337/api/restaurants/bw64dnu97i56nq85106yt4du` - - - - +restaurants)' }, + { name: 'documentId', type: 'string', required: true, description: 'Document ID of the entry to delete' }, + ]} + codePath="/api/restaurants/bw64dnu97i56nq85106yt4du" + codePathHighlights={['restaurants', 'bw64dnu97i56nq85106yt4du']} + codeTabs={[ + { + label: 'cURL', + code: `curl -X DELETE \\ + 'http://localhost:1337/api/restaurants/bw64dnu97i56nq85106yt4du' \\ + -H 'Authorization: Bearer '`, + }, + { + label: 'JavaScript', + code: `const response = await fetch( + 'http://localhost:1337/api/restaurants/bw64dnu97i56nq85106yt4du', + { + method: 'DELETE', + headers: { + Authorization: 'Bearer ', + }, + } +);`, + }, + ]} + responses={[]} + isLast +/> diff --git a/docusaurus/docs/cms/api/rest/filters.md b/docusaurus/docs/cms/api/rest/filters.md index 20ced56cb1..bcbf8f2635 100644 --- a/docusaurus/docs/cms/api/rest/filters.md +++ b/docusaurus/docs/cms/api/rest/filters.md @@ -24,6 +24,13 @@ import DeepFilteringBlogLink from '/docs/snippets/deep-filtering-blog.md' # REST API: Filters + + +The REST API filters feature allows filtering query results using operators like `$eq`, `$contains`, and `$between`, with support for complex filtering using `$and`, `$or`, and `$not`, as well as deep filtering across related content. + + + + The [REST API](/cms/api/rest) offers the ability to filter results found with its ["Get entries"](/cms/api/rest#get-all) method.
Using optional Strapi features can provide some more filters: @@ -79,24 +86,20 @@ By default, the filters can only be used from `find` endpoints generated by the ## Example: Find users having 'John' as a first name -You can use the `$eq` filter operator to find an exact match. - -
- - - - -`GET /api/users?filters[username][$eq]=John` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/users?\${query}\`);`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "data": [ { "id": 1, @@ -130,38 +132,34 @@ await request(`/api/users?${query}`); } ], "meta": { - "pagination": { - "page": 1, - "pageSize": 25, - "pageCount": 1, - "total": 1 + "pagination": { + "page": 1, + "pageSize": 25, + "pageCount": 1, + "total": 1 + } } -} -``` - - - +}`, + }, + ]} +/> ## Example: Find multiple restaurants with ids 3, 6,8 -You can use the `$in` filter operator with an array of values to find multiple exact values. - -
- - - - -`GET /api/restaurants?filters[id][$in][0]=3&filters[id][$in][1]=6&filters[id][$in][2]=8` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/restaurants?\${query}\`);`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "data": [ { "id": 3, "documentId": "ethwxjxtvuxl89jq720e38uk", - "name": "test3", - // ... + "name": "test3" }, { "id": 6, "documentId": "ethwxjxtvuxl89jq720e38uk", - "name": "test6", - // ... + "name": "test6" }, { "id": 8, "documentId": "cf07g1dbusqr8mzmlbqvlegx", - "name": "test8", - // ... - }, + "name": "test8" + } ], - "meta": { - // ... - } -} -``` - - - + "meta": {} +}`, + }, + ]} +/> ## Complex filtering -Complex filtering is combining multiple filters using advanced methods such as combining `$and` & `$or`. This allows for more flexibility to request exactly the data needed. - -
- - - -`GET /api/books?filters[$and][0][$or][0][date][$eq]=2020-01-01&filters[$and][0][$or][1][date][$eq]=2020-01-02&filters[$and][1][author][name][$eq]=Kai%20doe` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/books?\${query}\`);`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "data": [ { "id": 1, "documentId": "rxngxzclq0zdaqtvz67hj38d", "name": "test1", - "date": "2020-01-01", - // ... + "date": "2020-01-01" }, { "id": 2, "documentId": "kjkhff4e269a50b4vi16stst", "name": "test2", - "date": "2020-01-02", - // ... + "date": "2020-01-02" } ], - "meta": { - // ... - } -} -``` - - - + "meta": {} +}`, + }, + ]} +/> :::note The response above only contains a book's own attributes. The `author` relation traversed by the `$and` filter is not returned unless requested through the [`populate` parameter](/cms/api/rest/populate-select#population), for example by adding `&populate=author` to the request. ::: - ## Deep filtering -Deep filtering is filtering on a relation's fields. - :::note - Relations, media fields, components, and dynamic zones are not populated by default. Use the `populate` parameter to populate these content structures (see [`populate` documentation](/cms/api/rest/populate-select#population)) - You can filter what you populate, you can also filter nested relations, but you can't use filters for polymorphic content structures (such as media fields and dynamic zones). @@ -313,20 +291,19 @@ Querying your API with deep filters may cause performance issues. If one of you - - - -`GET /api/restaurants?filters[chef][restaurants][stars][$eq]=5` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/restaurants?\${query}\`);`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: `{ "data": [ { "id": 1, "documentId": "cvsz61qg33rtyv1qljb1nrtg", "name": "GORDON RAMSAY STEAK", "stars": 5 - // ... }, { "id": 2, "documentId": "uh17h7ibw0g8thit6ivi71d8", "name": "GORDON RAMSAY BURGER", "stars": 5 - // ... } ], - "meta": { - // ... - } -} -``` - - - + "meta": {} +}`, + }, + ]} + isLast +/> :::note The response above mirrors the default REST output, which excludes the relations traversed by the filter. Add a [`populate` parameter](/cms/api/rest/populate-select#population) such as `&populate[chef][populate][restaurants]=true` to also return the `chef.restaurants` relation referenced in the filter. ::: - diff --git a/docusaurus/docs/cms/api/rest/guides/intro.md b/docusaurus/docs/cms/api/rest/guides/intro.md index 204de65784..080ad195b8 100644 --- a/docusaurus/docs/cms/api/rest/guides/intro.md +++ b/docusaurus/docs/cms/api/rest/guides/intro.md @@ -16,6 +16,13 @@ tags: # REST API Guides + + +Explore detailed guides and step-by-step instructions on specific REST API topics, including populate parameters and custom controllers for accessing creator fields. + + + + The [REST API reference](/cms/api/rest) documentation is meant to provide a quick reference for all the endpoints and parameters available. ## Guides diff --git a/docusaurus/docs/cms/api/rest/guides/populate-creator-fields.md b/docusaurus/docs/cms/api/rest/guides/populate-creator-fields.md index b2ac590631..df9ac3585b 100644 --- a/docusaurus/docs/cms/api/rest/guides/populate-creator-fields.md +++ b/docusaurus/docs/cms/api/rest/guides/populate-creator-fields.md @@ -14,7 +14,14 @@ tags: - updatedBy --- -# 🛠️ How to populate creator fields such as `createdBy` and `updatedBy` +# How to populate creator fields such as `createdBy` and `updatedBy` + + + +Enable the `populateCreatorFields` option in a content-type schema and create a route middleware to include `createdBy` and `updatedBy` fields in REST API responses. + + + The creator fields `createdBy` and `updatedBy` are removed from the [REST API](/cms/api/rest) response by default. These 2 fields can be returned in the REST API by activating the `populateCreatorFields` parameter at the content-type level. diff --git a/docusaurus/docs/cms/api/rest/guides/understanding-populate.md b/docusaurus/docs/cms/api/rest/guides/understanding-populate.md index 4965bc14ab..0792aa1229 100644 --- a/docusaurus/docs/cms/api/rest/guides/understanding-populate.md +++ b/docusaurus/docs/cms/api/rest/guides/understanding-populate.md @@ -17,12 +17,16 @@ tags: import QsIntroFull from '/docs/snippets/qs-intro-full.md' import QsForQueryTitle from '/docs/snippets/qs-for-query-title.md' import QsForQueryBody from '/docs/snippets/qs-for-query-body.md' -import NotV5 from '/docs/snippets/_not-updated-to-v5.md' import ScreenshotNumberReference from '/src/components/ScreenshotNumberReference.jsx'; -# 🧠 Understanding the `populate` parameter for the REST API +# Understanding the `populate` parameter for the REST API + + + +The `populate` parameter in REST API queries includes additional fields, relations, components, and dynamic zones in responses beyond default attributes. Use `populate=*` for all 1-level-deep relations, or explicitly specify fields with nested arrays and fragment syntax for deeper or selective population. + + - :::note Note: Example responses might differ from your experience @@ -80,17 +84,24 @@ The following example is the full response for all 4 entries from the `articles` Notice how the response only includes the `title`, `slug`, `createdAt`, `updatedAt`, `publishedAt`, and `locale` fields, and the field content of the article as handled by the CKEditor plugin (`ckeditor_content`, truncated for brevity): - - - -`GET /api/articles` - - - - - -```json -{ + - +}` + } + ]} +/> ### Example: With `populate=*` @@ -158,7 +168,7 @@ With the `populate=*` parameter, a `GET` request to `/api/articles` also returns The following example is the full response for the first of all 4 entries from the `articles` content-types (the data from articles with ids 2, 3, and 4 is truncated for brevity). Scroll down to see that the response size is much bigger than without populate. The response now includes additional fields (see highlighted lines) such as: -* the `image` media field (which stores all information about the article cover, including all its different formats), +* the `image` media field (which stores all information about the article cover, including all its different formats), * the first-level fields of the `blocks` dynamic zone and the `seo` component, * the `category` relation and its fields, * and even some information about the articles translated in other languages, as shown by the `localizations` object. @@ -168,17 +178,25 @@ To populate deeply nested components, see the [populate components](#populate-co :::
- - - -`GET /api/articles?populate=*` - - - - -```json {13-122} -{ + - +}` + } + ]} +/> ## Populate specific relations and fields @@ -375,7 +392,7 @@ Populate as an array
(to populate many relations 1 level deep) ```json { - populate: [ + populate: [ 'articles', 'restaurants' ], @@ -411,17 +428,24 @@ Notice that the response does not include any media fields, relations, component
- - - -`GET /api/articles` - - - - - -```json -{ + - +}` + } + ]} +/> #### Example: With `populate[0]=category` @@ -491,17 +513,24 @@ The following example is the full response for all 4 entries from the `articles` Notice that the response now includes additional data with the `category` field for each article (see highlighted lines): - - - -`GET /api/articles?populate[0]=category` - - - - - -```json {13-23,36-46,59-69,82-92} -{ + - +}` + } + ]} +/> ### Populate several levels deep for specific relations @@ -641,17 +669,24 @@ Let's compare and explain the responses returned with `populate[0]=category` (1 When we only populate 1 level deep, asking for the categories associated to articles, we can get the following example response (highlighted lines show the `category` relations field): - - - -`GET /api/articles?populate[0]=category` - - - - - -```json {13-23,36-46,59-69,82-92} -{ + - +}` + } + ]} +/> #### Example: With 2-level deep population @@ -757,17 +791,24 @@ When we populate 2 levels deep, asking for the categories associated to articles Notice that we now have the `restaurants` relation field included with the response inside the `category` relation (see highlighted lines): - - - -`GET /api/articles?populate[category][populate][0]=restaurants` - - - - - -```json {13-56} -{{ + - +}` + } + ]} +/> ### Populate components @@ -892,17 +932,24 @@ When we only populate the `seo` component, we go only 1 level deep, and we can g Notice there's no mention of the `metaSocial` component nested within the `seo` component: - - - -`GET /api/articles?populate[0]=seo` - - - - - -```json {13-22} -{ + - +}` + } + ]} +/> #### Example: 1st level and 2nd level component @@ -959,17 +1005,24 @@ When we populate 2 levels deep, asking both for the `seo` component and the `met Notice that we now have the `metaSocial` component-related data included with the response (see highlighted lines): - - - -`GET /api/articles?populate[0]=seo&populate[1]=seo.metaSocial` - - - - - -```json {13,22-29} -{ + - +}` + } + ]} +/> ### Populate dynamic zones -Dynamic zones are highly dynamic content structures by essence. To populate dynamic zones and their content, you need to explicitly define what to populate with the response. - +}` + } + ]} +/> --> Dynamic zones are highly dynamic content structures by essence. When querying dynamic zones, standard populate parameters (such as `populate[0]=dynamic-zone-name` or `populate=*`) will only fetch the default scalar fields (e.g., strings, numbers, booleans) of the components within the dynamic zone. By default, they will **not** populate nested relations, media fields, or nested components inside those components. @@ -1300,18 +1362,24 @@ In the following example response, highlighted lines show that: - But because we have only asked to populate everything for the `CtaCommandLine` component and have not defined anything for the `faq` component, no data from the `faq` component is returned. - - - - -`GET /api/articles?populate[blocks][on][blocks.related-articles][populate][articles][populate][0]=image&populate[blocks][on][blocks.cta-command-line][populate]=*` - - - - - -```json {16-17,29-34} -{ + - - +}` + } + ]} +/> :::tip Avoid over-populating in production Using `populate=*` or deep population plugins can create unpredictable, costly database queries. In production, always populate explicitly and limit depth to 2-3 levels. Consider using route-level middlewares to centralize population logic. See on the Strapi blog. diff --git a/docusaurus/docs/cms/api/rest/interactive-query-builder.md b/docusaurus/docs/cms/api/rest/interactive-query-builder.md index c8346d57f6..be7982a29b 100644 --- a/docusaurus/docs/cms/api/rest/interactive-query-builder.md +++ b/docusaurus/docs/cms/api/rest/interactive-query-builder.md @@ -12,6 +12,13 @@ tags: # Build your query URL with Strapi's interactive tool + + +An interactive query builder tool that automatically generates REST API query URLs from your endpoint and parameters, powered by the `qs` library to handle complex nested queries. + + + + A wide range of parameters can be used and combined to query your content with the [REST API](/cms/api/rest), which can result in long and complex query URLs. Strapi's codebase uses to parse and stringify nested JavaScript objects. It's recommended to use `qs` directly to generate complex query URLs instead of creating them manually. diff --git a/docusaurus/docs/cms/api/rest/locale.md b/docusaurus/docs/cms/api/rest/locale.md index f250e5aa4a..4db4189937 100644 --- a/docusaurus/docs/cms/api/rest/locale.md +++ b/docusaurus/docs/cms/api/rest/locale.md @@ -19,6 +19,13 @@ import QsForQueryTitle from '/docs/snippets/qs-for-query-title.md' # REST API: `locale` + + +The `locale` REST API parameter retrieves and manages documents in specific languages, defaulting to the application's default locale. Use it to fetch, create, update, and delete locale-specific versions of documents in both collection and single types. + + + + The [Internationalization (i18n) feature](/cms/features/internationalization) adds new abilities to the [REST API](/cms/api/rest). :::prerequisites @@ -63,53 +70,57 @@ The following table lists the new possible use cases added by i18n to the REST A ### `GET` Get all documents in a specific locale {#rest-get-all} - - - - -`GET http://localhost:1337/api/restaurants?locale=fr` - - - - - -```json -{ - "data": [ + - + }, null, 2), + }, + ]} +/> ### `GET` Get a document in a specific locale {#rest-get} @@ -124,87 +135,91 @@ To get a specific document in a given locale, add the `locale` parameter to the To get a specific document in a collection type in a given locale, add the `locale` parameter to the query, after the `documentId`: - - - - -`GET /api/restaurants/lr5wju2og49bf820kj9kz8c3?locale=fr` - - - - - -```json -{ - "data": [ + - - + ]} +/> #### Single types {#get-one-single-type} To get a specific single type document in a given locale, add the `locale` parameter to the query, after the single type name: - - - - -`GET /api/homepage?locale=fr` - - - - - -```json -{ - "data": { - "id": 10, - "documentId": "ukbpbnu8kbutpn98rsanyi50", - "Title": "Page d'accueil", - "Body": null, - "createdAt": "2024-03-07T13:28:26.349Z", - "updatedAt": "2024-03-07T13:28:26.349Z", - "publishedAt": "2024-03-07T13:28:26.353Z", - "locale": "fr" - }, - "meta": {} -} -``` - - - - + ### `POST` Create a new localized document for a collection type {#rest-create} @@ -219,81 +234,87 @@ To create a localized document from scratch, send a POST request to the Content If no locale has been passed in the request body, the document is created using the default locale for the application: - - - -`POST http://localhost:1337/api/restaurants` + - - - -```json -{ - "data": { - "id": 13, - "documentId": "jae8klabhuucbkgfe2xxc5dj", - "Name": "Oplato", - "Description": null, - "createdAt": "2024-03-06T22:19:54.646Z", - "updatedAt": "2024-03-06T22:19:54.646Z", - "publishedAt": "2024-03-06T22:19:54.649Z", - "locale": "en" - }, - "meta": {} -} -``` - - - +}`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: { + id: 13, + documentId: "jae8klabhuucbkgfe2xxc5dj", + Name: "Oplato", + Description: null, + createdAt: "2024-03-06T22:19:54.646Z", + updatedAt: "2024-03-06T22:19:54.646Z", + publishedAt: "2024-03-06T22:19:54.649Z", + locale: "en" + }, + meta: {} + }, null, 2), + }, + ]} +/> #### For a specific locale {#rest-create-specific-locale} To create a localized entry for a locale different from the default one, add the `locale` parameter to the query URL of the POST request: - - - -`POST http://localhost:1337/api/restaurants?locale=fr` + - - - -```json -{ - "data": { - "id": 15, - "documentId": "ldcmn698iams5nuaehj69j5o", - "Name": "She's Cake", - "Description": null, - "createdAt": "2024-03-06T22:21:18.373Z", - "updatedAt": "2024-03-06T22:21:18.373Z", - "publishedAt": "2024-03-06T22:21:18.378Z", - "locale": "fr" - }, - "meta": {} -} -``` - - - +}`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: { + id: 15, + documentId: "ldcmn698iams5nuaehj69j5o", + Name: "She's Cake", + Description: null, + createdAt: "2024-03-06T22:21:18.373Z", + updatedAt: "2024-03-06T22:21:18.373Z", + publishedAt: "2024-03-06T22:21:18.378Z", + locale: "fr" + }, + meta: {} + }, null, 2), + }, + ]} +/> ### `PUT` Create a new, or update an existing, locale version for an existing document {#rest-update} @@ -325,85 +346,87 @@ It is not possible to change the locale of an existing localized entry. When upd To create a new locale for an existing document in a collection type, add the `locale` parameter to the query, after the `documentId`, and pass data to the request's body: - - - - -`PUT http://localhost:1337/api/restaurants/lr5wju2og49bf820kj9kz8c3?locale=fr` + - - - -```json -{ - "data": { - "id": 19, - "documentId": "lr5wju2og49bf820kj9kz8c3", - "Name": "She's Cake in French", - "Description": null, - "createdAt": "2024-03-07T12:13:09.551Z", - "updatedAt": "2024-03-07T12:13:09.551Z", - "publishedAt": "2024-03-07T12:13:09.554Z", - "locale": "fr" - }, - "meta": {} -} -``` - - - - +}`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: { + id: 19, + documentId: "lr5wju2og49bf820kj9kz8c3", + Name: "She's Cake in French", + Description: null, + createdAt: "2024-03-07T12:13:09.551Z", + updatedAt: "2024-03-07T12:13:09.551Z", + publishedAt: "2024-03-07T12:13:09.554Z", + locale: "fr" + }, + meta: {} + }, null, 2), + }, + ]} +/> #### In a single type {#rest-put-single-type} To create a new locale for an existing single type document, add the `locale` parameter to the query, after the single type name, and pass data to the request's body: - - - - -`PUT http://localhost:1337/api/homepage?locale=fr` + - - - -```json -{ - "data": { - "id": 10, - "documentId": "ukbpbnu8kbutpn98rsanyi50", - "Title": "Page d'accueil", - "Body": null, - "createdAt": "2024-03-07T13:28:26.349Z", - "updatedAt": "2024-03-07T13:28:26.349Z", - "publishedAt": "2024-03-07T13:28:26.353Z", - "locale": "fr" - }, - "meta": {} -} -``` - - - - +}`, + }, + ]} + responses={[ + { + status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: { + id: 10, + documentId: "ukbpbnu8kbutpn98rsanyi50", + Title: "Page d'accueil", + Body: null, + createdAt: "2024-03-07T13:28:26.349Z", + updatedAt: "2024-03-07T13:28:26.349Z", + publishedAt: "2024-03-07T13:28:26.353Z", + locale: "fr" + }, + meta: {} + }, null, 2), + }, + ]} +/>
@@ -417,18 +440,48 @@ To delete a locale version of a document, send a `DELETE` request with the appro To delete only a specific locale version of a document in a collection type, add the `locale` parameter to the query after the `documentId`: - - -`DELETE /api/restaurants/abcdefghijklmno456?locale=fr` - - + #### In a single type {#rest-delete-single-type} To delete only a specific locale version of a single type document, add the `locale` parameter to the query after the single type name: - - -`DELETE /api/homepage?locale=fr` - - + diff --git a/docusaurus/docs/cms/api/rest/parameters.md b/docusaurus/docs/cms/api/rest/parameters.md index d683c6e6a5..efe90e4beb 100644 --- a/docusaurus/docs/cms/api/rest/parameters.md +++ b/docusaurus/docs/cms/api/rest/parameters.md @@ -16,6 +16,13 @@ tags: # REST API parameters + + +REST API parameters filter, sort, paginate, and select fields and relations in Strapi queries. Use `filters`, `locale`, `populate`, `sort`, and `pagination` to refine your content requests. + + + + API parameters can be used with the [REST API](/cms/api/rest) to filter, sort, and paginate results and to select fields and relations to populate. Additionally, specific parameters related to optional Strapi features can be used, like the publication state and locale of a content-type. The following API parameters are available: diff --git a/docusaurus/docs/cms/api/rest/populate-select.md b/docusaurus/docs/cms/api/rest/populate-select.md index 282da2f41e..9802a65dfa 100644 --- a/docusaurus/docs/cms/api/rest/populate-select.md +++ b/docusaurus/docs/cms/api/rest/populate-select.md @@ -50,18 +50,20 @@ Queries can accept a `fields` parameter to select only some fields. By default, Field selection does not work on relational, media, component, or dynamic zone fields. To populate these fields, use the [`populate` parameter](#population). ::: - - - -`GET /api/restaurants?fields[0]=name&fields[1]=description` - -
-JavaScript query (built with the qs library) - - - -```js -const qs = require('qs'); + -
-
- - - -```json -{ - "data": [ +await request(\`/api/users?\${query}\`);`, + }, + ]} + responses={[ { - "id": 4, - "Name": "Pizzeria Arrivederci", - "Description": [ - { - "type": "paragraph", - "children": [ - { - "type": "text", - "text": "Specialized in pizza, we invite you to rediscover our classics, such as 4 Formaggi or Calzone, and our original creations such as Do Luigi or Nduja." - } - ] + status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: [ + { + id: 4, + Name: "Pizzeria Arrivederci", + Description: [ + { + type: "paragraph", + children: [ + { + type: "text", + text: "Specialized in pizza, we invite you to rediscover our classics, such as 4 Formaggi or Calzone, and our original creations such as Do Luigi or Nduja." + } + ] + } + ], + documentId: "lr5wju2og49bf820kj9kz8c3" + } + ], + meta: { + pagination: { + page: 1, + pageSize: 25, + pageCount: 1, + total: 4 + } } - ], - "documentId": "lr5wju2og49bf820kj9kz8c3" + }, null, 2), }, - // … - ], - "meta": { - "pagination": { - "page": 1, - "pageSize": 25, - "pageCount": 1, - "total": 4 - } - } -} -``` - - -
+ ]} +/> ## Population @@ -125,7 +122,7 @@ The `find` permission must be enabled for the content-types that are being popul You can use the `populate` parameter alone or [in combination with multiple operators](#combining-population-with-other-operators) for more control over the population. -:::caution +:::caution `populate=deep` plugins are [not recommended in Strapi](https://support.strapi.io/articles/8544110758-why-populate-deep-plugins-are-not-recommended-in-strapi). ::: @@ -162,18 +159,19 @@ Top-level pagination parameters (e.g., `pagination[page]` and `pagination[pageSi `fields` and `populate` can be combined. - - - -`GET /api/articles?fields[0]=title&fields[1]=slug&populate[headerImage][fields][0]=name&populate[headerImage][fields][1]=url` - -
-JavaScript query (built with the qs library) - - - -```js -const qs = require('qs'); + -
-
- - - -```json -{ - "data": [ +await request(\`/api/articles?\${query}\`);`, + }, + ]} + responses={[ { - "id": 1, - "documentId": "h90lgohlzfpjf3bvan72mzll", - "title": "Test Article", - "slug": "test-article", - "headerImage": { - "id": 1, - "documentId": "cf07g1dbusqr8mzmlbqvlegx", - "name": "17520.jpg", - "url": "/uploads/17520_73c601c014.jpg" - } - } - ], - "meta": { - // ... - } -} -``` - - -
+ status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: [ + { + id: 1, + documentId: "h90lgohlzfpjf3bvan72mzll", + title: "Test Article", + slug: "test-article", + headerImage: { + id: 1, + documentId: "cf07g1dbusqr8mzmlbqvlegx", + name: "17520.jpg", + url: "/uploads/17520_73c601c014.jpg" + } + } + ], + meta: {} + }, null, 2), + }, + ]} +/> #### Populate with filtering `filters` and `populate` can be combined. - - - -`GET /api/articles?populate[categories][sort][0]=name%3Aasc&populate[categories][filters][name][$eq]=Cars` - -
-JavaScript query (built with the qs library) - - - -```js -const qs = require('qs'); + - -
-
- - - -```json -{ - "data": [ +await request(\`/api/articles?\${query}\`);`, + }, + ]} + responses={[ { - "id": 1, - "documentId": "a1b2c3d4e5d6f7g8h9i0jkl", - "title": "Test Article", - // ... - "categories": { - "data": [ + status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: [ { - "id": 2, - "documentId": "jKd8djla9ndalk98hflj3", - "name": "Cars" - // ... + id: 1, + documentId: "a1b2c3d4e5d6f7g8h9i0jkl", + title: "Test Article", + categories: { + data: [ + { + id: 2, + documentId: "jKd8djla9ndalk98hflj3", + name: "Cars" + } + ] + } } - ] - } - } - } - ], - "meta": { - // ... - } -} -``` - - -
+ ], + meta: {} + }, null, 2), + }, + ]} +/> :::note For many-to-many and other join-table relations, an explicit `sort` within a `populate` object overrides the default connect order. Omit `sort` to preserve the connect order (the order in which entries were associated). @@ -302,4 +285,4 @@ For many-to-many and other join-table relations, an explicit `sort` within a `po :::tip Performance tip In production, always use explicit population instead of wildcards like `populate=*`. Limit population depth to 2-3 levels and consider centralizing population logic in route middlewares. See on the Strapi blog. -::: \ No newline at end of file +::: diff --git a/docusaurus/docs/cms/api/rest/relations.md b/docusaurus/docs/cms/api/rest/relations.md index 67d242acbf..2e2f5bfd99 100644 --- a/docusaurus/docs/cms/api/rest/relations.md +++ b/docusaurus/docs/cms/api/rest/relations.md @@ -13,6 +13,13 @@ tags: # Managing relations with API requests + + +Use `connect`, `disconnect`, and `set` parameters in REST and GraphQL API requests to manage relations between content-types. Reorder relations using positional arguments like `before`, `after`, `start`, or `end`. + + + + Defining relations between content-types (that are designated as entities in the database layers) is connecting entities with each other. Relations between content-types can be managed through the [admin panel](/cms/features/content-manager#relational-fields) or through [REST API](/cms/api/rest) or [Document Service API](/cms/api/document-service) requests. diff --git a/docusaurus/docs/cms/api/rest/sort-pagination.md b/docusaurus/docs/cms/api/rest/sort-pagination.md index 01c4ed4529..ccba21f8e9 100644 --- a/docusaurus/docs/cms/api/rest/sort-pagination.md +++ b/docusaurus/docs/cms/api/rest/sort-pagination.md @@ -22,6 +22,13 @@ import QsForQueryBody from '/docs/snippets/qs-for-query-body.md' # REST API: Sort & Pagination + + +Sort REST API results on one or multiple fields with `:asc` or `:desc` syntax, and paginate using either page-based or offset-based parameters. + + + + Entries that are returned by queries to the [REST API](/cms/api/rest) can be sorted and paginated. :::tip @@ -47,37 +54,34 @@ The sorting order can be defined with: You can sort by multiple fields by passing fields in a `sort` array. -
- - - - -`GET /api/restaurants?sort[0]=Description&sort[1]=Name` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/restaurants?\${query}\`);` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "data": [ { "id": 9, @@ -93,7 +97,7 @@ await request(`/api/restaurants?${query}`); } ] } - ], + ] // … }, { @@ -110,55 +114,51 @@ await request(`/api/restaurants?${query}`); } ] } - ], + ] // … - }, - // … + } + // … ], "meta": { // … } -} -``` - - - +}` + } + ]} +/> ### Example: Sort using 2 fields and set the order Using the `sort` parameter and defining `:asc` or `:desc` on sorted fields, you can get results sorted in a particular order. -
- - - - -`GET /api/restaurants?sort[0]=Description:asc&sort[1]=Name:desc` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/restaurants?\${query}\`);` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "data": [ { "id": 8, @@ -174,7 +174,7 @@ await request(`/api/restaurants?${query}`); } ] } - ], + ] // … }, { @@ -191,20 +191,18 @@ await request(`/api/restaurants?${query}`); } ] } - ], + ] // … - }, + } // … ], "meta": { // … } -} -``` - - - - +}` + } + ]} +/> ## Pagination @@ -227,20 +225,19 @@ To paginate results by page, use the following parameters: | `pagination[pageSize]` | Integer | Page size | 25 | | `pagination[withCount]` | Boolean | Adds the total numbers of entries and the number of pages to the response | True | - - - -`GET /api/articles?pagination[page]=1&pagination[pageSize]=10` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/articles?\${query}\`);` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "data": [ // ... ], @@ -270,11 +266,10 @@ await request(`/api/articles?${query}`); "total": 48 } } -} -``` - - - +}` + } + ]} +/> ### Pagination by offset @@ -290,20 +285,19 @@ To paginate results by offset, use the following parameters: The default and maximum values for `pagination[limit]` can be [configured in the `./config/api.js`](/cms/configurations/api) file with the `api.rest.defaultLimit` and `api.rest.maxLimit` keys. ::: - - - -`GET /api/articles?pagination[start]=0&pagination[limit]=10` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json -{ +await request(\`/api/articles?\${query}\`);` + } + ]} + responses={[ + { + status: 200, + statusText: "OK", + body: `{ "data": [ // ... ], @@ -332,8 +325,7 @@ await request(`/api/articles?${query}`); "total": 42 } } -} -``` - - - +}` + } + ]} +/> diff --git a/docusaurus/docs/cms/api/rest/status.md b/docusaurus/docs/cms/api/rest/status.md index 2d38ff9a0f..14f6a693e3 100644 --- a/docusaurus/docs/cms/api/rest/status.md +++ b/docusaurus/docs/cms/api/rest/status.md @@ -20,6 +20,13 @@ import QsForQueryTitle from '/docs/snippets/qs-for-query-title.md' # REST API: `status` + + +The REST API's `status` parameter filters documents by their publication state, returning either published versions (default) or drafts by passing `status=draft`. + + + + The [REST API](/cms/api/rest) offers the ability to filter results based on their status, draft or published. :::prerequisites @@ -41,69 +48,61 @@ Since published versions are returned by default, passing no status parameter is

- - - -`GET /api/articles?status=draft` - - - -
-JavaScript query (built with the qs library): - - - -```js -const qs = require('qs'); + - - - -```json {21} -{ - "data": [ - // … +await request(\`/api/articles?\${query}\`);`, + }, + ]} + responses={[ { - "id": 5, - "documentId": "znrlzntu9ei5onjvwfaalu2v", - "Name": "Biscotte Restaurant", - "Description": [ - { - "type": "paragraph", - "children": [ - { - "type": "text", - "text": "This is the draft version." - } - ] + status: 200, + statusText: 'OK', + body: JSON.stringify({ + data: [ + { + id: 5, + documentId: "znrlzntu9ei5onjvwfaalu2v", + Name: "Biscotte Restaurant", + Description: [ + { + type: "paragraph", + children: [ + { + type: "text", + text: "This is the draft version." + } + ] + } + ], + createdAt: "2024-03-06T13:43:30.172Z", + updatedAt: "2024-03-06T21:38:46.353Z", + publishedAt: null, + locale: "en" + } + ], + meta: { + pagination: { + page: 1, + pageSize: 25, + pageCount: 1, + total: 4 + } } - ], - "createdAt": "2024-03-06T13:43:30.172Z", - "updatedAt": "2024-03-06T21:38:46.353Z", - "publishedAt": null, - "locale": "en" + }, null, 2), }, - // … - ], - "meta": { - "pagination": { - "page": 1, - "pageSize": 25, - "pageCount": 1, - "total": 4 - } - } -} -``` - - - + ]} +/> diff --git a/docusaurus/docs/cms/api/rest/upload.md b/docusaurus/docs/cms/api/rest/upload.md index eface8c815..a3bb0ce5ea 100644 --- a/docusaurus/docs/cms/api/rest/upload.md +++ b/docusaurus/docs/cms/api/rest/upload.md @@ -11,6 +11,13 @@ tags: # REST API: Upload files + + +The `/api/upload` REST API endpoints enable you to upload files to the Media Library, retrieve paginated file lists, update file metadata, and delete files from your Strapi application. + + + + The [Media Library feature](/cms/features/media-library) is powered in the back-end server of Strapi by the `upload` package. To upload files to Strapi, you can either use the Media Library directly from the admin panel, or use the [REST API](/cms/api/rest), with the following available endpoints : | Method | Path | Description | diff --git a/docusaurus/docs/cms/backend-customization/controllers.md b/docusaurus/docs/cms/backend-customization/controllers.md index 074b20115d..38fee4d85a 100644 --- a/docusaurus/docs/cms/backend-customization/controllers.md +++ b/docusaurus/docs/cms/backend-customization/controllers.md @@ -18,7 +18,7 @@ tags: # Controllers -Controllers bundle actions that handle business logic for each route within Strapi’s MVC pattern. This documentation demonstrates generating controllers, extending core ones with `createCoreController`, and delegating heavy logic to services. +Controllers bundle actions that handle business logic for each route within Strapi's MVC pattern. This documentation demonstrates generating controllers, extending core ones with `createCoreController`, and delegating heavy logic to services. Controllers are JavaScript files that contain a set of methods, called actions, reached by the client according to the requested [route](/cms/backend-customization/routes). Whenever a client requests the route, the action performs the business logic code and sends back the [response](/cms/backend-customization/requests-responses). Controllers represent the C in the model-view-controller (MVC) pattern. @@ -265,7 +265,7 @@ module.exports = { It's strongly recommended you sanitize (v4.8.0+) and/or validate (v4.13.0+) your incoming request query utilizing the new `sanitizeQuery` and `validateQuery` functions to prevent the leaking of private data. ::: -Sanitization means that the object is “cleaned” and returned. +Sanitization means that the object is “cleaned” and returned. Validation means an assertion is made that the data is already clean and throws an error if something is found that shouldn't be there. @@ -409,12 +409,9 @@ export default { Default controllers and actions are created for each content-type. These default controllers are used to return responses to API requests (e.g. when `GET /api/articles/3` is accessed, the `findOne` action of the default controller for the "Article" content-type is called). Default controllers can be customized to implement your own logic. The following code examples should help you get started. -:::tip -An action from a core controller can be replaced entirely by [creating a custom action](#adding-a-new-controller) and naming the action the same as the original action (e.g. `find`, `findOne`, `create`, `update`, or `delete`). -::: - -:::tip -When extending a core controller, you do not need to re-implement any sanitization as it will already be handled by the core controller you are extending. Where possible it's strongly recommended to extend the core controller instead of creating a custom controller. +:::tip +- An action from a core controller can be replaced entirely by [creating a custom action](#adding-a-new-controller) and naming the action the same as the original action (e.g. `find`, `findOne`, `create`, `update`, or `delete`). +- When extending a core controller, you do not need to re-implement any sanitization as it will already be handled by the core controller you are extending. Where possible it's strongly recommended to extend the core controller instead of creating a custom controller. :::
@@ -424,7 +421,7 @@ When extending a core controller, you do not need to re-implement any sanitizati The [backend customization examples cookbook](/cms/backend-customization/examples) shows how you can overwrite a default controller action, for instance for the [`create` action](/cms/backend-customization/examples/services-and-controllers#custom-controller). ::: - + ```js async find(ctx) { diff --git a/docusaurus/docs/cms/backend-customization/examples.md b/docusaurus/docs/cms/backend-customization/examples.md index 209ec237fc..94b5d6d98b 100644 --- a/docusaurus/docs/cms/backend-customization/examples.md +++ b/docusaurus/docs/cms/backend-customization/examples.md @@ -6,11 +6,18 @@ pagination_prev: cms/backend-customization pagination_next: cms/backend-customization/examples/authentication --- -import NotV5 from '/docs/snippets/_not-updated-to-v5.md' +import CookbookNote from '/docs/snippets/_cookbook-foodadvisor.md' # Backend customization: An examples cookbook using FoodAdvisor - + + +A cookbook of real-world backend customization examples using the FoodAdvisor demo application, demonstrating how to implement custom routes, controllers, services, policies, and middlewares in Strapi. + + + + + The present section of the documentation is intended for developers who would like to get a deeper understanding of the Strapi back end customization possibilities. diff --git a/docusaurus/docs/cms/backend-customization/examples/authentication.md b/docusaurus/docs/cms/backend-customization/examples/authentication.md index 98141eb8d5..c8651e5ff1 100644 --- a/docusaurus/docs/cms/backend-customization/examples/authentication.md +++ b/docusaurus/docs/cms/backend-customization/examples/authentication.md @@ -8,6 +8,13 @@ pagination_next: cms/backend-customization/examples/services-and-controllers # Examples cookbook: Authentication flow with JWT + + +Authenticate REST API requests using JWT by sending credentials to the `/auth/local` endpoint and storing the token in `localStorage`, with optional session management for refresh token support. + + + + :::prerequisites This page is part of the back end customization examples cookbook. Please ensure you've read its [introduction](/cms/backend-customization/examples). ::: diff --git a/docusaurus/docs/cms/backend-customization/examples/middlewares.md b/docusaurus/docs/cms/backend-customization/examples/middlewares.md index afcaa31d2d..81f9512f63 100644 --- a/docusaurus/docs/cms/backend-customization/examples/middlewares.md +++ b/docusaurus/docs/cms/backend-customization/examples/middlewares.md @@ -5,11 +5,18 @@ displayed_sidebar: cmsSidebar pagination_prev: cms/backend-customization/examples/routes --- -import NotV5 from '/docs/snippets/_not-updated-to-v5.md' +import CookbookNote from '/docs/snippets/_cookbook-foodadvisor.md' # Examples cookbook: Custom global middlewares - + + +Custom global middlewares intercept incoming requests before controller execution, enabling you to add logic like analytics tracking. This example creates a middleware that logs restaurant page visits to a Google Sheet. + + + + + :::prerequisites This page is part of the back end customization examples cookbook. Please ensure you've read its [introduction](/cms/backend-customization/examples). @@ -196,12 +203,11 @@ Additional information can be found in the [middlewares customization](/cms/back tabName, }); - // Get the restaurant ID from the params in the URL + // Get the restaurant documentId from the params in the URL const restaurantId = context.params.id; - const restaurant = await strapi.entityService.findOne( - 'api::restaurant.restaurant', - restaurantId - ); + const restaurant = await strapi.documents('api::restaurant.restaurant').findOne({ + documentId: restaurantId, + }); // Read the spreadsheet to get the current data const restaurantAnalytics = await readGoogleSheet(); diff --git a/docusaurus/docs/cms/backend-customization/examples/policies.md b/docusaurus/docs/cms/backend-customization/examples/policies.md index 17e08decee..5bdad1d67d 100644 --- a/docusaurus/docs/cms/backend-customization/examples/policies.md +++ b/docusaurus/docs/cms/backend-customization/examples/policies.md @@ -6,11 +6,18 @@ pagination_prev: cms/backend-customization/examples/services-and-controllers pagination_next: cms/backend-customization/examples/routes --- -import NotV5 from '/docs/snippets/_not-updated-to-v5.md' +import CookbookNote from '/docs/snippets/_cookbook-foodadvisor.md' # Examples cookbook: Custom policies - + + +Custom policies control access to content-type endpoints by allowing or blocking requests, and can throw custom errors using `PolicyError` for better error handling and front-end integration. + + + + + :::prerequisites This page is part of the back end customization examples cookbook. Please ensure you've read its [introduction](/cms/backend-customization/examples). @@ -39,7 +46,7 @@ Let's say we would like to customize the backend of @@ -48,7 +55,7 @@ Let's say we would like to customize the backend of -Additional information can be found in the [Policies](/cms/backend-customization/policies), [Routes](/cms/backend-customization/routes), and [Entity Service API](/cms/api/entity-service) documentation. +Additional information can be found in the [Policies](/cms/backend-customization/policies), [Routes](/cms/backend-customization/routes), and [Document Service API](/cms/api/document-service) documentation. @@ -72,18 +79,15 @@ module.exports = async (policyContext, config, { strapi }) => { } /** * Queries the Restaurants collection type - * using the Entity Service API + * using the Document Service API * to retrieve information about the restaurant's owner. */ - const [restaurant] = await strapi.entityService.findMany( - 'api::restaurant.restaurant', - { - filters: { - slug: body.restaurant, - }, - populate: ['owner'], - } - ); + const [restaurant] = await strapi.documents('api::restaurant.restaurant').findMany({ + filters: { + slug: body.restaurant, + }, + populate: ['owner'], + }); if (!restaurant) { return false; } @@ -150,18 +154,15 @@ module.exports = async (policyContext, config, { strapi }) => { } /** * Queries the Restaurants collection type - * using the Entity Service API + * using the Document Service API * to retrieve information about the restaurant's owner. */ - const filteredRestaurants = await strapi.entityService.findMany( - 'api::restaurant.restaurant', - { - filters: { - slug: body.restaurant, - }, - populate: ['owner'], - } - ); + const filteredRestaurants = await strapi.documents('api::restaurant.restaurant').findMany({ + filters: { + slug: body.restaurant, + }, + populate: ['owner'], + }); const restaurant = filteredRestaurants[0]; diff --git a/docusaurus/docs/cms/backend-customization/examples/routes.md b/docusaurus/docs/cms/backend-customization/examples/routes.md index 257d7c09a5..c31ed7fc1e 100644 --- a/docusaurus/docs/cms/backend-customization/examples/routes.md +++ b/docusaurus/docs/cms/backend-customization/examples/routes.md @@ -6,11 +6,18 @@ pagination_prev: cms/backend-customization/examples/policies pagination_next: cms/backend-customization/examples/middlewares --- -import NotV5 from '/docs/snippets/_not-updated-to-v5.md' +import CookbookNote from '/docs/snippets/_cookbook-foodadvisor.md' # Examples cookbook: Custom routes - + + +Custom routes let you explicitly configure routes for content-types to control authentication and apply policies, such as bypassing default Strapi authentication or restricting access based on custom conditions. + + + + + :::prerequisites This page is part of the back end customization examples cookbook. Please ensure you've read its [introduction](/cms/backend-customization/examples). diff --git a/docusaurus/docs/cms/backend-customization/examples/services-and-controllers.md b/docusaurus/docs/cms/backend-customization/examples/services-and-controllers.md index 3f4e218049..7972e07d3e 100644 --- a/docusaurus/docs/cms/backend-customization/examples/services-and-controllers.md +++ b/docusaurus/docs/cms/backend-customization/examples/services-and-controllers.md @@ -15,11 +15,18 @@ tags: - services --- -import NotV5 from '/docs/snippets/_not-updated-to-v5.md' +import CookbookNote from '/docs/snippets/_cookbook-foodadvisor.md' # Examples cookbook: Custom services and controllers - + + +Services encapsulate reusable business logic that controllers invoke to handle reviews and email notifications. This guide demonstrates creating custom services using the Document Service API and custom controllers that call them. + + + + + :::prerequisites This page is part of the back end customization examples cookbook. Please ensure you've read its [introduction](/cms/backend-customization/examples). @@ -33,7 +40,7 @@ This page will teach about the following advanced topics: |------|---------| | Create a component that interacts with the backend of Strapi | [REST API queries from the front-end](#rest-api-queries-from-the-front-end) | | Understand how services and controllers can play together | [Controllers vs. services](#controllers-vs-services) | -| Create custom services |
  • A [custom service](#custom-service-creating-a-review) that only uses the Entity Service API
  • Another more [advanced custom service](#custom-service-sending-an-email-to-the-restaurant-owner) that uses both Entity Service API and a Strapi plugin
| +| Create custom services |
  • A [custom service](#custom-service-creating-a-review) that only uses the Document Service API
  • Another more [advanced custom service](#custom-service-sending-an-email-to-the-restaurant-owner) that uses both the Document Service API and a Strapi plugin
| | Use services in a controller | [Custom controller](#custom-controller) |
@@ -223,8 +230,8 @@ Let's update the existing `review.js` service file for the "Reviews" collection - Declare a `create` method. - Grab context from the request. -- Use the `findMany()` method from the EntityService API to find a restaurant. -- Use the `create()` method from the EntityService API to append data to the restaurant, populating the restaurant owner. +- Use the `findMany()` method from the Document Service API to find a restaurant. +- Use the `create()` method from the Document Service API to append data to the restaurant, populating the restaurant owner. - Return the new review data. @@ -233,7 +240,7 @@ Let's update the existing `review.js` service file for the "Reviews" collection -Additional information can be found in the [request context](/cms/backend-customization/requests-responses), [services](/cms/backend-customization/services) and [EntityService API](/cms/api/entity-service) documentation. +Additional information can be found in the [request context](/cms/backend-customization/requests-responses), [services](/cms/backend-customization/services) and [Document Service API](/cms/api/document-service) documentation. @@ -255,28 +262,25 @@ module.exports = createCoreService('api::review.review', ({ strapi }) => ({ /** * Queries the Restaurants collection type - * using the Entity Service API + * using the Document Service API * to retrieve information about the restaurant. */ - const restaurants = await strapi.entityService.findMany( - 'api::restaurant.restaurant', - { - filters: { - slug: body.restaurant, - }, - } - ); + const restaurants = await strapi.documents('api::restaurant.restaurant').findMany({ + filters: { + slug: body.restaurant, + }, + }); /** * Creates a new entry for the Reviews collection type * and populates data with information about the restaurant's owner - * using the Entity Service API. + * using the Document Service API. */ - const newReview = await strapi.entityService.create('api::review.review', { + const newReview = await strapi.documents('api::review.review').create({ data: { note: body.note, content: body.content, - restaurant: restaurants[0].id, + restaurant: restaurants[0].documentId, author: user.id, }, populate: ['restaurant.owner'], @@ -334,7 +338,7 @@ This service is an advanced code example using the [Email](/cms/features/email) - Create a new service file for the "Email" single type, - Declare a `send()` method for this service, -- Grab the sender address stored in the Email single type using the Entity Service API, +- Grab the sender address stored in the Email single type using the Document Service API, - Use email details (recipient's address, subject, and email body) passed when invoking the service's `send()` method to send an email using the Email plugin and a previously configured provider. @@ -343,7 +347,7 @@ This service is an advanced code example using the [Email](/cms/features/email) -Additional information can be found in the [Services](/cms/backend-customization/services), [Entity Service API](/cms/api/entity-service) and [Email feature](/cms/features/email) documentation. +Additional information can be found in the [Services](/cms/backend-customization/services), [Document Service API](/cms/api/document-service) and [Email feature](/cms/features/email) documentation. @@ -364,12 +368,10 @@ module.exports = createCoreService('api::email.email', ({ strapi }) => ({ /** * Retrieves email configuration data * stored in the Email single type - * using the Entity Service API. + * using the Document Service API. + * For a single type, use findFirst() to get its document. */ - const emailConfig = await strapi.entityService.findOne( - 'api::email.email', - 1 - ); + const emailConfig = await strapi.documents('api::email.email').findFirst(); /** * Sends an email using: diff --git a/docusaurus/docs/cms/billing-portal.md b/docusaurus/docs/cms/billing-portal.md index 9e143e8fbd..d0f81094c9 100644 --- a/docusaurus/docs/cms/billing-portal.md +++ b/docusaurus/docs/cms/billing-portal.md @@ -73,11 +73,11 @@ To update the seat count or add-ons of an active Growth subscription: 4. Click **Confirm** to apply the changes. :::note -When you add seats or enable the SSO add-on, the change applies immediately. You are charged a prorated amount for the remainder of the current billing period. +When you add seats or enable the SSO add-on, you are charged a prorated amount immediately. However, your Strapi CMS instance checks for license updates on startup and every 12 hours, so new seats may take up to 12 hours to appear in the admin panel. To apply the change sooner, restart your Strapi instance. When you remove seats or disable the SSO add-on, the change takes effect at the next renewal. Your current seat count and add-ons stay active until then. -If you add seats and disable SSO in the same change, the seat increase applies immediately with a prorated charge. SSO removal is still deferred to the next renewal. +If you add seats and disable SSO in the same change, the seat increase is charged immediately. SSO removal is still deferred to the next renewal. ::: ### Canceling a Growth subscription diff --git a/docusaurus/docs/cms/cli.md b/docusaurus/docs/cms/cli.md index 58c41c45ad..d3f3d540f4 100644 --- a/docusaurus/docs/cms/cli.md +++ b/docusaurus/docs/cms/cli.md @@ -452,7 +452,7 @@ strapi admin:create-user --firstname=Kai --lastname=Doe --email=chef@strapi.io - | -l, --lastname | string | The administrator's last name | No | | -e, --email | string | The administrator's email | Yes | | -p, --password | string | New password for the administrator | No | -| -h, --help | | display help for command | | +| -h, --help | | display help for command | No | ### `strapi admin:reset-user-password` @@ -504,7 +504,7 @@ strapi admin:active-user --email=chef@strapi.io --active=true | ------------ | ------ | -------------------------------------------- | -------- | | -e, --email | string | The administrator's email | Yes | | -a, --active | string | The active status to set (`true` or `false`) | Yes | -| -h, --help | | display help for command | | +| -h, --help | | display help for command | No | ### `strapi admin:block-user` @@ -524,7 +524,7 @@ strapi admin:block-user --email=chef@strapi.io --block=true | ----------- | ------ | --------------------------------------------- | -------- | | -e, --email | string | The administrator's email | Yes | | -b, --block | string | The blocked status to set (`true` or `false`) | Yes | -| -h, --help | | display help for command | | +| -h, --help | | display help for command | No | ### `strapi admin:delete-user` @@ -543,7 +543,7 @@ strapi admin:delete-user --email=chef@strapi.io | Option | Type | Description | Required | | --------------- | ------ | ----------------------------- | -------- | | -e, --email | string | The administrator's email | Yes | -| -h, --help | | display help for command | | +| -h, --help | | display help for command | No | ## Code generation diff --git a/docusaurus/docs/cms/community.md b/docusaurus/docs/cms/community.md index 045799209f..3872806af8 100644 --- a/docusaurus/docs/cms/community.md +++ b/docusaurus/docs/cms/community.md @@ -12,6 +12,13 @@ tags: # Community & Support + + +Strapi is an open-source, community-oriented project welcoming contributions to the core, documentation, and design system. Get support through GitHub Discussions and Discord for free, or access the Support platform with an active paid plan. + + + + Strapi is an open-source project (see file for more information). The core project, as well as the documentation and any related tool can be found in the GitHub organization. ## Open-source & Contribution diff --git a/docusaurus/docs/cms/configurations.md b/docusaurus/docs/cms/configurations.md index b935567b19..d781b59c79 100644 --- a/docusaurus/docs/cms/configurations.md +++ b/docusaurus/docs/cms/configurations.md @@ -16,11 +16,18 @@ import ProjectStructureConfigFiles from '@site/src/components/ProjectStructureCo # Configuration + + +Strapi applications are configured through files in the `/config` folder, including required base configurations for database, server, admin panel, middlewares, and API, plus optional configurations for plugins, TypeScript, API tokens, lifecycle functions, cron jobs, and environment variables. + + + + The configuration of a Strapi project lives in the `/config` folder: -The block above is an excerpt from the project structure. You can click on any file name in purple to read the corresponding documentation. Visit the project structure page for the full version. +

The block above is an excerpt from the project structure. You can click on any file name in purple to read the corresponding documentation. Visit the project structure page for the full version.

## Base configurations diff --git a/docusaurus/docs/cms/configurations/cron.md b/docusaurus/docs/cms/configurations/cron.md index e6c251eef0..23e4abb4b0 100644 --- a/docusaurus/docs/cms/configurations/cron.md +++ b/docusaurus/docs/cms/configurations/cron.md @@ -164,6 +164,7 @@ export default {
Advanced example #2: One-off cron jobs + The following cron job is run only once at a given time: diff --git a/docusaurus/docs/cms/configurations/guides/access-cast-environment-variables.md b/docusaurus/docs/cms/configurations/guides/access-cast-environment-variables.md index d5382e73fd..e50d0655f6 100644 --- a/docusaurus/docs/cms/configurations/guides/access-cast-environment-variables.md +++ b/docusaurus/docs/cms/configurations/guides/access-cast-environment-variables.md @@ -12,6 +12,13 @@ tags: # How to access and cast environment variables + + +The `env()` utility accesses environment variables from `.env` files and casts them to different types including `int`, `float`, `bool`, `json`, `array`, `date`, and `oneOf`. + + + + In most use cases there will be different configurations between environments (e.g. database credentials). Instead of writing those credentials into configuration files, variables can be defined in a `.env` file at the root of the application: diff --git a/docusaurus/docs/cms/configurations/guides/access-configuration-values.md b/docusaurus/docs/cms/configurations/guides/access-configuration-values.md index 388ddbcae9..5de07dc920 100644 --- a/docusaurus/docs/cms/configurations/guides/access-configuration-values.md +++ b/docusaurus/docs/cms/configurations/guides/access-configuration-values.md @@ -9,6 +9,13 @@ tags: # How to access to configuration values from the code + + +Access configuration values loaded on startup using the `strapi.config.get()` method with dot notation for nested keys across all configuration files. + + + + All the [configuration files](/cms/configurations) are loaded on startup and can be accessed through the `strapi.config` configuration provider. If the `/config/server.ts|js` file has the following configuration: diff --git a/docusaurus/docs/cms/configurations/guides/configure-sso.md b/docusaurus/docs/cms/configurations/guides/configure-sso.md index 5ce2bf87eb..1337297b40 100644 --- a/docusaurus/docs/cms/configurations/guides/configure-sso.md +++ b/docusaurus/docs/cms/configurations/guides/configure-sso.md @@ -16,6 +16,13 @@ tags: import NotV5 from '/docs/snippets/_not-updated-to-v5.md' # How to configure SSO providers + + + +Configure SSO providers in the Strapi admin panel by registering OAuth/OIDC applications, adding credentials to `auth.providers` in `/config/admin`, and setting up callback URLs to enable additional sign-in methods. + + + [Single Sign-On (SSO)](/cms/features/sso) on Strapi allows you to configure additional sign-in and sign-up methods for the Strapi admin panel. diff --git a/docusaurus/docs/cms/configurations/guides/rbac.md b/docusaurus/docs/cms/configurations/guides/rbac.md index a7b63c70bb..0adc5812a5 100644 --- a/docusaurus/docs/cms/configurations/guides/rbac.md +++ b/docusaurus/docs/cms/configurations/guides/rbac.md @@ -15,6 +15,13 @@ tags: # How to create custom conditions for Role-Based Access Control (RBAC) + + +Create custom Role-Based Access Control (RBAC) conditions in Strapi using the `conditionProvider` API to restrict admin panel access based on user properties, entity queries, or external conditions. + + + + Role-Based Access Control (RBAC) is an approach to restricting access to some users. In a Strapi application, users of the admin panel are administrators. Their roles and permissions are [configured in the admin panel](/cms/features/rbac). ## Declaring new conditions diff --git a/docusaurus/docs/cms/configurations/media-library-providers.md b/docusaurus/docs/cms/configurations/media-library-providers.md index b1ef4daa14..13c0216ee1 100644 --- a/docusaurus/docs/cms/configurations/media-library-providers.md +++ b/docusaurus/docs/cms/configurations/media-library-providers.md @@ -12,6 +12,13 @@ import MediaLibProvidersNotes from '/docs/snippets/media-library-providers-notes # Media Library providers + + +Media Library providers extend Strapi's upload capabilities to store files in external services like AWS S3 or Cloudinary. You can install official providers, configure them in `/config/plugins`, create custom providers, or set up private providers with signed URLs for secure asset access. + + + + The [Media Library](/cms/features/media-library) feature is powered by a back-end server package called Upload which leverages the use of providers. By default Strapi provides a provider that uploads files to a local `public/uploads/` directory in your Strapi project. Additional providers are available and add an extension to the core capabilities of the plugin. Use them to upload your files to another location, such as AWS S3 or Cloudinary. diff --git a/docusaurus/docs/cms/configurations/sso-providers/discord.md b/docusaurus/docs/cms/configurations/sso-providers/discord.md index 5735bffba6..1e9357bd80 100644 --- a/docusaurus/docs/cms/configurations/sso-providers/discord.md +++ b/docusaurus/docs/cms/configurations/sso-providers/discord.md @@ -10,6 +10,13 @@ tags: # Discord provider SSO configuration + + +Discord SSO provider enables users to sign in and sign up to Strapi through their Discord account. Configure it in `config/admin` using `passport-discord` with client credentials and email scope. + + + + The present page explains how to setup the Discord provider for the [Single Sign-On (SSO) feature](/cms/features/sso). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/sso-providers/github.md b/docusaurus/docs/cms/configurations/sso-providers/github.md index cec3b2bf8e..9027fa7b93 100644 --- a/docusaurus/docs/cms/configurations/sso-providers/github.md +++ b/docusaurus/docs/cms/configurations/sso-providers/github.md @@ -10,6 +10,13 @@ tags: # GitHub provider SSO configuration + + +Configure GitHub as an SSO provider for Strapi admin sign-in using `passport-github2` in the `config/admin` file with your GitHub OAuth credentials and user email scope. + + + + The present page explains how to setup the GitHub provider for the [Single Sign-On (SSO) feature](/cms/features/sso). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/sso-providers/google.md b/docusaurus/docs/cms/configurations/sso-providers/google.md index 9e2861f556..20654950ab 100644 --- a/docusaurus/docs/cms/configurations/sso-providers/google.md +++ b/docusaurus/docs/cms/configurations/sso-providers/google.md @@ -10,6 +10,13 @@ tags: # Google provider SSO configuration + + +Configure Google as an SSO provider in your Strapi admin panel to allow users to sign in and sign up using their Google account credentials. + + + + The present page explains how to setup the Google provider for the [Single Sign-On (SSO) feature](/cms/features/sso). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/sso-providers/keycloak.md b/docusaurus/docs/cms/configurations/sso-providers/keycloak.md index 22d27acbe4..ee2a1cc627 100644 --- a/docusaurus/docs/cms/configurations/sso-providers/keycloak.md +++ b/docusaurus/docs/cms/configurations/sso-providers/keycloak.md @@ -10,6 +10,13 @@ tags: # Keycloak (OpenID Connect) provider SSO configuration + + +Keycloak is an OpenID Connect SSO provider that lets users sign in to Strapi through Keycloak authentication using the `passport-keycloak-oauth2-oidc` strategy configured in `config/admin`. + + + + The present page explains how to setup the Keycloak provider for the [Single Sign-On (SSO) feature](/cms/features/sso). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/sso-providers/microsoft.md b/docusaurus/docs/cms/configurations/sso-providers/microsoft.md index 3c0752971a..b0ae94d75c 100644 --- a/docusaurus/docs/cms/configurations/sso-providers/microsoft.md +++ b/docusaurus/docs/cms/configurations/sso-providers/microsoft.md @@ -10,6 +10,13 @@ tags: # Microsoft provider SSO configuration + + +Configure the Microsoft SSO provider using `passport-azure-ad-oauth2` to allow users to sign in and sign up to your Strapi admin panel via their Microsoft accounts. + + + + The present page explains how to setup the Microsoft provider for the [Single Sign-On (SSO) feature](/cms/features/sso). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/sso-providers/okta.md b/docusaurus/docs/cms/configurations/sso-providers/okta.md index e5017c6301..474a3570d2 100644 --- a/docusaurus/docs/cms/configurations/sso-providers/okta.md +++ b/docusaurus/docs/cms/configurations/sso-providers/okta.md @@ -10,6 +10,13 @@ tags: # Okta provider SSO configuration + + +Okta is an SSO provider that allows users to sign in and sign up to Strapi through their Okta account using OAuth2 credentials configured in the `auth.providers` array. + + + + The present page explains how to setup the Okta provider for the [Single Sign-On (SSO) feature](/cms/features/sso). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers.md index 9fecbbb7af..fe102bd425 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers.md @@ -11,6 +11,13 @@ tags: # Users & Permissions providers + + +Configure OAuth and OAuth2 providers for Strapi's Users & Permissions authentication feature, with setup guides for common providers like GitHub, Google, and Auth0, plus instructions for creating custom providers. + + + + Strapi comes with a predefined set of built-in providers for the [Users & Permissions feature](/cms/features/users-permissions). The present page explains how the login flow works, how to set up the server URL, and list many examples for common 3rd-party providers. If you're looking to create your own custom provider, please refer to the [dedicated guide](/cms/configurations/users-and-permissions-providers/new-provider-guide). diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md index 11e0b362e5..d410181699 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/auth-zero.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Auth0 provider setup for Users & Permissions + + +Auth0 provider setup enables OAuth 2.0 authentication for the Users & Permissions feature, requiring configuration in both Auth0 tenant and Strapi admin settings using Client ID, Client Secret, and subdomain credentials. + + + + The present page explains how to setup the Auth0 provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/aws-cognito.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/aws-cognito.md index d7e288fa68..05ab09275a 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/aws-cognito.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/aws-cognito.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # AWS Cognito provider setup for Users & Permissions + + +AWS Cognito provider lets you set up OAuth 2.0 authentication for Users & Permissions by configuring a user pool in AWS and adding the client credentials and domain to Strapi's provider settings. + + + + The present page explains how to setup the AWS Cognito provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md index e46768c30f..42a772b077 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/cas.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # CAS provider setup for Users & Permissions + + +CAS is an SSO server that Strapi can use for authentication when deployed with OIDC support. Configure a CAS service definition and provide the client ID, secret, and provider subdomain in Strapi's Users & Permissions settings. + + + + The present page explains how to set up the CAS provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/discord.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/discord.md index 573f7ecd39..397cbcd611 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/discord.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/discord.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Discord provider setup for Users & Permissions + + +Discord provider setup allows you to authenticate users via Discord OAuth2 by configuring your Discord app credentials in Strapi's Users & Permissions provider settings. + + + + The present page explains how to setup the Discord provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/facebook.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/facebook.md index 42490bc711..1b4ce6c644 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/facebook.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/facebook.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Facebook provider setup for Users & Permissions + + +Facebook provider setup enables social login authentication in Strapi's Users & Permissions feature. Configure a Facebook app with OAuth credentials and update Strapi settings to enable the provider with your Client ID, Client Secret, and frontend redirect URL. + + + + The present page explains how to setup the Facebook provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/github.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/github.md index 275635f677..fd8c329a8d 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/github.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/github.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # GitHub provider setup for Users & Permissions + + +GitHub provider setup enables OAuth authentication for Strapi's Users & Permissions feature, requiring GitHub OAuth app configuration and Strapi provider settings. + + + + The present page explains how to setup the GitHub provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/google.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/google.md index 8020cb8a76..66af63b0e6 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/google.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/google.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Google provider setup for Users & Permissions + + +Configure Google OAuth authentication for Strapi Users & Permissions by creating credentials in Google Developer Console and adding them to the provider settings. + + + + The present page explains how to setup the Google provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md index 7307e8d5a8..618384ff2b 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/instagram.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Instagram provider setup for Users & Permissions + + +The Instagram Basic Display API is deprecated as of December 4, 2024. Strapi's built-in Instagram provider no longer works and requires updating to Meta's Instagram Business Login API instead. + + + + The present page explains how to setup the Instagram provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/keycloak.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/keycloak.md index a6abb68737..5e9ddfb4c1 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/keycloak.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/keycloak.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Keycloak provider setup for Users & Permissions + + +Set up Keycloak as an identity provider for Strapi's Users & Permissions feature by configuring a client in Keycloak, then enabling and filling in the Keycloak provider details in Strapi's admin settings. + + + + The present page explains how to setup the Keycloak provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md index 8eb7d32baf..68acfb0892 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/linkedin.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # LinkedIn provider setup for Users & Permissions + + +Configure LinkedIn as a provider for Strapi's Users & Permissions feature by creating a LinkedIn app, registering the redirect URL, and entering your credentials in the Strapi admin panel. + + + + The present page explains how to setup the LinkedIn provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/new-provider-guide.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/new-provider-guide.md index 70ddbe52e0..f84ec34697 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/new-provider-guide.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/new-provider-guide.md @@ -11,6 +11,13 @@ tags: # Creating and adding a custom Users & Permissions provider + + +Create custom OAuth providers for Strapi's Users & Permissions feature by registering them in `src/index.js` and implementing an `authCallback` that returns user `email` and `username` for automatic registration or login. + + + + Strapi provides a list of [built-in providers](/cms/configurations/users-and-permissions-providers#setting-up-the-provider---examples) for the [Users & Permissions feature](/cms/features/users-permissions). You can also create your own provider following this guide. :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/patreon.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/patreon.md index 8f1964a5e0..2f92146d25 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/patreon.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/patreon.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Patreon provider setup for Users & Permissions + + +Set up Patreon as an OAuth provider for Users & Permissions by registering an OAuth client on Patreon and configuring it in Strapi with your Client ID and Client Secret. + + + + The present page explains how to setup the Patreon provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/reddit.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/reddit.md index 91ea9faed2..c384707253 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/reddit.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/reddit.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Reddit provider setup for Users & Permissions + + +Configure the Reddit provider for Users & Permissions by creating a Reddit app and inputting the Client ID and Secret in Strapi's provider settings. + + + + The present page explains how to setup the Reddit provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitch.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitch.md index 47d139560f..ae39689c99 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitch.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitch.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Twitch provider setup for Users & Permissions + + +Configure Twitch OAuth authentication for Strapi's Users & Permissions feature by registering your application on the Twitch developer console and adding your credentials to Strapi's provider settings. + + + + The present page explains how to setup the Twitch provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md index 09092e76ba..e0c5564772 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/twitter.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # Twitter provider setup for Users & Permissions + + +Configure Twitter (now X) as an OAuth provider for Users & Permissions. Requires a paid X Developer Portal plan since the v1.1 API endpoint is no longer freely available. + + + + The present page explains how to setup the Twitter provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/configurations/users-and-permissions-providers/vk.md b/docusaurus/docs/cms/configurations/users-and-permissions-providers/vk.md index 1527d3bd96..4b5d54d0ce 100644 --- a/docusaurus/docs/cms/configurations/users-and-permissions-providers/vk.md +++ b/docusaurus/docs/cms/configurations/users-and-permissions-providers/vk.md @@ -13,6 +13,13 @@ import ConfigDone from '/docs/snippets/u-and-p-provider-config-done.md' # VK provider setup for Users & Permissions + + +VK provider setup for Users & Permissions enables authentication via VK. Configure a VK app, then set the client ID, secret, and redirect URL in Strapi's provider settings to enable VK login. + + + + The present page explains how to setup the VK provider for the [Users & Permissions feature](/cms/features/users-permissions). :::prerequisites diff --git a/docusaurus/docs/cms/customization.md b/docusaurus/docs/cms/customization.md index a81920ff58..da828aec6a 100644 --- a/docusaurus/docs/cms/customization.md +++ b/docusaurus/docs/cms/customization.md @@ -16,6 +16,13 @@ tags: # Customization + + +Strapi contains a backend server and admin panel, both of which can be customized to extend functionality like routes, policies, middlewares, themes, and more. + + + + Strapi includes 2 main components: - The back-end part of Strapi is a **server** that receives requests and handles them to return responses that can surface the data you built and saved through the Content-Type Builder and Content Manager. The backend server is described in more details in the [Backend Customization introduction](/cms/backend-customization). Most of the parts of the backend server can be customized. diff --git a/docusaurus/docs/cms/data-management/export.md b/docusaurus/docs/cms/data-management/export.md index d819c4a918..7a4211edc5 100644 --- a/docusaurus/docs/cms/data-management/export.md +++ b/docusaurus/docs/cms/data-management/export.md @@ -19,6 +19,13 @@ tags: # Data export + + +The `strapi export` command exports data from a Strapi instance as an encrypted and compressed archive containing entities, relations, assets, schemas, and configuration. Customize exports using options like `--no-encrypt`, `--no-compress`, `--only`, and `--exclude`. + + + + The `strapi export` command is part of the [Data Management feature](/cms/features/data-management) and used to export data from a local Strapi instance. By default, the `strapi export` command exports data as an encrypted and compressed `tar.gz.enc` file which includes: diff --git a/docusaurus/docs/cms/data-management/import.md b/docusaurus/docs/cms/data-management/import.md index b66c665ca3..0c916090f9 100644 --- a/docusaurus/docs/cms/data-management/import.md +++ b/docusaurus/docs/cms/data-management/import.md @@ -17,6 +17,13 @@ tags: # Data import + + +The `strapi import` command restores project data from an encrypted or compressed archive, including content, configuration, files, and schemas. It supports importing from `.tar.gz.enc` files or unpacked directories, with options to exclude or include specific data types. + + + + The `strapi import` command is part of the [Data Management feature](/cms/features/data-management) and used to import data from a file or directory. By default, the `strapi import` command imports data from an encrypted and compressed `tar.gz.enc` file which includes: diff --git a/docusaurus/docs/cms/data-management/transfer.md b/docusaurus/docs/cms/data-management/transfer.md index afd0172111..9f6c570c4e 100644 --- a/docusaurus/docs/cms/data-management/transfer.md +++ b/docusaurus/docs/cms/data-management/transfer.md @@ -13,6 +13,13 @@ tags: # Data transfer + + +The `strapi transfer` command streams data between two Strapi instances with identical schemas, transferring content, files, and configuration using transfer tokens for authorization and authentication. + + + + The `strapi transfer` command is part of the [Data Management feature](/cms/features/data-management) and streams your data from one Strapi instance to another Strapi instance. The `transfer` command uses strict schema matching, meaning your two Strapi instances need to be exact copies of each other except for the contained data. The default `transfer` command transfers your content (entities and relations), files (assets), project configuration, and schemas. The command allows you to transfer data: - from a local Strapi instance to a remote Strapi instance diff --git a/docusaurus/docs/cms/faq.md b/docusaurus/docs/cms/faq.md index 71f3d8b644..c5765b1f16 100644 --- a/docusaurus/docs/cms/faq.md +++ b/docusaurus/docs/cms/faq.md @@ -26,6 +26,13 @@ tags: # Frequently asked questions + + +Frequently asked questions covering common Strapi topics including content-type management, deployment, authentication, database handling, serverless limitations, plugins, Docker, SSL configuration, TypeScript support, and feature availability. + + + + Below are answers and solutions to most common issues that you may experience when working with Strapi. ## Why can't I create or update content-types in production/staging? diff --git a/docusaurus/docs/cms/features/preview.md b/docusaurus/docs/cms/features/preview.md index a414b39ac9..5fe023e653 100644 --- a/docusaurus/docs/cms/features/preview.md +++ b/docusaurus/docs/cms/features/preview.md @@ -33,9 +33,11 @@ With the Preview feature, you can preview your front end application directly fr }} /> - + +*/} ## Configuration diff --git a/docusaurus/docs/cms/features/strapi-mcp-server.md b/docusaurus/docs/cms/features/strapi-mcp-server.md index 3105154ad6..022282379d 100644 --- a/docusaurus/docs/cms/features/strapi-mcp-server.md +++ b/docusaurus/docs/cms/features/strapi-mcp-server.md @@ -11,7 +11,7 @@ toc_max_heading_level: 4 --- # MCP server - + diff --git a/docusaurus/docs/cms/getting-started/setting-up-admin-panel.md b/docusaurus/docs/cms/getting-started/setting-up-admin-panel.md index b6d3fb0e9a..859fe17f7c 100644 --- a/docusaurus/docs/cms/getting-started/setting-up-admin-panel.md +++ b/docusaurus/docs/cms/getting-started/setting-up-admin-panel.md @@ -8,6 +8,13 @@ tags: - password --- + + +The admin panel is where you manage content-types, content, and users. Access it via the app URL, optionally using SSO, then configure your administrator profile including name, email, language, and password. + + + + Before going over individual features, we recommend the following steps to set up and configure your Strapi admin panel correctly. Once you complete the setup, you can access the admin panel through the provided URL. diff --git a/docusaurus/docs/cms/installation.md b/docusaurus/docs/cms/installation.md index c1b6b0a5a5..b912b58036 100644 --- a/docusaurus/docs/cms/installation.md +++ b/docusaurus/docs/cms/installation.md @@ -10,6 +10,13 @@ tags: # Installation + + +Strapi projects can be installed locally via CLI or run in Docker containers for development and production. + + + + Strapi projects can be installed either locally on a computer or on a remote server. The following installation guide provides step-by-step instructions on how to install and create a new Strapi project on your local machine: diff --git a/docusaurus/docs/cms/installation/cli.md b/docusaurus/docs/cms/installation/cli.md index a7228bd191..6a81e0c983 100644 --- a/docusaurus/docs/cms/installation/cli.md +++ b/docusaurus/docs/cms/installation/cli.md @@ -17,6 +17,13 @@ import SupportedDatabases from '/docs/snippets/supported-databases.md' # Installing from CLI + + +The Strapi CLI is the fastest way to install Strapi locally using `npx create-strapi@latest`, with options to configure TypeScript, databases (`--dbclient`, `--dbhost`, etc.), and other setup preferences via command-line flags. + + + + Strapi CLI (Command Line Interface) installation scripts are the fastest way to get Strapi running locally. The following guide is the installation option most recommended by Strapi. ## Preparing the installation diff --git a/docusaurus/docs/cms/intro.md b/docusaurus/docs/cms/intro.md index df3ecead39..f5dbd7dedf 100644 --- a/docusaurus/docs/cms/intro.md +++ b/docusaurus/docs/cms/intro.md @@ -12,6 +12,13 @@ tags: # Welcome to the Strapi CMS Documentation! + + +Strapi 5 is an open-source headless CMS where developers can build custom applications and manage content through an extensible admin panel with built-in role-based access control. + + + + The Strapi CMS documentation focuses on Strapi 5 and will take you through the complete journey of your Strapi 5 project. From the technical information related to the setup, advanced usage, customization and update of your project, to the management of the admin panel and its content and users. + +The Document Service API replaces the Entity Service API in Strapi 5. The upgrade tool's codemod automatically converts function calls and `publicationState` to `status`, but manual intervention is required for `documentId` values and publication methods like `publish()` and `unpublish()`. + + + + In Strapi 5, the [Document Service API](/cms/api/document-service) replaces the Entity Service API from Strapi v4 (see [breaking change description](/cms/migration/v4-to-v5/breaking-changes/entity-service-deprecated)). The present page is intended to give developers an idea of how to migrate away from the Entity Service API, by describing which changes in custom code will be handled by codemods from the [upgrade tool](/cms/upgrade-tool) and which will have to be handled manually. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/helper-plugin.md b/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/helper-plugin.md index 51630771ee..d6ba21f15d 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/helper-plugin.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/helper-plugin.md @@ -10,6 +10,13 @@ tags: # `helper-plugin` migration reference + + +Reference guide listing every export from the deprecated `helper-plugin` package with migration paths to replacement components and utilities in `@strapi/strapi/admin`, `@strapi/design-system`, and other packages. + + + + This document has been written to help developers migrate their Strapi plugins and applications to _not_ use the `helper-plugin` package. It lists every export that existed in the `helper-plugin` package, in alphabetical order and grouped by domain. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/introduction.md b/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/introduction.md index c46abf6bd1..61e2d0e457 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/introduction.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/introduction.md @@ -9,6 +9,13 @@ tags: # Additional resources for upgrading to Strapi 5 + + +Additional resources provide dedicated guidance on specific Strapi 5 migration topics, including transitioning from the Entity Service API to Document Service API, upgrading plugins, and handling Design System v2 breaking changes. + + + + The following pages cover some dedicated topics for specific use cases when upgrading to Strapi 5. Please ensure you have read the [introduction to upgrading to Strapi 5](/cms/migration/v4-to-v5/introduction-and-faq) and [step-by-step guide](/cms/migration/v4-to-v5/step-by-step) before moving forward. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/plugins-migration.md b/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/plugins-migration.md index 2d8ca7d951..d543e1cfa0 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/plugins-migration.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/additional-resources/plugins-migration.md @@ -9,6 +9,13 @@ tags: # Plugins upgrade summary + + +Plugin developers upgrading from Strapi v4 to Strapi 5 must migrate to the Plugin SDK, transition from the Entity Service API to the Document Service API, update front-end code to use Design System v2 and remove `helper-plugin` dependencies. + + + + The present page is intended to be used as a short summary of everything to consider if you are a plugin developer upgrading your plugin from Strapi v4 to Strapi 5. The page quickly describes the changes affecting plugins and links to additional resources where necessary. :::strapi Plugin SDK diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes.md index 181b483007..bf9dd6a0b6 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes.md @@ -11,6 +11,13 @@ tags: # Strapi v4 to Strapi 5 breaking changes + + +A comprehensive index of breaking changes between Strapi v4 and v5, organized by category (database, dependencies, configuration, APIs) with information on plugin impact and codemod support. + + + + The present page lists all the breaking changes introduced in Strapi 5. Breaking changes are grouped into topic-related categories, and for each line in the following tables line you will find: diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/admin-panel-rbac-store-updated.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/admin-panel-rbac-store-updated.md index f677ae7f4c..c2d902d8bb 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/admin-panel-rbac-store-updated.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/admin-panel-rbac-store-updated.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The admin panel RBAC system has been updated + + +Strapi 5 removes the `content-manager_rbacManager` redux store section and uses the regular permissions system with an updated `useRBAC` hook instead. + + + + In Strapi 5, the `content-manager_rbacManager`, which is a section of Strapi's redux store for the admin panel, is removed and the regular permissions system is used instead. Additionally, the `useRBAC` hook is updated. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/attributes-and-content-types-names-reserved.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/attributes-and-content-types-names-reserved.md index 998e848631..3e714b15be 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/attributes-and-content-types-names-reserved.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/attributes-and-content-types-names-reserved.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Some attributes and content types names are reserved + + +In Strapi 5, certain attribute names like `meta`, `status`, `entryId`, and anything prefixed with `strapi` are now reserved and cannot be used. Fields and content types using these names in v4 must be renamed before migrating to Strapi 5. + + + + In Strapi 5, some attributes and content types names are reserved, and all fields or content types in Strapi v4 using these reserved names should be renamed before migrating to Strapi 5 to prevent data loss. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/components-and-dynamic-zones-do-not-return-id.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/components-and-dynamic-zones-do-not-return-id.md index 610582e24f..f0cad186d5 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/components-and-dynamic-zones-do-not-return-id.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/components-and-dynamic-zones-do-not-return-id.md @@ -17,6 +17,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Components and dynamic zones do not return an `id` + + +In Strapi 5, components and dynamic zones no longer return an `id` in REST API responses, preventing partial updates and requiring full component objects to be sent instead. + + + + In Strapi 5, components and dynamic zones do not return an `id` with REST API requests so it's not possible to partially update them. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/core-service-methods-use-document-service.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/core-service-methods-use-document-service.md index 2c8f436ec9..1e0c145992 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/core-service-methods-use-document-service.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/core-service-methods-use-document-service.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Core service methods use the Document Service API + + +In Strapi 5, core service methods use the Document Service API instead of the Entity Service API, with methods like `findOne`, `update`, and `delete` receiving a `documentId` instead of `entityId`. + + + + In Strapi 5, core service methods use the Document Service API instead of the Entity Service API. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-columns.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-columns.md index 50ed5df16b..0a07b0d4cb 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-columns.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-columns.md @@ -13,6 +13,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Content types always have feature columns + + +In Strapi 5, all content types automatically include `document_id`, `published_at`, and `locale` database columns for document management, publication, and internationalization. + + + + In Strapi 5, Content types always have document, publication and internationalization columns created in database. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-identifiers-shortened.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-identifiers-shortened.md index b901c5a108..c571ffe210 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-identifiers-shortened.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/database-identifiers-shortened.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Database identifiers shortened in v5 + + +Database identifiers are limited to 55 characters in Strapi v5; longer identifiers are automatically shortened with a hash suffix to prevent conflicts. + + + + In Strapi 5, database identifiers can't be longer than 55 characters. + +In Strapi 5, the `defaultIndex` option is removed from the `public` middleware, and the root `/` URL automatically redirects to the admin panel login or homepage if connected. + + + + In Strapi 5, the 'defaultIndex' option does not exist anymore and the root `/` URL automatically redirects to the admin panel login or homepage if already connected. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/default-input-validation.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/default-input-validation.md index a2ea5df58b..6e39351871 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/default-input-validation.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/default-input-validation.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # REST API input is validated by default in controllers + + +In Strapi 5, REST API input is validated by default in controllers instead of being silently sanitized, throwing `400 Bad Request` errors for invalid data like unrecognized fields and unpermitted relations. + + + + Sanitization means that the object is “cleaned” and returned. Validation means an assertion is made that the data is already clean and throws an error if something is found that shouldn't be there. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/design-system.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/design-system.md index e75ee0fe4c..541388c375 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/design-system.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/design-system.md @@ -13,6 +13,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The Strapi Design System has been upgraded to v2 + + +The Strapi Design System has been upgraded to v2 in Strapi 5 with changes to import structure, component APIs, and styling, including root imports, Radix-UI migrations, a new Field API, and a new base font-size of 62.5%. + + + + The has been completely updated in Strapi 5 with significant changes to component structure, APIs, and usage patterns. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/do-not-update-repeatable-components-with-document-service-api.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/do-not-update-repeatable-components-with-document-service-api.md index 65490326ed..0fb7e44112 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/do-not-update-repeatable-components-with-document-service-api.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/do-not-update-repeatable-components-with-document-service-api.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Updating repeatable components with the Document Service API is not recommended + + +In Strapi 5, updating repeatable components with the Document Service API is not recommended because draft and published components have different IDs, preventing successful updates using `documentId`. + + + + In Strapi 5, it's not recommended to update repeatable components with the API, due to some limitations of the new Document Service API. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/edit-view-layout-and-list-view-layout-rewritten.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/edit-view-layout-and-list-view-layout-rewritten.md index a31d12f58c..4fbde7ff6f 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/edit-view-layout-and-list-view-layout-rewritten.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/edit-view-layout-and-list-view-layout-rewritten.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The `EditViewLayout` and `ListViewLayout` have been rewritten + + +In Strapi 5, the `content-manager_editViewLayoutManager` and `content-manager_listViewLayoutManager` Redux hooks have been removed and replaced with a new `useDocumentLayout` hook for admin panel customization. + + + + In Strapi 5, some admin panel hooks have been removed from the Redux store and a new `useDocumentLayout` hook is introduced. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/entity-service-deprecated.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/entity-service-deprecated.md index 7cbba2e4b5..4def21777b 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/entity-service-deprecated.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/entity-service-deprecated.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Entity Service deprecated + + +The Entity Service API is deprecated in Strapi 5 and replaced by the Document Service API, which uses `documentId`, returns arrays for all queries, and introduces new methods for draft and publish workflows. + + + + The Entity Service that was used in Strapi v4 is deprecated and replaced by the new [Document Service API](/cms/api/document-service) in Strapi 5. + +In Strapi 5, `strapi.fetch` wraps the native `fetch()` API instead of node-fetch, requiring the `timeout` parameter to be replaced with `signal: AbortSignal.timeout()`. + + + + In Strapi 5, the `strapi.fetch` object is now wrapping node Fetch API instead of node-fetch. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/get-where-removed.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/get-where-removed.md index 1584e04604..8fd7e2aa9e 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/get-where-removed.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/get-where-removed.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The `getWhere()` method for permission provider instances has been removed + + +The `getWhere()` method for permission provider instances has been removed in Strapi 5; use `provider.values().filter()` with a custom predicate instead to query and match provider items. + + + + In Strapi 5, the `getWhere()` method for permission provider instances has been removed, and users should first get the provider values, then filter them. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated.md index f4a8d68f60..95a690b428 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/graphql-api-updated.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The GraphQL API has been updated + + +The Strapi 5 GraphQL API supports a new flattened response format and Relay-style `*_connection` queries for pagination. Migrate gradually using `v4CompatibilityMode`, adopt `documentId`, rename fields to `*_connection`, and eventually drop the `attributes` wrapper. + + + + In Strapi 5, the GraphQL API has been updated. It handles the new, flattened response format (see [related breaking change](/cms/migration/v4-to-v5/breaking-changes/new-response-format.md)), and can also now accept queries. Flat queries still return a simple array of documents. You can also use Relay-style `*_connection` queries, which return `nodes` and a `pageInfo` object to handle pagination. Use these when you need metadata about pages or total counts. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/helper-plugin-deprecated.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/helper-plugin-deprecated.md index 1d406931c2..5a30f09ad8 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/helper-plugin-deprecated.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/helper-plugin-deprecated.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `helper-plugin` deprecated + + +In Strapi 5, the `helper-plugin` is removed and replaced with imports from `@strapi/strapi/admin` and `@strapi/design-system`. Codemods automatically handle most migration changes for plugin developers. + + + + In Strapi 5, the `helper-plugin` is removed. A whole migration reference is available for plugin developers, and codemods will automatically handle some changes. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/i18n-content-manager-locale.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/i18n-content-manager-locale.md index aed06c733d..0595a06c08 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/i18n-content-manager-locale.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/i18n-content-manager-locale.md @@ -9,6 +9,13 @@ tags: - upgrade to Strapi 5 --- + + +Internationalization (i18n) is now part of Strapi core instead of a plugin. The locale parameter sent to Content Manager changes from `plugins[i18n][locale]` in v4 to `locale` in v5. + + + + import Intro from '/docs/snippets/breaking-change-page-intro.md' import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro.md' diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/inject-content-manager-component.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/inject-content-manager-component.md index 28089f6cc7..e5cb490cbb 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/inject-content-manager-component.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/inject-content-manager-component.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `injectContentManagerComponent()` removed + + +The `injectContentManagerComponent()` method is removed in Strapi 5 and replaced with `getPlugin('content-manager').injectComponent()` since the Content Manager is now a plugin. + + + + In Strapi 5, the `injectContentManagerComponent` method is removed because the Content Manager is now a plugin. The [Admin Panel API](/cms/plugins-development/admin-injection-zones) method is replaced by `getPlugin('content-manager').injectComponent()`. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/is-supported-image-removed.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/is-supported-image-removed.md index 6c681232e6..f049259e59 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/is-supported-image-removed.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/is-supported-image-removed.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The `isSupportedImage` method is removed + + +The `isSupportedImage` method is removed in Strapi 5. Developers must use `isImage` or `isOptimizableImage` instead. + + + + The `isSupportedImage` method has been issuing a deprecation warning ever since v4, and is finally being removed in Strapi 5. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/koa-body-v6.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/koa-body-v6.md index 925fa4fcdf..d62a690312 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/koa-body-v6.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/koa-body-v6.md @@ -16,6 +16,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Strapi 5 uses `koa-body` v6 + + +Strapi 5 upgrades to `koa-body` v6 with `formidable` v2, changing uploaded file properties from `path`, `name`, `type` to `filepath`, `originalFilename`, `mimetype` in custom endpoints. + + + + Strapi 5 uses v6, which updates `formidable` to v2. This means uploaded files have new properties. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/license-only.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/license-only.md index 9a22ed53fc..ad2da1be8c 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/license-only.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/license-only.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `lockIcon` property replaced by `licenseOnly` + + +In Strapi 5, the `lockIcon` property is replaced by `licenseOnly` in the Admin Panel API methods `addMenuLink()`, `addSettingsLink()`, and `addSettingsLinks()`, displaying a lightning icon to indicate paid features. + + + + Strapi 5 adds a new `licenseOnly` boolean property to pass in the `addMenuLink`, in the `addSettingsLink` and in the `addSettingsLinks` actions. Adding this property shows a lightning ⚡️ icon near the link, and indicates paid features. A similar result can be achieved in Strapi v4 by adding the `lockIcon` property. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service.md index 966721859b..c5d42b9a22 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Database lifecycle hooks are triggered differently with the Document Service API methods + + +In Strapi 5, database lifecycle hooks are triggered differently when using Document Service API methods, varying by operation type and status changes due to the new Draft & Publish system. + + + + In Strapi 5, database lifecycle hooks are triggered differently with the various [Document Service API](/cms/api/document-service) methods, mainly due to the new way the [Draft & Publish](/cms/features/draft-and-publish) feature works. The majority of use cases should only use the Document Service. The Document Service API handles Draft & Publish, i18n, and any underlying strapi logic. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mailgun-provider-variables.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mailgun-provider-variables.md index 24fff1234d..40e61d74d3 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mailgun-provider-variables.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mailgun-provider-variables.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Some Mailgun provider legacy variables are not supported + + +In Strapi 5, legacy Mailgun provider variables `apiKey` and `host` are no longer supported; use `key` and `url` instead. + + + + In Strapi 5, the support is dropped for some legacy variables deprecated in Strapi v4 for the Mailgun provider. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/model-config-path-uses-uid.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/model-config-path-uses-uid.md index c2c19fbba6..d9138695fb 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/model-config-path-uses-uid.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/model-config-path-uses-uid.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Model config path uses uid instead of dot notation + + +In Strapi 5, configuration paths use `::` notation instead of dot notation to access models, changing `plugin.upload.somesetting` to `plugin::upload.somesetting`. + + + + In Strapi 5, to retrieve config values you will need to use `config.get('plugin::upload.myconfigval')` or `config.get('api::myapi.myconfigval')` diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mysql5-unsupported.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mysql5-unsupported.md index 6f519cdf17..51a9cf877a 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mysql5-unsupported.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/mysql5-unsupported.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # MySQL v5 is not supported in Strapi v5 anymore + + +MySQL v5 is no longer supported in Strapi v5; MySQL v8 is now the minimum required version. Upgrade your MySQL database to v8.0 to use Strapi v5. + + + + In Strapi 5, MySQL version 5 is not supported. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/new-response-format.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/new-response-format.md index 7b58f8a6a5..60ec06cacf 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/new-response-format.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/new-response-format.md @@ -16,6 +16,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Strapi 5 has a new, flattened response format for REST API calls + + +Strapi 5 flattens REST API responses by removing the `attributes` wrapper and using `documentId` instead of `id`. Use the `Strapi-Response-Format: v4` header during migration for backward compatibility. + + + + In Strapi 5, the REST API response format has been simplified and flattened. You can set the `Strapi-Response-Format: v4` header to use the old v4 format while you convert your code to fully take into account the new Strapi 5 response format. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-find-page-in-document-service.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-find-page-in-document-service.md index 66888edd57..959cfe4b7c 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-find-page-in-document-service.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-find-page-in-document-service.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # No `findPage()` in Document Service API + + +Strapi 5 replaces the Entity Service API with the Document Service API, which does not include `findPage()`. Use the Document Service API's `findMany()` method instead. + + + + In Strapi 5, the [Document Service API](/cms/api/document-service) replaces the Entity Service API. There is no `findPage()` method available in the Document Service API and users should use the `findMany()` method instead. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-locale-all.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-locale-all.md index 12184b33a0..89e611e9af 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-locale-all.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-locale-all.md @@ -17,6 +17,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `locale=all` can not be used to get all entries in all locales + + +In Strapi 5, the `locale=all` parameter no longer retrieves all localized versions; instead, specific locale values must be requested individually. + + + + In Strapi 5, it's no longer possible to get all localized versions of a content type with the `locale=all` parameter. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-shared-population-strategy-components-dynamic-zones.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-shared-population-strategy-components-dynamic-zones.md index 77068d842a..6ae8dac42c 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-shared-population-strategy-components-dynamic-zones.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-shared-population-strategy-components-dynamic-zones.md @@ -16,6 +16,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Components and dynamic zones should be populated using the detailed population strategy (`on` fragments) + + +In Strapi 5, components and dynamic zones must be explicitly populated using `on` fragments instead of the shared population strategy supported in v4. + + + + In Strapi 5, components and dynamic zones should be populated using the detailed population strategy, with `on` fragments. The shared population strategy possible in Strapi v4 is no longer supported. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-upload-at-entry-creation.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-upload-at-entry-creation.md index 84fed29474..f1d13fc102 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-upload-at-entry-creation.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/no-upload-at-entry-creation.md @@ -13,6 +13,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Upload a file at entry creation is no longer supported + + +In Strapi 5, uploading a file while creating an entry is no longer supported. Users must upload the file first via the Upload API, then create the entry with the file id. + + + + In Strapi 5, it is not possible to upload a file while creating an entry, so this should be done in 2 steps. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-better-sqlite3-for-sqlite.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-better-sqlite3-for-sqlite.md index e72849c8ad..b172792dbd 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-better-sqlite3-for-sqlite.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-better-sqlite3-for-sqlite.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Only the `better-sqlite3` package is supported for the SQLite client + + +In Strapi 5, SQLite databases must use the `better-sqlite3` package with the database client configuration set to `sqlite` instead of other options like `sqlite3` or `sqlite-legacy`. + + + + Strapi 5 can only use the `better-sqlite3` package for SQLite databases, and the `client` value for it must be set to `sqlite`. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-mysql2-package-for-mysql.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-mysql2-package-for-mysql.md index 9bec51d5a2..2da1439d3a 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-mysql2-package-for-mysql.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/only-mysql2-package-for-mysql.md @@ -16,6 +16,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Only the `mysql2` package is supported for the MySQL client + + +Strapi 5 only supports the `mysql2` package for MySQL databases and requires the `client` configuration option to be set to `mysql`. + + + + Strapi 5 can only use the `mysql2` package for MySQL databases, and the `client` value for it must be set to `mysql`. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publication-state-removed.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publication-state-removed.md index 2897a46271..f0525b7507 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publication-state-removed.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publication-state-removed.md @@ -17,6 +17,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `publicationState` is removed and replaced by `status` + + +In Strapi 5, the `publicationState` parameter is replaced with `status`, which accepts `draft` and `published` values instead of `live` and `preview`. + + + + In Strapi 5, the [Draft & Publish feature](/cms/features/draft-and-publish) has been reworked, and the Content API, including REST, GraphQL, and Document Service APIs accept a new `status` parameter. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publishedat-always-set-when-dandp-disabled.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publishedat-always-set-when-dandp-disabled.md index 40fc2f14ca..bd08d14586 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publishedat-always-set-when-dandp-disabled.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/publishedat-always-set-when-dandp-disabled.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Content types with Draft & Publish disabled always have the publishedAt value set to a date + + +In Strapi 5, content-types with Draft & Publish disabled always have the `publishedAt` attribute set to a date, whereas in v4 the attribute did not exist. + + + + In Strapi 5, content-types with Draft & Publish disabled always have the publishedAt value set to a date. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/react-router-dom-6.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/react-router-dom-6.md index 08ae849da8..bc95228998 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/react-router-dom-6.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/react-router-dom-6.md @@ -13,7 +13,14 @@ tags: import Intro from '/docs/snippets/breaking-change-page-intro.md' import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro.md' -# Strapi users `react-router-dom` v6 +# Strapi uses `react-router-dom` v6 + + + +Strapi 5 upgrades to `react-router-dom` v6, requiring settings and menu links added via the Admin Panel API to use relative paths instead of absolute paths. + + + Strapi 5 uses v6. This impacts the links added to [settings](/cms/plugins-development/admin-navigation-settings#settings) or to the [menu](/cms/plugins-development/admin-navigation-settings#navigation-sidebar-menu-links) using the Admin Panel API. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/redux-content-manager-app-state.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/redux-content-manager-app-state.md index 88622b9559..9c6e211f3c 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/redux-content-manager-app-state.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/redux-content-manager-app-state.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The ContentManagerAppState redux is modified + + +In Strapi 5, the ContentManagerAppState redux store removed RESET_INIT_DATA and GET_INIT_DATA actions, and changed SET_INIT_DATA payload structure to no longer nest attributes within a data object. + + + + In Strapi 5, the redux store for the Content Manager has been changed and some redux actions were removed. Notably, the `useContentManagerInitData` redux state for the Content Manager has been refactored to remove `ModelsContext`. Users might be relying on the original structure in a middleware or subscriber; doing so this will break their application. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md index 2174906431..b18e15fdec 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/register-allowed-fields.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The Users & Permissions plugin's `register.allowedFields` configuration option defaults to `[]` + + +In Strapi 5, the Users & Permissions plugin's `register.allowedFields` defaults to an empty array, requiring explicit field allowlisting instead of accepting all fields by default. + + + + In Strapi 5, the Users & Permissions plugin's `register.allowedFields` configuration option defaults to `[]`. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/remove-webhook-populate-relations.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/remove-webhook-populate-relations.md index 0d232e131d..344134cb4f 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/remove-webhook-populate-relations.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/remove-webhook-populate-relations.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The `webhooks.populateRelations` server configuration is removed + + +In Strapi 5, the `webhooks.populateRelations` server configuration is removed. Webhook refactoring eliminates the need for this option, but code relying on populated relations in create, update, and delete responses must be updated to fetch necessary data manually. + + + + In Strapi 5, webhooks have been refactored and the `webhook.populateRelations` option will become redundant. This might affect lifecycles expecting the returned relations of create, update and delete to be populated. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options.md index 2638f21a29..a0dc1b4894 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/removed-support-for-some-env-options.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Some `env`-only configuration options are handled by the server configuration + + +In Strapi 5, three environment variables (`STRAPI_DISABLE_REMOTE_DATA_TRANSFER`, `STRAPI_HIDE_STARTUP_MESSAGE`, `STRAPI_DISABLE_UPDATE_NOTIFICATION`) are now configured via the server configuration file instead of environment variables. + + + + In Strapi 5, some configuration options that were only handled by environment variables in Strapi v4 are now handled in the [server configuration](/cms/configurations/server) file. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-default-log-level.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-default-log-level.md index ed6023b9b1..dd62be4cbd 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-default-log-level.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-default-log-level.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Server log level is `http` + + +In Strapi 5, the server log level defaults to `http` instead of `silly`, reducing verbose logging by hiding `silly` and `debug` level logs. Configure the log level in your server configuration file to adjust output verbosity. + + + + You can adjust the server log level in the configuration to control how much detail you see in your server logs. If you want to see more or less verbose logs in your server logs, this feature allows you to customize it according to your needs. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-proxy.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-proxy.md index 3e62584079..b3e5968a3a 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-proxy.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/server-proxy.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Server proxy configurations are grouped under the `server.proxy` object + + +In Strapi 5, all proxy configuration options are consolidated under the `server.proxy` object in `/config/server.js|ts`, replacing separate `server.globalProxy` and `server.proxy` options from v4. + + + + In Strapi 5, all proxy configuration options are now configured through the `server.proxy` object in `/config/server.js|ts`, whether they are for requests made within `strapi.fetch` or for the global proxy agent for the server. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/sort-by-id.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/sort-by-id.md index 9c5731e4eb..8c994bc242 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/sort-by-id.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/sort-by-id.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Sorting by `id` is no longer possible to sort by chronological order in Strapi 5 + + +Sorting by `id` no longer works chronologically in Strapi 5 due to uuid-based documents; use `createdAt` with the Document Service API instead. + + + + In Strapi 5, sorting by `id` to sort by chronological order is no longer possible since [documents](/cms/api/document) use an uuid. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-container.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-container.md index 562dc36b4a..5704bc760e 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-container.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-container.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `Strapi` is a subclass of `Container` + + +In Strapi 5, `Strapi` is a subclass of `Container`, allowing you to access container methods directly on the `strapi` object using `strapi.add()` and `strapi.get()` instead of `strapi.container.register()` and `strapi.container.get()`. + + + + In Strapi 5, `Strapi` is a subclass of the `Container` class to make it simpler to access services and unify the service access with one method. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-imports.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-imports.md index 516cf4af2a..1d837e8967 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-imports.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-imports.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Strapi factories import have been updated + + +In Strapi 5, the import syntax for the application init function and factories has been updated; use `createStrapi` from `@strapi/strapi` instead of the v4 patterns, and some legacy import patterns are no longer supported. + + + + In Strapi 5, strapi factories import have been updated. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-utils-refactored.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-utils-refactored.md index 0fcab8030b..03468f4f01 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-utils-refactored.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strapi-utils-refactored.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `strapi-utils` refactored + + +In Strapi 5, the `strapi-utils` package is refactored with utilities reorganized into `arrays`, `dates`, `strings`, `objects`, and `async` namespaces, and some utilities moved, replaced with service methods, or removed. + + + + In Strapi 5, the `strapi-utils` core package has been refactored. This page lists the additions, removals, and other updates. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strict-requirements-config-files.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strict-requirements-config-files.md index 2918a11b25..3103d0e9c9 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strict-requirements-config-files.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/strict-requirements-config-files.md @@ -13,6 +13,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Strict requirements for configuration files + + +Strapi 5 enforces strict naming requirements for configuration files in the `/config/` folder: no case-insensitive duplicates, no duplicate base filenames, and certain reserved names are blocked; custom configurations should use files with names compliant to these rules. + + + + Strapi 5 has strict requirements on the configuration filenames allowed to be loaded. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/templates.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/templates.md index f850b4c07a..e0937a1f42 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/templates.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/templates.md @@ -13,6 +13,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Templates are now standalone, regular Strapi applications + + +Templates are now standalone Strapi 5 applications instead of npm packages with strict requirements, making them easier to create, distribute, and reuse. + + + + Templates have been fully rewritten in Strapi 5 and now are standalone, regular Strapi applications, making it easier to create, distribute, and reuse them. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/upgrade-to-apollov4.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/upgrade-to-apollov4.md index aeceaddd50..abed6c83d9 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/upgrade-to-apollov4.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/upgrade-to-apollov4.md @@ -18,6 +18,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Apollo Server v3 upgraded to Apollo Server v4 + + +Strapi 5 upgrades Apollo Server from v3 to v4 and GraphQL from v15 to v16, requiring migration updates to error handling, CSRF prevention, and plugin configuration. + + + + Strapi 5 has migrated to Apollo Server v4 and this might require some manual migration steps. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/use-document-id.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/use-document-id.md index 8c933e01b5..976047fd21 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/use-document-id.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/use-document-id.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # `documentId` should be used instead of `id` in Content API calls + + +In Strapi 5, the `documentId` field replaces `id` for identifying documents in Content API calls (REST API and GraphQL) as part of the Document Service API transition. + + + + In Strapi 5, the underlying API handling content is the [Document Service API](/cms/api/document-service) and documents should be called by their `documentId` in Content API calls (REST API & GraphQL). @@ -46,7 +53,7 @@ Entries were identified by their `id`: "title": "Article A" "relation": { "data": { - "id": "clkgylw7d000108lc4rw1bb6s" + "id": 15 "name": "Category A" } } @@ -70,13 +77,13 @@ Documents are identified by their `documentId`: { "data": { // system fields - "documentId": "clkgylmcc000008lcdd868feh", + "documentId": "a1b2c3d4e5f6g7h8i9j0klmn", "locale": "en", // user fields "title": "Article A" "relation": { // system fields - "documentId": "clkgylw7d000108lc4rw1bb6s" + "documentId": "j9k8l7m6n5o4p3q2r1s0tuvw" // user fields "name": "Category A" } diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/vite.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/vite.md index 1fe717c7fc..f262abb9ee 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/vite.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/vite.md @@ -15,6 +15,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Vite is the default bundler in Strapi 5 + + +In Strapi 5, Vite replaces webpack as the default bundler. Users with custom webpack configurations can convert to Vite configurations or use `--bundler=webpack` to maintain v4 behavior. + + + + In Strapi 5, Vite is the default bundler. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/webpack-aliases-removed.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/webpack-aliases-removed.md index e79412d27e..6ba4761425 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/webpack-aliases-removed.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/webpack-aliases-removed.md @@ -16,6 +16,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # Webpack Aliases are removed + + +Strapi v5 removes most webpack aliases for better compatibility, keeping only essential dependencies like `react`, `react-dom`, `react-router-dom`, and `styled-components` aliased. + + + + In Strapi v5, webpack aliases are removed ensuring better compatibility and reduced dependency conflicts. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/yarn-not-default.md b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/yarn-not-default.md index 5294c5c6e2..22b462f100 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/yarn-not-default.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/breaking-changes/yarn-not-default.md @@ -14,6 +14,13 @@ import MigrationIntro from '/docs/snippets/breaking-change-page-migration-intro. # The CLI default package manager is not yarn anymore + + +In Strapi 5, the CLI detects your package manager and uses it to install dependencies instead of defaulting to `yarn`. Use the `--use-yarn` flag if you need to enforce yarn specifically. + + + + In Strapi v5, the command used to run dependencies installation is the one used to actually install them. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/introduction-and-faq.md b/docusaurus/docs/cms/migration/v4-to-v5/introduction-and-faq.md index 934556c2fd..4564b85898 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/introduction-and-faq.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/introduction-and-faq.md @@ -10,6 +10,13 @@ tags: # Upgrading to Strapi 5: Introduction and FAQ + + +Upgrading to Strapi 5 from v4 uses an upgrade tool with codemods to handle code changes, while built-in data migration scripts automatically update the database on first startup. + + + + The latest major version of Strapi is Strapi 5. Strapi v4 is still supported until April 2026. Whenever you feel ready to upgrade to Strapi 5, the present page will help you. It lists all available resources for upgrading from Strapi 4 to Strapi 5 and answers general questions you might have. diff --git a/docusaurus/docs/cms/migration/v4-to-v5/step-by-step.md b/docusaurus/docs/cms/migration/v4-to-v5/step-by-step.md index 2d7ec65c85..7ce28d1ba8 100644 --- a/docusaurus/docs/cms/migration/v4-to-v5/step-by-step.md +++ b/docusaurus/docs/cms/migration/v4-to-v5/step-by-step.md @@ -12,6 +12,13 @@ tags: # Step-by-step guide to upgrade to Strapi 5 + + +Follow step-by-step instructions to upgrade your Strapi v4 application to Strapi 5, including database and code backups, running the automated upgrade tool, handling manual code updates, and gradually migrating your REST and GraphQL API calls using compatibility headers. + + + + The latest major version of Strapi is Strapi 5. The present page is meant to be used as step-by-step instructions for upgrading your Strapi v4 application to Strapi 5. diff --git a/docusaurus/docs/cms/plugins-development/developing-plugins.md b/docusaurus/docs/cms/plugins-development/developing-plugins.md index 7aa46209b8..1bf3dcda8f 100644 --- a/docusaurus/docs/cms/plugins-development/developing-plugins.md +++ b/docusaurus/docs/cms/plugins-development/developing-plugins.md @@ -14,6 +14,13 @@ tags: # Developing Strapi plugins + + +Strapi plugins extend core functionality using Admin Panel API, Server API, or MCP server tools. Plugins can be local or published to the Marketplace, and are created using the Plugin SDK. + + + + Strapi allows the development of plugins that work exactly like the built-in plugins or 3rd-party plugins available from the . Once created, your plugin can be: - used as a local plugin, working only with a specific Strapi project, diff --git a/docusaurus/docs/cms/plugins-development/extend-mcp-server.md b/docusaurus/docs/cms/plugins-development/extend-mcp-server.md index 48e0b420cb..c6907b24c1 100644 --- a/docusaurus/docs/cms/plugins-development/extend-mcp-server.md +++ b/docusaurus/docs/cms/plugins-development/extend-mcp-server.md @@ -19,7 +19,7 @@ tags: Strapi plugins can register additional MCP tools through the `strapi.ai.mcp` service. Registrations must happen while the MCP server is idle (during the plugin's `register()` lifecycle phase), before the server starts. -Strapi includes a built-in [Model Context Protocol (MCP) server](/cms/features/strapi-mcp-server) that exposes content management tools to AI clients. In addition to the content-type tools generated from your schema, plugins can register their own custom tools so AI clients can trigger plugin-specific actions. +Strapi includes a built-in [Model Context Protocol (MCP) server](/cms/features/strapi-mcp-server) that exposes content management tools to AI clients. In addition to the tools generated from your schema, plugins can register their own MCP capabilities so AI clients can trigger plugin-specific actions. Plugins can register 3 capability types through the `strapi.ai.mcp` service: tools, resources, and prompts. Registrations must happen while the MCP server is idle, before it starts. In Strapi's load lifecycle, register a tool during the plugin's `register()` phase. @@ -35,31 +35,29 @@ const { z } = require('@strapi/utils'); module.exports = { register({ strapi }) { - if (strapi.ai.mcp.isEnabled()) { - strapi.ai.mcp.registerTool({ - name: 'my_custom_tool', - title: 'My Custom Tool', - description: 'A short description shown to the AI client.', - auth: { - // The session gate passes when the token satisfies ANY policy in the array. - policies: [{ action: 'plugin::my-plugin.my-action' }], - }, - // resolveInputSchema and resolveOutputSchema are called per request, - // so they can narrow schemas based on the token's permissions. - resolveInputSchema: (context) => - z.object({ - message: z.string().describe('The message to echo.'), - }), - resolveOutputSchema: (context) => - z.object({ - result: z.string(), - }), - createHandler: (strapi, context) => async ({ args }) => ({ - content: [{ type: 'text', text: args.message }], - structuredContent: { result: args.message }, + strapi.ai.mcp.registerTool({ + name: 'my_custom_tool', + title: 'My Custom Tool', + description: 'A short description shown to the AI client.', + auth: { + // The session gate passes when the token satisfies ANY policy in the array. + policies: [{ action: 'plugin::my-plugin.my-action' }], + }, + // resolveInputSchema and resolveOutputSchema are called per request, + // so they can narrow schemas based on the token's permissions. + resolveInputSchema: (context) => + z.object({ + message: z.string().describe('The message to echo.'), }), - }); - } + resolveOutputSchema: (context) => + z.object({ + result: z.string(), + }), + createHandler: (strapi, context) => async ({ args }) => ({ + content: [{ type: 'text', text: args.message }], + structuredContent: { result: args.message }, + }), + }); }, }; ``` @@ -72,31 +70,29 @@ import { z } from '@strapi/utils'; export default { register({ strapi }) { - if (strapi.ai.mcp.isEnabled()) { - strapi.ai.mcp.registerTool({ - name: 'my_custom_tool', - title: 'My Custom Tool', - description: 'A short description shown to the AI client.', - auth: { - // The session gate passes when the token satisfies ANY policy in the array. - policies: [{ action: 'plugin::my-plugin.my-action' }], - }, - // resolveInputSchema and resolveOutputSchema are called per request, - // so they can narrow schemas based on the token's permissions. - resolveInputSchema: (context) => - z.object({ - message: z.string().describe('The message to echo.'), - }), - resolveOutputSchema: (context) => - z.object({ - result: z.string(), - }), - createHandler: (strapi, context) => async ({ args }) => ({ - content: [{ type: 'text', text: args.message }], - structuredContent: { result: args.message }, + strapi.ai.mcp.registerTool({ + name: 'my_custom_tool', + title: 'My Custom Tool', + description: 'A short description shown to the AI client.', + auth: { + // The session gate passes when the token satisfies ANY policy in the array. + policies: [{ action: 'plugin::my-plugin.my-action' }], + }, + // resolveInputSchema and resolveOutputSchema are called per request, + // so they can narrow schemas based on the token's permissions. + resolveInputSchema: (context) => + z.object({ + message: z.string().describe('The message to echo.'), + }), + resolveOutputSchema: (context) => + z.object({ + result: z.string(), }), - }); - } + createHandler: (strapi, context) => async ({ args }) => ({ + content: [{ type: 'text', text: args.message }], + structuredContent: { result: args.message }, + }), + }); }, }; ``` @@ -111,7 +107,7 @@ export default { | `name` | String | Yes | Unique tool name. Must be unique across all registered MCP tools. | | `title` | String | Yes | Human-readable title shown to the AI client. | | `description` | String | Yes | Short description of what the tool does. | -| `auth` | Object | Yes (or `devModeOnly`) | Auth requirement. The session gate passes when the token satisfies **any** policy in the `policies` array. Each policy is `{ action, subject? }`. | +| `auth` | Object | Yes (or `devModeOnly`) | Auth requirement. The session gate passes when the token satisfies any policy in the `policies` array. Each policy is `{ action, subject? }`. | | `devModeOnly` | Boolean | Yes (or `auth`) | Set to `true` to restrict the tool to development mode only (equivalent to the built-in `log` tool). | | `resolveInputSchema` | Function | No | Returns a Zod schema for the tool's input arguments. Called per request so RBAC constraints can be applied dynamically. Omit for tools with no input. | | `resolveOutputSchema` | Function | Yes | Returns a Zod schema for the tool's structured output. Called per request. | @@ -121,3 +117,89 @@ export default { `resolveInputSchema` and `resolveOutputSchema` are called once per incoming MCP request, so you can narrow schemas dynamically based on the token's permissions (via `context.userAbility`). ::: +## Defining capabilities with builder helpers + +:::caution +Builder helpers are an optional convenience for TypeScript users. The standard, recommended way to register a capability is to pass its definition inline to [`registerTool()`](#registering-a-custom-tool), as shown in the [previous section](#registering-a-custom-tool). You never need a builder helper to register a tool, resource, or prompt: skip this section unless you specifically want the extra TypeScript inference it provides. +::: + +Passing the tool definition inline to [`registerTool()`](#registering-a-custom-tool) is the standard approach and works well for most cases. For larger plugins that keep capability definitions in their own modules, Strapi optionally exports a set of builder helpers that improve TypeScript inference when a definition is declared away from its `register` call. + +These helpers are exported under the `ai.mcp` namespace on `@strapi/strapi`: `ai.mcp.defineTool`, `ai.mcp.defineResource`, and `ai.mcp.definePrompt`. Each one returns its definition unchanged at runtime: it is a pure type-inference helper, not a different way to register a capability. They infer the capability's `name`, schemas, and handler types, and narrow the access variant (`devModeOnly` or `auth`) so the result is directly assignable to the matching `register` method. This is similar to the `factories` helpers used for content-manager APIs. + +Whether or not you use a builder, registration still happens the same way: pass the definition to `registerTool()` (or `registerResource()` / `registerPrompt()`) during the plugin's `register()` phase. Each definition takes either `devModeOnly: true` or an `auth` policy set, never both. + +### Defining a tool + +The following example uses `devModeOnly` for brevity. An `auth` policy set, like the one shown in the [tool definition options](#tool-definition-options) above, works the same way: + +```ts title="src/plugins/my-plugin/mcp/greet.ts" +import { ai } from '@strapi/strapi'; +import { z } from '@strapi/utils'; + +export const greet = ai.mcp.defineTool({ + name: 'greet', + title: 'Greet', + description: 'Greets a user by name', + devModeOnly: true, + resolveInputSchema: () => z.object({ name: z.string() }), + resolveOutputSchema: () => z.object({ message: z.string() }), + createHandler: (strapi) => async ({ args }) => { + const message = `Hello, ${args.name}!`; + return { content: [{ type: 'text', text: message }], structuredContent: { message } }; + }, +}); +``` + +Register the tool from the plugin's server entry file: + +```ts title="src/plugins/my-plugin/strapi-server.ts" +import { greet } from './mcp/greet'; + +export default { + register({ strapi }) { + strapi.ai.mcp.registerTool(greet); + }, +}; +``` + +### Defining a resource + +A resource exposes read-only data to AI clients through a URI. Define it with `ai.mcp.defineResource`, then register it with `strapi.ai.mcp.registerResource()`: + +```ts title="src/plugins/my-plugin/mcp/app-info.ts" +import { ai } from '@strapi/strapi'; + +export const appInfo = ai.mcp.defineResource({ + name: 'app-info', + uri: 'strapi://app/info', + metadata: { description: 'Metadata about the app', mimeType: 'application/json' }, + devModeOnly: true, + createHandler: (strapi) => async (uri) => ({ + contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify({ ok: true }) }], + }), +}); +``` + +### Defining a prompt + +A prompt exposes a reusable prompt template to AI clients. Define it with `ai.mcp.definePrompt`, then register it with `strapi.ai.mcp.registerPrompt()`: + +```ts title="src/plugins/my-plugin/mcp/app-context.ts" +import { ai } from '@strapi/strapi'; + +export const appContext = ai.mcp.definePrompt({ + name: 'app-context', + title: 'App Context', + description: 'Provides context about the app', + devModeOnly: true, + createHandler: (strapi) => async () => ({ + messages: [{ role: 'user', content: { type: 'text', text: 'You are connected to Strapi.' } }], + }), +}); +``` + +:::note +The builders are identity functions: they do not change the definition at runtime. Defining a capability does not register it. Pass the result to `strapi.ai.mcp.registerTool()`, `registerResource()`, or `registerPrompt()` during `register()`, while the MCP server is still idle. +::: + diff --git a/docusaurus/docs/cms/plugins-development/guides/admin-permissions-for-plugins.md b/docusaurus/docs/cms/plugins-development/guides/admin-permissions-for-plugins.md index d5ab0c4d2a..236e968cbf 100644 --- a/docusaurus/docs/cms/plugins-development/guides/admin-permissions-for-plugins.md +++ b/docusaurus/docs/cms/plugins-development/guides/admin-permissions-for-plugins.md @@ -14,6 +14,13 @@ tags: # How to create admin permissions from plugins + + +Plugins can register admin permissions server-side using `strapi.admin.services.permission.actionProvider.registerMany()`, then protect pages with ``, menu links, and components using the `useRBAC` hook to enforce role-based access control. + + + + When [developing a Strapi plugin](/cms/plugins-development/developing-plugins), you might want to create admin permissions for your plugin. By doing that you can hook in to the [RBAC system](/cms/features/rbac) of Strapi to selectively grant permissions to certain pieces of your plugin. To create admin permissions for your Strapi plugin, you'll need to register them on the server side before implementing them on the admin side. diff --git a/docusaurus/docs/cms/plugins-development/guides/create-components-for-plugins.md b/docusaurus/docs/cms/plugins-development/guides/create-components-for-plugins.md index ca4c2edbcb..4937459961 100644 --- a/docusaurus/docs/cms/plugins-development/guides/create-components-for-plugins.md +++ b/docusaurus/docs/cms/plugins-development/guides/create-components-for-plugins.md @@ -14,6 +14,13 @@ tags: # How to create components for Strapi plugins + + +Create reusable `component` data structures for Strapi plugins using the Content-Type Builder or manually by defining a schema file with attributes and metadata in your plugin's server directory. + + + + When [developing a Strapi plugin](/cms/plugins-development/developing-plugins), you might want to create reusable components for your plugin. Components in Strapi are reusable data structures that can be used across different content-types. To create components for your Strapi plugin, you'll need to follow a similar approach to creating content-types, but with some specific differences. diff --git a/docusaurus/docs/cms/plugins-development/guides/pass-data-from-server-to-admin.md b/docusaurus/docs/cms/plugins-development/guides/pass-data-from-server-to-admin.md index 776e62e957..b5b43c750b 100644 --- a/docusaurus/docs/cms/plugins-development/guides/pass-data-from-server-to-admin.md +++ b/docusaurus/docs/cms/plugins-development/guides/pass-data-from-server-to-admin.md @@ -12,11 +12,14 @@ tags: - plugins development guides --- -import NotV5 from '/docs/snippets/_not-updated-to-v5.md' - # How to pass data from server to admin panel with a Strapi plugin - + + +Pass data from a Strapi plugin's server to the admin panel by creating a custom admin route and using the `getFetchClient` API to request data from admin components. + + + Strapi is **headless** . The admin panel is completely separate from the server. diff --git a/docusaurus/docs/cms/plugins-development/guides/store-and-access-data.md b/docusaurus/docs/cms/plugins-development/guides/store-and-access-data.md index b205fd1594..a936c1f45f 100644 --- a/docusaurus/docs/cms/plugins-development/guides/store-and-access-data.md +++ b/docusaurus/docs/cms/plugins-development/guides/store-and-access-data.md @@ -13,6 +13,13 @@ tags: # How to store and access data from a Strapi plugin + + +Plugin content-types store and persist data like standard content-types. Use the CLI generator to create them, then interact with data via the Document Service API or Query Engine API. + + + + To store data with a Strapi [plugin](/cms/plugins-development/developing-plugins), use a plugin content-type. Plugin content-types work exactly like other [content-types](/cms/backend-customization/models). Once the content-type is [created](#create-a-content-type-for-your-plugin), you can start [interacting with the data](#interact-with-data-from-the-plugin). ## Create a content-type for your plugin diff --git a/docusaurus/docs/cms/plugins-development/plugin-sdk.md b/docusaurus/docs/cms/plugins-development/plugin-sdk.md index 533187d0e1..0846d43bf1 100644 --- a/docusaurus/docs/cms/plugins-development/plugin-sdk.md +++ b/docusaurus/docs/cms/plugins-development/plugin-sdk.md @@ -14,6 +14,13 @@ import UsingSDKplugin5 from '/docs/snippets/sdk-plugin-v5-v6.md' # Plugin SDK reference + + +The Plugin SDK is a set of commands from @strapi/sdk-plugin for creating, building, linking, and publishing Strapi plugins locally or to NPM and the Marketplace. + + + + The Plugin SDK is set of commands provided by the package orientated around developing plugins to use them as local plugins or to publish them on NPM and/or submit them to the Marketplace. The present documentation lists the available Plugin SDK commands. The [associated guide](/cms/plugins-development/create-a-plugin) illustrates how to use these commands to create a plugin from scratch, link it to an existing project, and publish it. diff --git a/docusaurus/docs/cms/plugins-development/plugin-structure.md b/docusaurus/docs/cms/plugins-development/plugin-structure.md index facf29c7ed..8b7042fd59 100644 --- a/docusaurus/docs/cms/plugins-development/plugin-structure.md +++ b/docusaurus/docs/cms/plugins-development/plugin-structure.md @@ -18,6 +18,13 @@ import InteractivePluginStructure from '@site/src/components/PluginStructure.js' # Plugin structure + + +A Strapi plugin is divided into an `admin/` folder for admin panel UI components and a `server/` folder for backend logic like content-types and controllers, each with its own API. + + + + When [creating a plugin with Plugin SDK](/cms/plugins-development/create-a-plugin), Strapi generates the following boilerplate structure for you in the `/src/plugins/my-plugin` folder: diff --git a/docusaurus/docs/cms/plugins-development/server-getters-usage.md b/docusaurus/docs/cms/plugins-development/server-getters-usage.md index 113909d217..39045a6a4f 100644 --- a/docusaurus/docs/cms/plugins-development/server-getters-usage.md +++ b/docusaurus/docs/cms/plugins-development/server-getters-usage.md @@ -55,10 +55,15 @@ The choice is a matter of context and readability: The following table lists all available getters for a plugin named `todo` with a resource named `task`: -| | Service | Controller | Content-type | Policy | Middleware | Routes | Configuration | -| --- | --- | --- | --- | --- | --- | --- | --- | -| **Top-level** | `strapi.plugin('todo').service('task')` | `strapi.plugin('todo').controller('task')` | `strapi.plugin('todo').contentType('task')` | `strapi.plugin('todo').policy('is-owner')` | `strapi.plugin('todo').middleware('audit-log')` | `strapi.plugin('todo').routes` | `strapi.plugin('todo').config('featureFlag')` | -| **Global** | `strapi.service('plugin::todo.task')` | `strapi.controller('plugin::todo.task')` | `strapi.contentType('plugin::todo.task')` | `strapi.policy('plugin::todo.is-owner')` | `strapi.middleware('plugin::todo.audit-log')` | — | `strapi.config.get('plugin::todo.featureFlag')` | +| | Top-level | Global | +| --- | --- | --- | +| **Service** | `strapi.plugin('todo').service('task')` | `strapi.service('plugin::todo.task')` | +| **Controller** | `strapi.plugin('todo').controller('task')` | `strapi.controller('plugin::todo.task')` | +| **Content-type** | `strapi.plugin('todo').contentType('task')` | `strapi.contentType('plugin::todo.task')` | +| **Policy** | `strapi.plugin('todo').policy('is-owner')` | `strapi.policy('plugin::todo.is-owner')` | +| **Middleware** | `strapi.plugin('todo').middleware('audit-log')` | `strapi.middleware('plugin::todo.audit-log')` | +| **Routes** | `strapi.plugin('todo').routes` | — | +| **Configuration** | `strapi.plugin('todo').config('featureFlag')` | `strapi.config.get('plugin::todo.featureFlag')` | Both styles return the same underlying object. Routes have no global getter equivalent. Configuration uses dedicated config APIs rather than resource getters, both forms read the same merged value. @@ -68,6 +73,8 @@ Run `yarn strapi console` or `npm run strapi console` to inspect the `strapi` ob ## Usage examples +
+ ### Calling a plugin service from a controller The most common pattern: a controller delegates to its own plugin's service: diff --git a/docusaurus/docs/cms/plugins/documentation.md b/docusaurus/docs/cms/plugins/documentation.md index 2fc376a0b7..1bb6e665ef 100644 --- a/docusaurus/docs/cms/plugins/documentation.md +++ b/docusaurus/docs/cms/plugins/documentation.md @@ -1,5 +1,6 @@ --- title: Documentation plugin +pagination_label: Documentation plugin displayed_sidebar: cmsSidebar description: By using Swagger UI, the API documentation plugin takes out most of your pain to generate your documentation. toc_max_heading_level: 5 diff --git a/docusaurus/docs/cms/plugins/graphql.md b/docusaurus/docs/cms/plugins/graphql.md index b84363ebaa..70e3348255 100644 --- a/docusaurus/docs/cms/plugins/graphql.md +++ b/docusaurus/docs/cms/plugins/graphql.md @@ -1,5 +1,6 @@ --- title: GraphQL plugin +pagination_label: GraphQL plugin displayed_sidebar: cmsSidebar toc_max_heading_level: 6 description: Use a GraphQL endpoint in your Strapi project to fetch and mutate your content. diff --git a/docusaurus/docs/cms/project-structure.md b/docusaurus/docs/cms/project-structure.md index 010a2648a0..b6ffbd796c 100644 --- a/docusaurus/docs/cms/project-structure.md +++ b/docusaurus/docs/cms/project-structure.md @@ -11,6 +11,13 @@ import InteractiveProjectStructure from '@site/src/components/ProjectStructure.j # Project structure + + +A Strapi project's structure varies depending on whether it was created with TypeScript (the default with `--quickstart`) or vanilla JavaScript, and is displayed through an interactive project structure component. + + + + The structure of a Strapi project depends on whether the project was created with [TypeScript](/cms/typescript) (which is the default if you used the `--quickstart` option while creating the project) or with vanilla JavaScript, and looks like the following: diff --git a/docusaurus/docs/cms/quick-start.md b/docusaurus/docs/cms/quick-start.md index 5a9eb8ff94..f8e9d767df 100644 --- a/docusaurus/docs/cms/quick-start.md +++ b/docusaurus/docs/cms/quick-start.md @@ -16,8 +16,19 @@ import InstallPrerequisites from '/docs/snippets/installation-prerequisites.md' # Quick Start Guide + + +Build and deploy a Strapi project from scratch in 10 steps: create a local project with `create-strapi@latest`, define collection types using the Content-Type Builder, deploy to Strapi Cloud with `npm run strapi deploy`, and add content via the Content Manager. + + + + Strapi offers a lot of flexibility. Whether you want to go fast and quickly see the final result, or would rather dive deeper into the product, we got you covered. For this tutorial, we'll go for the DIY approach and build a project and content structure from scratch, then deploy your project to Strapi Cloud to add data from there. +:::tip Track your progress +This guide is organized into collapsible steps. Click a step's title to expand or collapse it, and click the circle on the right of a step to mark it as completed once you're done. Completed steps turn green, and a progress summary at the bottom-right of the page keeps track of how far along you are. +::: + :::strapi 3 options to discover Strapi There are 3 options to discover Strapi. Choose what best suits you: @@ -40,10 +51,7 @@ We will first create a new Strapi project on your machine by running a command i Follow the steps below by clicking on the togglable content to read more instructions. -
-Step 1: Run the installation script and create a Strapi Cloud account - -### Step 1: Run the installation script and create a Strapi Cloud account + 1. Run the following command in a terminal: @@ -87,12 +95,9 @@ As you will see in the terminal, your project is now building locally. * Many more installation options are available. Please refer to the [installation documentation](/cms/installation) for details. ::: -
- -
-Step 2: Register the first local administrator user + -### Step 2: Register the first local administrator user + Once the installation is complete, you need to start the server. In the terminal, type or copy and paste the following: @@ -116,9 +121,9 @@ sources={{ light: '/img/assets/quick-start-guide/qsg-handson-part1-01-admin_panel-v5.png', dark: '/img/assets/quick-start-guide/qsg-handson-part1-01-admin_panel-v5_DARK.png', }} -/> +/> -
+ :::callout Congratulations! You have just created a new Strapi project! You can start playing with Strapi and discover the [Content Manager](/cms/features/content-manager) by yourself, or proceed to part B below. @@ -140,11 +145,7 @@ You might also need to run `npm run build` prior to the `develop` command, espec The Content-Type Builder helps you create your content structure. When creating an empty project with Strapi, this is where to get the party started! -
- -Step 1: Create a "Restaurant" collection type - -### Step 1: Create a "Restaurant" collection type + Your restaurants directory will eventually include many restaurants, so we need to create a "Restaurant" collection type. Then we can describe the fields to display when adding a new restaurant entry: @@ -170,12 +171,9 @@ sources={{ Once Strapi has restarted, "Restaurant" is listed under _Content Manager > Collection types_ in the navigation. Wow, you have just created your very first content-type! It was so cool, let's create another one right now, just for pleasure.
-
- -
-Step 2: Create a "Category" collection type + -### Step 2: Create a "Category" collection type + It would help getting a bit more organized if our restaurants directory had some categories. Let's create a "Category" collection type: @@ -200,7 +198,7 @@ sources={{ 11. Finally, click **Finish**, then the **Save** button, and wait for Strapi to restart. -
+ :::callout Congratulations! You have just created a basic content structure for your Strapi project! You can keep on playing with the [Content-Type Builder](/cms/features/content-type-builder), or proceed to parts C and D below to discover Strapi Cloud and add actual content to your project. @@ -261,10 +259,7 @@ Feel free to play with the Content-Type Builder even further and add more fields Now that we have created a basic content structure with 2 collection types, "Restaurant" and "Category", and deployed your project to Strapi Cloud, let's use the Cloud to actually add content by creating new entries. -
-Step 1: Log in to the admin panel of your new Strapi Cloud project - -### Step 1: Log in to the admin panel of your new Strapi Cloud project + Now that your Strapi Cloud project is created, let's log in into the project: @@ -295,13 +290,9 @@ Any project hosted on Strapi Cloud is accessible from its own URL, something lik
-
- -
-Step 2: Create an entry for the "Restaurant" collection type + - -### Step 2: Create an entry for the "Restaurant" collection type + 1. Go to _Content Manager > Collection types - Restaurant_ in the navigation. 2. Click on **Create new entry**. @@ -319,12 +310,9 @@ sources={{ The restaurant is now listed in the _Collection types - Restaurant_ view of the _Content Manager_.
-
+ -
-Step 3: Add Categories - -#### Step 3: Add Categories + Let's go to _Content Manager > Collection types - Category_ and create 2 categories: @@ -348,12 +336,9 @@ Now, we will add a category to a restaurant: 1. Go to _Content Manager > Collection types - Restaurant_ in the navigation, and click on "Biscotte Restaurant". 2. In the **Categories** drop-down list at the bottom of the page, select "French Food". Scroll back to the top of the page and click **Save**. -
- -
-Step 4: Set Roles & Permissions + -### Step 4: Set Roles & Permissions + We have just added a restaurant and 2 categories. We now have enough content to consume (pun intended). But first, we need to make sure that the content is publicly accessible through the API: @@ -373,12 +358,9 @@ sources={{ dark: '/img/assets/quick-start-guide/qsg-handson-part2-04-roles-v5_DARK.png' }}/> -
- -
-Step 5: Publish the content + -### Step 5: Publish the content + By default, any content you create is saved as a draft. Let's publish our categories and restaurant. @@ -399,12 +381,9 @@ sources={{ }} /> -
+ -
-Step 6: Use the API - -### Step 6: Use the API + OK dear gourmet, we have just finished creating our content and making it accessible through the API. You can give yourself a pat on the back — but you have yet to see the final result of your hard work. @@ -452,7 +431,7 @@ Try it now! The result should be similar to the example response below 👇.
-
+ :::callout Congratulations! Now your content is created, published, and you have permissions to request it through the API. @@ -463,11 +442,26 @@ Keep on creating amazing content! The databases for your Strapi Cloud project and your local project are different. This means that data is not automatically synchronized between your Strapi Cloud and local projects. You can use the [data management system](/cms/features/data-management) to transfer data between projects. ::: -## What to do next? - -Now that you know the basics of creating and publishing content with Strapi, we encourage you to explore and dig deeper into some Strapi features: - - learn how to use Strapi's [REST](/cms/api/rest) API to query the content,
- learn more about Strapi features by browsing the **Features** category,
- learn more about Strapi Cloud projects by reading the [Cloud Documentation](/cloud/intro),
- and [customize your Strapi back end](/cms/backend-customization) and [admin panel](/cms/admin-panel-customization) for advanced use cases.
+
+ +## What's next? + + + + + + + +
diff --git a/docusaurus/docs/cms/setup-deployment.md b/docusaurus/docs/cms/setup-deployment.md index ecb237403e..1e5f533ed8 100644 --- a/docusaurus/docs/cms/setup-deployment.md +++ b/docusaurus/docs/cms/setup-deployment.md @@ -15,6 +15,13 @@ tags: # Installation, Configuration, and Deployment + + +Strapi follows a three-step workflow: install on your local machine, configure the server and admin panel, then deploy to a remote environment like Strapi Cloud. + + + + Strapi is meant to be installed on your local machine, then configured, and finally deployed to a remote environment. This documentation section describes these topics, and clicking on any of the following cards will lead you to the corresponding section: diff --git a/docusaurus/docs/cms/typescript.md b/docusaurus/docs/cms/typescript.md index 35bb842eca..3e81e29c6f 100644 --- a/docusaurus/docs/cms/typescript.md +++ b/docusaurus/docs/cms/typescript.md @@ -8,6 +8,13 @@ tags: --- # TypeScript + + + +TypeScript adds a type system layer to Strapi applications, enabling type-safe code and automatic type generation. Create a new TypeScript project with the `--typescript` flag or add TypeScript support to an existing project. + + + adds an additional type system layer above JavaScript, which means that any valid JavaScript code is also valid TypeScript code. In the context of Strapi development, TypeScript allows for a more type-safe codebase for your application, and provides you with a set of tools for automatic type generation and autocompletion. diff --git a/docusaurus/docs/cms/typescript/adding-support-to-existing-project.md b/docusaurus/docs/cms/typescript/adding-support-to-existing-project.md index 6069023250..25902e2323 100644 --- a/docusaurus/docs/cms/typescript/adding-support-to-existing-project.md +++ b/docusaurus/docs/cms/typescript/adding-support-to-existing-project.md @@ -12,6 +12,13 @@ tags: # Adding TypeScript support to existing Strapi projects + + +Add TypeScript support to existing Strapi projects by creating root and admin `tsconfig.json` files with `allowJs: true` for incremental migration, then rebuild the admin panel. + + + + Adding [TypeScript](/cms/typescript) support to an existing project requires adding 2 `tsconfig.json` files and rebuilding the admin panel. Additionally, the `eslintrc` and `eslintignore` files can be optionally removed. The TypeScript flag `allowJs` should be set to `true` in the root `tsconfig.json` file to incrementally add TypeScript files to existing JavaScript projects. The `allowJs` flag allows `.ts` and `.tsx` files to coexist with JavaScript files. diff --git a/docusaurus/docs/cms/typescript/documents-and-entries.md b/docusaurus/docs/cms/typescript/documents-and-entries.md index 44cbb605ec..8d58cbaefe 100644 --- a/docusaurus/docs/cms/typescript/documents-and-entries.md +++ b/docusaurus/docs/cms/typescript/documents-and-entries.md @@ -15,6 +15,13 @@ tags: # Manipulating documents and entries with a TypeScript-based project + + +Safely manipulate documents and entries in Strapi v5 TypeScript projects using the `UID` and `Data` namespaces for type safety, enabling both generic and known entity type operations with code completion. + + + + This guide will explore [TypeScript](/cms/typescript) patterns for manipulating documents and entries in a Strapi v5 application, including how to leverage Strapi's `UID` and `Data` namespaces to interact with both generic and known entity types safely. If you're working on a TypeScript-based Strapi project, mastering these approaches will help you take full advantage of type safety and code completion, ensuring robust, error-free interactions with your application’s content and components. :::prerequisites diff --git a/docusaurus/docs/cms/typescript/guides.md b/docusaurus/docs/cms/typescript/guides.md index 6d0acffa24..e51b6dcc35 100644 --- a/docusaurus/docs/cms/typescript/guides.md +++ b/docusaurus/docs/cms/typescript/guides.md @@ -10,6 +10,13 @@ tags: # TypeScript guides + + +Guides for leveraging TypeScript in Strapi projects, covering patterns for manipulating documents and entries, and adding TypeScript support to existing projects. + + + + The following guides will help you on specific aspects of a [Typescript-based](/cms/typescript) Strapi project. diff --git a/docusaurus/docs/cms/upgrade-tool.md b/docusaurus/docs/cms/upgrade-tool.md index ea69194a83..db35898afa 100644 --- a/docusaurus/docs/cms/upgrade-tool.md +++ b/docusaurus/docs/cms/upgrade-tool.md @@ -15,6 +15,13 @@ tags: # Upgrade tool + + +The upgrade tool is a CLI command that automatically upgrades Strapi applications to a new version by updating dependencies and applying codemods to the codebase. + + + + The upgrade tool assists Strapi users in upgrading their Strapi application dependencies and code to a specific version. Running the upgrade tool triggers the update of the application dependencies, their installation, and the execution of a series of **codemods** that automatically edit the application codebase according to the breaking changes introduced up until the targeted version. diff --git a/docusaurus/docs/cms/upgrades.md b/docusaurus/docs/cms/upgrades.md index 6913cbed7b..7eae382506 100644 --- a/docusaurus/docs/cms/upgrades.md +++ b/docusaurus/docs/cms/upgrades.md @@ -17,6 +17,13 @@ import DevelopCommand from '/docs/snippets/develop-npm-yarn.md' # Upgrades + + +Strapi periodically releases new versions with improvements. Find your current version in the admin panel or terminal, then follow the upgrade guide for Strapi v4 to v5 migration or use the upgrade tool for v5.x updates. + + + + Strapi periodically releases code improvements through new versions. New Strapi versions are announced in both the terminal and in the administration panel, and list what is new with each new version. The latest version number of Strapi that was released by the Strapi core team can be found on or on . diff --git a/docusaurus/docs/cms/usage-information.md b/docusaurus/docs/cms/usage-information.md index 9afaec1138..98a1ea8c8d 100644 --- a/docusaurus/docs/cms/usage-information.md +++ b/docusaurus/docs/cms/usage-information.md @@ -11,6 +11,13 @@ tags: # Collected Usage Information + + +Strapi collects non-sensitive aggregated data like project ID, machine ID, environment state, and OS to improve the platform, with GDPR compliance and opt-out available via `telemetry:disable` command or `strapi.telemetryDisabled` flag. + + + + We are committed to providing a solution, with Strapi, that exceeds the expectations of the users and community. We are also committed to continuing to develop and make Strapi even better than it is today. To that end, Strapi contains a feature in which non-sensitive data is collected. This data is collectively aggregated for all our users, which when taken together give us a better global understanding of how users are interacting and using Strapi. We will never share the data collected in any way that would identify our Customers or their users; if shared, this data will always be anonymous. ## Context diff --git a/docusaurus/docs/release-notes-archives.md b/docusaurus/docs/release-notes-archives.md new file mode 100644 index 0000000000..52b25bab71 --- /dev/null +++ b/docusaurus/docs/release-notes-archives.md @@ -0,0 +1,3508 @@ +--- +title: Documentation release notes archives +description: Archived Strapi Docs release notes for all previous documentation versions (5.x and 6.x), with links to GitHub pull requests for more information. +toc_max_heading_level: 2 +custom_edit_url: null +--- + +
+ +This page archives the release notes for all previous Strapi Docs versions (5.x and 6.x). For the latest release notes, see the [release notes page](/release-notes). + +## 6.28.0 + +
+### New content + +
+ +#### Repository +- [Document the Billing portal page and update tax guidance for Canada and India](https://github.com/strapi/documentation/pull/3239) +- [Add "Inki" Claude Code plugin: research, write, review, submit Strapi Docs update](https://github.com/strapi/documentation/pull/3200) + +### Updated content + +
+ +#### CMS +- [Document paginated upload files endpoint in the REST API](https://github.com/strapi/documentation/pull/3261) +- [Document documentId support in Users & Permissions relation updates](https://github.com/strapi/documentation/pull/3252) +- [Cms/document factory controller overrides](https://github.com/strapi/documentation/pull/3228) +- [Document the upgrade to command for targeting a specific version](https://github.com/strapi/documentation/pull/3222) +- [Document --install-deps and --no-install-deps CLI flags](https://github.com/strapi/documentation/pull/3221) + +#### Cloud +- [Cloud logs revamp](https://github.com/strapi/documentation/pull/3253) + +#### Repository +- [Document Strapi Cloud upload size limits](https://github.com/strapi/documentation/pull/3231) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Normalize Cloud configuration paths](https://github.com/strapi/documentation/pull/3250) +- [Update parameter name from 'id' to 'documentId'](https://github.com/strapi/documentation/pull/3236) +- [Clarify dynamic zone fragment populate syntax](https://github.com/strapi/documentation/pull/3233) +- [Fix `delete()` row description in REST client API reference](https://github.com/strapi/documentation/pull/3226) +- [Fix `count()` description and remove stray backtick in Document Service API](https://github.com/strapi/documentation/pull/3225) + +#### Repository +- [Rename Inki autonomy flag to `--non-interactive`](https://github.com/strapi/documentation/pull/3257) +- [Detect emphasis, button-icon, and admonition conventions in Inki style review](https://github.com/strapi/documentation/pull/3256) +- [Require Inki orchestrators to invoke sub-skills and bump to 0.2.1](https://github.com/strapi/documentation/pull/3255) +- [Detect title/content scope mismatch and inbound links in Inki review](https://github.com/strapi/documentation/pull/3244) +- [Add Cloud Advanced page type and template to Inki outline-checker](https://github.com/strapi/documentation/pull/3243) +- [Detect em dash HTML entities in Inki style-lint](https://github.com/strapi/documentation/pull/3242) +- [Inki v0.2: end-to-end document workflow, review agents, run logging, and authoring tooling](https://github.com/strapi/documentation/pull/3234) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + + + +## 6.27.0 + +
+### New content + +
+ +#### CMS +- [Strapi MCP server for content management](https://github.com/strapi/documentation/pull/3194) + +### Updated content + +
+ +- [Update Users & Permissions documentation](https://github.com/strapi/documentation/pull/3169) +- [Add deleteMany method documentation to Document Service API](https://github.com/strapi/documentation/pull/3206) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Document optional admin JWT secret for API-only deployments](https://github.com/strapi/documentation/pull/3218) +- [Fix Marketplace custom fields links in CMS feature docs](https://github.com/strapi/documentation/pull/3210) +- [Add v5 to v4 rollback FAQ entry to migration documentation](https://github.com/strapi/documentation/pull/3202) + +#### Repository +- [Make Notion logging idempotent by date for docs self-healing](https://github.com/strapi/documentation/pull/3217) +- [Fix self-healing metrics: track Doc PR fate retroactively](https://github.com/strapi/documentation/pull/3216) +- [Move the MCP server Plugin API reference to plugins-development](https://github.com/strapi/documentation/pull/3214) +- [Ignore local superpowers artifacts in .gitignore](https://github.com/strapi/documentation/pull/3198) +- [Add Need help admonition with support link on CMS and Cloud intros](https://github.com/strapi/documentation/pull/3197) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + andrii-bodnar + + + pwizla + + + singhvishalkr + +
+
+
+ + + + +## 6.26.0 + +
+### New content + +
+ +#### Cloud +- [Add middleware customization guide for Strapi Cloud production environment](https://github.com/strapi/documentation/pull/3148) + +### Updated content + +
+ +#### CMS +- [Document nested sort within populate for join-table relations](https://github.com/strapi/documentation/pull/3186) +- [Update Docker documentation with production setup and troubleshooting](https://github.com/strapi/documentation/pull/3109) + +#### Cloud +- [Environment clearing for Strapi Cloud](https://github.com/strapi/documentation/pull/3180) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add TypeScript workaround for Document Service relational operators](https://github.com/strapi/documentation/pull/3189) +- [Replace unimplemented GraphQL aggregations docs with warning](https://github.com/strapi/documentation/pull/3183) +- [Add tip about filtering by assignee and review stage in list view](https://github.com/strapi/documentation/pull/3170) + +#### Repository +- [Prevent editors from running Prettier](https://github.com/strapi/documentation/pull/3182) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + + + +## 6.25.0 + +
+### Updated content + +
+ +#### CMS +- [Document admin translation contribution path in FAQ](https://github.com/strapi/documentation/pull/3165) +- [Explain middleware on every core route for one content-type](https://github.com/strapi/documentation/pull/3152) +- [Document Content Manager Edit View context hook on Admin Panel API page](https://github.com/strapi/documentation/pull/3146) +- [Document `tsconfig` setup for local TypeScript plugins](https://github.com/strapi/documentation/pull/3121) +- [Add `addRichTextBlocks` to Content Manager API documentation](https://github.com/strapi/documentation/pull/3100) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Update sendmail provider description after Nodemailer switch](https://github.com/strapi/documentation/pull/3164) +- [Update live preview to include support for media](https://github.com/strapi/documentation/pull/3158) +- [Distinguish admin extensions from server plugin overrides](https://github.com/strapi/documentation/pull/3155) +- [Document `__component` for dynamic zones on REST create](https://github.com/strapi/documentation/pull/3153) +- [Document React admin dependencies for v4 upgrades](https://github.com/strapi/documentation/pull/3151) +- [Document dynamic zone __component in REST update section](https://github.com/strapi/documentation/pull/3150) +- [Align public middleware example with maxAge configuration](https://github.com/strapi/documentation/pull/3149) +- [Document locale parameter for Entity Service CRUD](https://github.com/strapi/documentation/pull/3147) +- [Note that REST filter examples need populate to surface traversed relations](https://github.com/strapi/documentation/pull/3144) +- [Document ADMIN_PATH and STRAPI_ADMIN_BACKEND_URL environment variables](https://github.com/strapi/documentation/pull/3143) +- [Document AWS RDS IAM auth with short-lived tokens](https://github.com/strapi/documentation/pull/3141) +- [Document concurrentUploadSize upload plugin option](https://github.com/strapi/documentation/pull/3138) +- [Update pnpm mention to warn about Strapi Cloud compatibility](https://github.com/strapi/documentation/pull/3135) +- [Clarify nested component required metadata gap in OpenAPI guide](https://github.com/strapi/documentation/pull/3128) + +#### Repository +- [Add conditional retrieval budgets and drafting guardrails to agent prompts](https://github.com/strapi/documentation/pull/3167) +- [Track ask_user router decisions in Notion metrics for docs self-healing system](https://github.com/strapi/documentation/pull/3166) +- [Add native Kapa dark mode support](https://github.com/strapi/documentation/pull/3159) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + + + +## 6.24.0 + +
+### New content + +
+ +#### CMS +- [Document the `/users` endpoints](https://github.com/strapi/documentation/pull/3027) +- [Admin tokens](https://github.com/strapi/documentation/pull/2992) + +### Updated content + +
+ +#### CMS +- [Clarify TypeScript Jest entrypoint for harness](https://github.com/strapi/documentation/pull/3125) +- [Add install step after clone in test-locally walkthrough for Data Transfer](https://github.com/strapi/documentation/pull/3122) +- [Add sharp configuration details for Media Library](https://github.com/strapi/documentation/pull/3102) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Align Document Service note with connect payloads](https://github.com/strapi/documentation/pull/3129) +- [Note that internal entity-validator is not public API](https://github.com/strapi/documentation/pull/3120) +- [Add missing Draft & Publish availability note to methods overview](https://github.com/strapi/documentation/pull/3119) +- [Add sanitization warning to Document Service API page](https://github.com/strapi/documentation/pull/3114) +- [Mention sorting by publish status in Content Manager List View](https://github.com/strapi/documentation/pull/3113) +- [Document polymorphic relations support in Document Service API populate](https://github.com/strapi/documentation/pull/3112) +- [Update plugin Component examples to use non-deprecated import pattern](https://github.com/strapi/documentation/pull/3111) +- [Fix OpenAPI example id type to string](https://github.com/strapi/documentation/pull/3107) +- [Document Deploy widget on homepage](https://github.com/strapi/documentation/pull/3106) + +#### Repository +- [Widen self-healing deduplication to scan all doc PRs](https://github.com/strapi/documentation/pull/3116) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + + + +## 6.23.0 + +
+### New content + +
+ +#### CMS +- [Add recap pages for AI features](https://github.com/strapi/documentation/pull/3091) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add a tip to AI for devs page to cross-link agents.md files](https://github.com/strapi/documentation/pull/3104) +- [Update database transactions page to use Document Service API](https://github.com/strapi/documentation/pull/3097) +- [Document populate support in Document Service API `delete()` operations](https://github.com/strapi/documentation/pull/3094) +- [Add note about Vite `.mts` ESM syntax support](https://github.com/strapi/documentation/pull/3080) + +#### Cloud +- [Reactivate the subscription flow for Strapi Cloud](https://github.com/strapi/documentation/pull/3101) + +#### Repository +- [Docs self-healing workflow improvements: Split Notion rejection metrics into Triage and Router](https://github.com/strapi/documentation/pull/3095) +- [Add Notion metrics logging for self-healing runs](https://github.com/strapi/documentation/pull/3079) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + mariekirsch + + + pwizla + +
+
+
+ + + + +## 6.22.0 + +
+### New + +
+ +#### CMS +- [Document responseType option for useFetchClient in plugins](https://github.com/strapi/documentation/pull/3081) + +#### Repo +- [Add docs self-healing workflow](https://github.com/strapi/documentation/pull/3059) + +### Updated content + +
+ +#### CMS +- [Add admin user management CLI commands + group CLI commands by category](https://github.com/strapi/documentation/pull/3061) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Document transfer checksum verification and asset idle timeout](https://github.com/strapi/documentation/pull/3077) +- [Mention improved transfer CLI progress display](https://github.com/strapi/documentation/pull/3076) +- [Document unique username generation for auth provider registration](https://github.com/strapi/documentation/pull/3075) +- [Document AWS S3 credential format with deprecation notice](https://github.com/strapi/documentation/pull/3068) +- [Document signed URL behavior for S3 private buckets](https://github.com/strapi/documentation/pull/3067) +- [Cross-link best practices for high-performance Strapi blog post](https://github.com/strapi/documentation/pull/3060) +- [Remove yarn from main pages](https://github.com/strapi/documentation/pull/3042) + +#### Repository +- [Fix auto-labeling: infra-only PRs always labeled as chore](https://github.com/strapi/documentation/pull/3085) +- [Docs self-healing workflow improvements: Auto-ignore rejected PRs for future runs](https://github.com/strapi/documentation/pull/3084) +- [Docs self-healing workflow improvements: Add dry run mode](https://github.com/strapi/documentation/pull/3082) +- [Docs self-healing workflow improvements: Exclude translations, bots, dependency upgrades](https://github.com/strapi/documentation/pull/3078) +- [Docs self-healing workflow improvements: Add Slack notification](https://github.com/strapi/documentation/pull/3072) +- [Docs self-healing workflow improvements: Add ignore list](https://github.com/strapi/documentation/pull/3070) +- [Docs self-healing workflow improvements: Skip `flag: documentation` PRs and run Tue-Sat only](https://github.com/strapi/documentation/pull/3066) +- [Docs self-healing workflow improvements: Add ultra-light Haiku triage before Router](https://github.com/strapi/documentation/pull/3065) +- [Docs self-healing workflow improvements: Split into Haiku Router + Sonnet Drafter](https://github.com/strapi/documentation/pull/3064) +- [Docs self-healing workflow improvements: Pre-filter PRs before Claude](https://github.com/strapi/documentation/pull/3062) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + cache-your-dreams + + + pwizla + +
+
+
+ + + + +## 6.21.0 + +
+### New content + +
+ +#### CMS +- [Document `@strapi/utils`](https://github.com/strapi/documentation/pull/3032) + +#### Repository +- [Add directory export/import instructions for the Data Management feature](https://github.com/strapi/documentation/pull/3043) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Clarify S3 URL construction priority for compatible providers](https://github.com/strapi/documentation/pull/3055) +- [Clarify populate and pagination combination](https://github.com/strapi/documentation/pull/3048) +- [Add FAQ entry about disabling foreign key creation in databases](https://github.com/strapi/documentation/pull/3047) +- [Use lockfile-based installs and document alternative base image for Docker](https://github.com/strapi/documentation/pull/3046) +- [Add supported browsers for Strapi Admin in Quick Start Guide prerequisites](https://github.com/strapi/documentation/pull/3045) +- [Preserve relations in fill from another locale feature](https://github.com/strapi/documentation/pull/3041) +- [Add openapi.json route documentation (#2143) (#2159)](https://github.com/strapi/documentation/pull/2759) + +#### Repository +- [Expand config abbreviations in agent prompts and authoring guides](https://github.com/strapi/documentation/pull/3057) +- [Merge AGENTS.md and CLAUDE.md](https://github.com/strapi/documentation/pull/3044) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + + + +## 6.20.0 + +
+### New content + +
+ +#### Repository +- [Add CLAUDE.MD](https://github.com/strapi/documentation/pull/3033) +- [Add Integrity Checker](https://github.com/strapi/documentation/pull/3031) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix Dockerfile by adjusting WORKDIR in production dockerfile](https://github.com/strapi/documentation/pull/3036) +- [Review workflows stage to permissions](https://github.com/strapi/documentation/pull/3024) + +#### Cloud +- [One time password update](https://github.com/strapi/documentation/pull/3037) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + + + +## 6.19.0 + +
+### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [fix: export includes 3rd party providers assets](https://github.com/strapi/documentation/pull/3022) +- [Add tips for List View and Edit View usage of `documentId` in Content Manager](https://github.com/strapi/documentation/pull/3021) + +#### Repository +- [Allow agents to do a single round of self-check after PR creation](https://github.com/strapi/documentation/pull/3019) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + nclsndr + + + pwizla + +
+
+
+ + + + +## 6.18.1 + +
+### Updated content + +
+ +#### CMS +- [Refresh the Quick Start Guide](https://github.com/strapi/documentation/pull/3017) +- [Add more information about the `arrayLimit` parameter from the `strapi::query` middleware](https://github.com/strapi/documentation/pull/3010) +- [Improve the admin panel extension page](https://github.com/strapi/documentation/pull/3003) + +#### Cloud +- [VAT handling on Strapi Cloud](https://github.com/strapi/documentation/pull/3011) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Extend warning about data loss when using DTS import](https://github.com/strapi/documentation/pull/3005) +- [Fix plugins extension page](https://github.com/strapi/documentation/pull/3000) + +#### Cloud +- [Downgrading with an organization repository](https://github.com/strapi/documentation/pull/3009) +- [Update project creation page](https://github.com/strapi/documentation/pull/3008) +- [Update deletion reasons](https://github.com/strapi/documentation/pull/3007) + +#### Repository +- [Ensure the Style Checker spots em dashes](https://github.com/strapi/documentation/pull/3002) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + innerdvations + + + mariekirsch + + + pwizla + +
+
+
+ + +## 6.18.0 + +
+### New content + +
+ +#### CMS +- [Fully rework and expand the server API part of the plugins development documentation](https://github.com/strapi/documentation/pull/2991) +- [Fully rework and expand the admin panel API part of the plugins development documentation](https://github.com/strapi/documentation/pull/2920) + +### Updated content + +
+ +#### CMS +- [Document list view filters for Draft & Publish](https://github.com/strapi/documentation/pull/2998) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix some inconsistencies between docs and codebase for Server API](https://github.com/strapi/documentation/pull/2996) +- [Fix middleware file path in upload documentation](https://github.com/strapi/documentation/pull/2993) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + evrys + + + maccomaccomaccomacco + + + pwizla + +
+
+
+ + + + +## 6.17.1 + +
+### New content + +
+ +#### Repository +- [Add Outline generator and Drafter tools](https://github.com/strapi/documentation/pull/2947) + +### Updated content + +
+ +#### CMS +- [Expand Email documentation with Nodemailer v8 options](https://github.com/strapi/documentation/pull/2988) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add relation open modal setting for content-manager configure the view](https://github.com/strapi/documentation/pull/2986) + +#### Repository +- [Improve Drafter instructions: avoid em dashes, add code highlights](https://github.com/strapi/documentation/pull/2989) +- [Ensure the Outline UX Analyzer tool is included in auto-chain mode](https://github.com/strapi/documentation/pull/2985) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + markkaylor + + + pwizla + +
+
+
+ + +## 6.17.0 + +
+### New content + +
+ +#### Repository +- [Add auto-chain mode to Docs AI creation/review tools](https://github.com/strapi/documentation/pull/2980) +- [Add Cursor rules and refine core project instructions](https://github.com/strapi/documentation/pull/2978) + +### Updated content + +
+ +#### CMS +- [Add `strictParams` and custom Content API parameters](https://github.com/strapi/documentation/pull/2974) +- [Improve REST API population page UX](https://github.com/strapi/documentation/pull/2971) +- [SDK plugin v6](https://github.com/strapi/documentation/pull/2919) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix inconsistent database requirements](https://github.com/strapi/documentation/pull/2976) +- [Update example request URL in REST API documentation](https://github.com/strapi/documentation/pull/2972) + +#### Repository +- [Update Cursor rules to include auto-chain mode](https://github.com/strapi/documentation/pull/2981) +- [Fix bug in Strapi CMS release notes link generation](https://github.com/strapi/documentation/pull/2970) +- [Fix auto-labelling of PRs by source and content-type](https://github.com/strapi/documentation/pull/2969) +- [Fix branch naming rules](https://github.com/strapi/documentation/pull/2967) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.16.1 + +
+### Updated content + +
+ +#### CMS +- [Update docs with persistent list view settings for the Content Manager](https://github.com/strapi/documentation/pull/2959) +- [Add extended AWS S3 provider configuration](https://github.com/strapi/documentation/pull/2949) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add `.strapi/` folder to "fix build issues with the generated types" TypeScript code example](https://github.com/strapi/documentation/pull/2963) +- [Add `--non-interactive` and `--enable-ab-tests` flags for CLI installation](https://github.com/strapi/documentation/pull/2957) +- [Update findOne method to use new document structure](https://github.com/strapi/documentation/pull/2950) +- [Update locale.md (POST requests)](https://github.com/strapi/documentation/pull/2948) +- [Add new `--no-build-admin` parameter for `strapi-develop` CLI](https://github.com/strapi/documentation/pull/2946) + +#### Repository +- [Add instructions for URLs validation to Router tool](https://github.com/strapi/documentation/pull/2960) +- [Improve Router output (tables, instructions for pipeline)](https://github.com/strapi/documentation/pull/2956) +- [Improve Drafter tool for API pages](https://github.com/strapi/documentation/pull/2955) +- [Clarify CMS vs. Docs version numbers in release notes](https://github.com/strapi/documentation/pull/2954) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + Bellian + + + bart-webleads + + + pwizla + +
+
+
+ +
+ + +## 6.16.0 + +
+### New content + +
+ +#### Repository +- [Add Router documentation tool](https://github.com/strapi/documentation/pull/2933) +- [Add Outliner tools for PR reviews](https://github.com/strapi/documentation/pull/2932) + +### Updated content + +
+ +#### CMS +- [Fix outdated `strapi develop` parameter docs](https://github.com/strapi/documentation/pull/2938) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add direct links to most asked integration pages](https://github.com/strapi/documentation/pull/2935) +- [Fix `ip` middleware not appearing in Configurations > Middlewares secondary sidebar](https://github.com/strapi/documentation/pull/2937) + +#### Repository +- [Re-introduce Routing summary in details for documentation specialists (Router tool)](https://github.com/strapi/documentation/pull/2942) +- [Improvements to Router tool ](https://github.com/strapi/documentation/pull/2941) +- [Replace `migration-template.md` with `breaking-change-template.md`](https://github.com/strapi/documentation/pull/2931) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + pwizla + +
+
+
+ + +## 6.15.1 + +
+### New content + +
+ +#### CMS + +- [Add focal point documentation to media library page](https://github.com/strapi/documentation/pull/2930) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix typo in "Populate and Select" documentation](https://github.com/strapi/documentation/pull/2929) +- [Reorganize Media Library providers documentation](https://github.com/strapi/documentation/pull/2922) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + leon-win + + + markkaylor + + + pwizla + +
+
+
+ + +## 6.15.0 + +
+### New content + +
+ +#### CMS +- [Add docs for Media Library retroactive AI generation](https://github.com/strapi/documentation/pull/2918) + +#### Repository +- [First documentation automation tools: agents.md, templates, and style checker](https://github.com/strapi/documentation/pull/2923) + +### Updated content + +
+ +#### CMS +- [Fix favicon docs](https://github.com/strapi/documentation/pull/2899) + +#### Repository +- [Add global Annotation for naming conventions (kebab-case and more)](https://github.com/strapi/documentation/pull/2926) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Update supported Node versions](https://github.com/strapi/documentation/pull/2917) + +#### Cloud +- [Clarify API request counting in usage billing documentation](https://github.com/strapi/documentation/pull/2924) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + mariekirsch + + + markkaylor + + + pwizla + +
+
+
+ + +## 6.14.1 + +
+### Updated content + +
+ +#### CMS +- [Fix Admin Panel API example that used deprecated helper plugin](https://github.com/strapi/documentation/pull/2910) + +#### Cloud +- [Cloud yearly plans](https://github.com/strapi/documentation/pull/2901) +- [Data transfer between Cloud environments](https://github.com/strapi/documentation/pull/2891) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Doc bugfix: documents().update expects documentId param outside of data](https://github.com/strapi/documentation/pull/2909) + +#### Cloud +- [Manage beta badge for Cloud features](https://github.com/strapi/documentation/pull/2913) +- [Update custom domain saving options](https://github.com/strapi/documentation/pull/2906) + + +#### Repository +- [Close corresponding milestone with automated release script](https://github.com/strapi/documentation/pull/2916) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + mariekirsch + + + mephinet + + + pwizla + +
+
+
+ +## 6.14.0 + +
+### New content + +
+ +#### Repository +- [Add hosted MCP server for docs](https://github.com/strapi/documentation/pull/2889) + +### Updated content + +
+ +#### Repository +- [Document auth fix for 5.24.0+](https://github.com/strapi/documentation/pull/2764) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Suggest using NPM for package manager when deploying to Kubernetes](https://github.com/strapi/documentation/pull/2533) + +#### Cloud +- [Update API request limits for the free Cloud plan](https://github.com/strapi/documentation/pull/2893) +- [Update region availability for Cloud](https://github.com/strapi/documentation/pull/2892) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + mariekirsch + + + pwizla + + + soheilnikroo + +
+
+
+ + +## 6.13.0 + +
+### New content + +
+ +#### Repository +- [Add `` component](https://github.com/strapi/documentation/pull/2883) + +### Updated content + +
+ +#### CMS +- [Checklist in SSO configuration documentation](https://github.com/strapi/documentation/pull/2882) +- [Document Service API intro rework: more details, updated structure](https://github.com/strapi/documentation/pull/2880) +- [Lifecycle functions rework: structure change, more details & examples](https://github.com/strapi/documentation/pull/2878) +- [Tip about nested page hierarchies in Content-type Builder documentation](https://github.com/strapi/documentation/pull/2876) +- [More details regarding image uploading](https://github.com/strapi/documentation/pull/2875) +- [Add example to Theme extension documentation](https://github.com/strapi/documentation/pull/2850) +- [Add TypeScript example and deliverability tip to Email documentation](https://github.com/strapi/documentation/pull/2839) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Notify users about Apollo In Memory Cache ID](https://github.com/strapi/documentation/pull/2884) +- [Add types for Backend Customization Custom Routes](https://github.com/strapi/documentation/pull/2879) + +#### Repository +- [Fix unneeded margin on first-in-the-list custom docs card component](https://github.com/strapi/documentation/pull/2881) +- [Remove Amplitude-related elements](https://github.com/strapi/documentation/pull/2873) +- [Fix main content layout shift](https://github.com/strapi/documentation/pull/2872) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + meganelacheny + + + pwizla + + + unrevised6419 + +
+
+
+ + +## 6.12.0 + +
+### New content + +
+ +#### CMS +- [Add a guide about using RBAC from plugins](https://github.com/strapi/documentation/pull/2788) + +#### Repository +- [LLMs-code.txt](https://github.com/strapi/documentation/pull/2819) + +### Updated content + +
+ +#### CMS +- [Update and add details & examples in GraphQL API migration guides](https://github.com/strapi/documentation/pull/2828) +- [Expand caution callout for media asset relations](https://github.com/strapi/documentation/pull/2822) +- [Aggregations section in GraphQL API documentation](https://github.com/strapi/documentation/pull/2810) + +#### Cloud +- [Clarify differences between accessing API on self-hosted VS Cloud hosted app](https://github.com/strapi/documentation/pull/2818) + +#### Repository +- [Add more information about `allowedHosts` for servers using Vite](https://github.com/strapi/documentation/pull/2813) +- [Fix main content alignment "flash"](https://github.com/strapi/documentation/pull/2812) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix mistake in Middleware documentation](https://github.com/strapi/documentation/pull/2820) + +#### Cloud +- [Save & deploy for Node version](https://github.com/strapi/documentation/pull/2808) + +#### Repository +- [Mention `/_health` endpoint in server config. & deployment docs](https://github.com/strapi/documentation/pull/2816) +- [Add warning for DATABASE_ environment variables](https://github.com/strapi/documentation/pull/2809) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.11.0 + +
+### New content + +
+ +#### Repository +- [Add "Open with… [LLM]" buttons](https://github.com/strapi/documentation/pull/2794) + +### Updated content + +
+ +#### CMS +- [Add security configuration documentation for Media Library](https://github.com/strapi/documentation/pull/2790) +- [Add information & configuration example in Email feature page](https://github.com/strapi/documentation/pull/2801) +- [Add information on controllers & routes](https://github.com/strapi/documentation/pull/2797) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Include `` components content in `llms.txt`](https://github.com/strapi/documentation/pull/2803) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + araksyagevorgyan + + + meganelacheny + + + pwizla + +
+
+
+ + +## 6.10.1 + +
+### Updated content + +
+ +#### CMS +- [More clarity and precisions on multi relations support](https://github.com/strapi/documentation/pull/2796) +- [AI-powered i18n](https://github.com/strapi/documentation/pull/2773) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix outdated example in Understanding populate guide](https://github.com/strapi/documentation/pull/2798) +- [Add tip about older `npx create-strapi-app@latest` installation command](https://github.com/strapi/documentation/pull/2795) + +#### Repository +- [Disable Kapa widget feedback](https://github.com/strapi/documentation/pull/2793) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + meganelacheny + + + pwizla + +
+
+
+ + +## 6.10.0 + +
+### New content + +
+ +#### Repository +- [Replace Algolia search with MeiliSearch](https://github.com/strapi/documentation/pull/2783) +- [Add a "News Ticker" to homepage](https://github.com/strapi/documentation/pull/2766) + +### Updated content + +
+ +#### CMS +- [Add rate limiting documentation for users-permissions plugin](https://github.com/strapi/documentation/pull/2782) + +#### Repository +- [Add contribution program links to footer and top nav](https://github.com/strapi/documentation/pull/2781) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Fix S key in Ask AI modal triggering the MeiliSearch modal](https://github.com/strapi/documentation/pull/2786) +- [Docs Contribution Program: updates in PR template & contribution guide](https://github.com/strapi/documentation/pull/2784) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + crasite + + + meganelacheny + + + pwizla + +
+
+
+ + +## 6.9.5 + +
+### Updated content + +
+ +#### CMS +- [Rework the Unit testing page for Strapi 5](https://github.com/strapi/documentation/pull/2712) + +### Chore, fixes, typos, and other improvements + +
+ +#### Cloud +- [Save & deploy for update repository](https://github.com/strapi/documentation/pull/2767) + +#### Repository +- [Fix code block buttons overlapping content](https://github.com/strapi/documentation/pull/2772) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + mariekirsch + + + pwizla + +
+
+
+ +## 6.9.4 + +
+ +### Chore, fixes, typos, and other improvements + +
+ +#### Cloud +- [Update Cloud docs for passwordless authentication](https://github.com/strapi/documentation/pull/2765) +- [Display Subscription ID in the project settings](https://github.com/strapi/documentation/pull/2761) +- [Update Usage & Billing with Free Plan details](https://github.com/strapi/documentation/pull/2762) + +#### CMS +- [Update Homepage customization page to add layout customization tips](https://github.com/strapi/documentation/pull/2741) +- [Add FAQ entry for MCP](https://github.com/strapi/documentation/pull/2754) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.9.3 + +
+### New content + +
+ +#### CMS +- [Strapi AI for Content-Type Builder](https://github.com/strapi/documentation/pull/2737) +- [Strapi AI for Media Library](https://github.com/strapi/documentation/pull/2751) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add information about disabling Strapi AI](https://github.com/strapi/documentation/pull/2749) +- [Fix `secrets.encryptionKey` in API tokens docs](https://github.com/strapi/documentation/pull/2743) + +#### Cloud +- [Save & deploy for domains](https://github.com/strapi/documentation/pull/2746) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 6.9.2 + +
+### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [fix: proxy breaking change in server example](https://github.com/strapi/documentation/pull/2731) + +#### Cloud +- [Fix reactivate subscription errors](https://github.com/strapi/documentation/pull/2734) +- [Save & deploy on branch change](https://github.com/strapi/documentation/pull/2730) +- [Save & deploy Cloud environment variables](https://github.com/strapi/documentation/pull/2729) +- [Add note about cloud project reactivation](https://github.com/strapi/documentation/pull/2701) + +#### Repository +- [Fix badges display & positioning](https://github.com/strapi/documentation/pull/2740) +- [Automatically add proper `source:` and `pr:` labels to PRs](https://github.com/strapi/documentation/pull/2735) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 6.9.1 + +
+### Updated content + +
+ +#### CMS +- [Fix Strapi TypeScript import example](https://github.com/strapi/documentation/pull/2721) +- [Explain `unique` parameter behavior with Draft & Publish](https://github.com/strapi/documentation/pull/2716) +- [Add session management documentation](https://github.com/strapi/documentation/pull/2709) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add additional context to the admin locales and translations page](https://github.com/strapi/documentation/pull/2717) +- [Fix CMS Quick Start for NPM compatibility](https://github.com/strapi/documentation/pull/2710) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 6.9.1 + +
+### Updated content + +
+ +#### CMS +- [Fix Strapi TypeScript import example](https://github.com/strapi/documentation/pull/2721) +- [Explain `unique` parameter behavior with Draft & Publish](https://github.com/strapi/documentation/pull/2716) +- [Add session management documentation](https://github.com/strapi/documentation/pull/2709) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add additional context to the admin locales and translations page](https://github.com/strapi/documentation/pull/2717) +- [Fix CMS Quick Start for NPM compatibility](https://github.com/strapi/documentation/pull/2710) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 6.9.0 + +
+### New content + +
+ +#### Repository +- [Add new "TL;DR" component to all relevant pages](https://github.com/strapi/documentation/pull/2702) + +### Updated content + +
+ +#### CMS +- [Live Preview improvements](https://github.com/strapi/documentation/pull/2690) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Update docker.md](https://github.com/strapi/documentation/pull/2707) +- [Fix old Strapi code base links wrongly referencing master branch](https://github.com/strapi/documentation/pull/2704) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + pwizla + + + the-clint + +
+
+
+ +## 6.8.1 + +
+### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix typo in Content-type definition for credentials in TypeScript docs code example](https://github.com/strapi/documentation/pull/2697) + +#### Repository +- [Automatically tag PRs: `internal` or `contribution`](https://github.com/strapi/documentation/pull/2691) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + busybox11 + + + pwizla + +
+
+
+ + +## 6.8.0 + +
+### New content + +
+ +#### Repository +- [Contextual AI for codeblocks](https://github.com/strapi/documentation/pull/2675) +- [Add AI Toolbar](https://github.com/strapi/documentation/pull/2673) +- [Add starter questions to Kapa AI modal](https://github.com/strapi/documentation/pull/2672) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Fix the strapi/strapi contributing link](https://github.com/strapi/documentation/pull/2686) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + guptadeepak8 + + + pwizla + +
+
+
+ + +## 6.7.0 + +
+### New content + +
+ +#### CMS +- [Open API spec generation](https://github.com/strapi/documentation/pull/2665) + +### Updated content + +
+ +#### CMS +- [Update Admin Panel and Homepage customization pages with new widgets and new guided tour UI](https://github.com/strapi/documentation/pull/2671) +- [Update controller sanitization](https://github.com/strapi/documentation/pull/2661) +- [Document flat archive structure for import and export](https://github.com/strapi/documentation/pull/2658) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix no search results for `db.query`](https://github.com/strapi/documentation/pull/2667) +- [Fix typo in lifecycle functions documentation](https://github.com/strapi/documentation/pull/2660) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + devios327 + + + maccomaccomaccomacco + + + pwizla + +
+
+
+ +## 6.6.6 + +
+### New content + +
+ +#### CMS +- [Add experimental firstPublishedAt configuration](https://github.com/strapi/documentation/pull/2636) +- [Update admin panel doc to add new 'Reset guided tour' setting](https://github.com/strapi/documentation/pull/2612) + +#### Cloud +- [Transfer ownership feature in Strapi Cloud docs](https://github.com/strapi/documentation/pull/2611) +- [Download backup on Strapi Cloud](https://github.com/strapi/documentation/pull/2582) + +### Updated content + +
+ +#### CMS +- [Clarify `database` vs. `filename` usage in database configuration](https://github.com/strapi/documentation/pull/2657) +- [Database configuration: callout with information on data.db path](https://github.com/strapi/documentation/pull/2655) +- [Expand service docs to mention methods wrap core methods from Document Service API](https://github.com/strapi/documentation/pull/2648) +- [Clarify Content Manager API typing](https://github.com/strapi/documentation/pull/2646) +- [Note in Server about keep alive configuration](https://github.com/strapi/documentation/pull/2645) +- [Improve PostgreSQL database config. example](https://github.com/strapi/documentation/pull/2643) +- [Improve environment variables page](https://github.com/strapi/documentation/pull/2639) +- [Add advanced queries and policies guides to GraphQL docs](https://github.com/strapi/documentation/pull/2634) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix 'v4CompatibilityMode' typo for Strapi 5 migration in step by step guide](https://github.com/strapi/documentation/pull/2640) +- [Fix 'v4CompatibilityMode' typo for Strapi 5 migration](https://github.com/strapi/documentation/pull/2635) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.6.5 + +
+### New content + +
+ +#### Cloud +- [Async project creation on Strapi Cloud](https://github.com/strapi/documentation/pull/2581) + +### Updated content + +
+ +#### CMS +- [Improve GraphQL queries explanations (Flat vs. Relay-style)](https://github.com/strapi/documentation/pull/2621) +- [Explain there's only one GraphQL endpoint and how to customize its URL](https://github.com/strapi/documentation/pull/2617) +- [GraphQL & REST API: more information on operators & more examples](https://github.com/strapi/documentation/pull/2615) +- [Update Preview feature docs to mention Desktop/Mobile switch](https://github.com/strapi/documentation/pull/2607) +- [Better explain the move to `documentId`](https://github.com/strapi/documentation/pull/2604) +- [Expand and improve Client docs](https://github.com/strapi/documentation/pull/2602) +- [Mention that the Document Service API `findOne` returns `null` if no document found](https://github.com/strapi/documentation/pull/2614) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Fix MermaidWithFallback diagram display](https://github.com/strapi/documentation/pull/2609) +- [Fix tabs display with long labels](https://github.com/strapi/documentation/pull/2605) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 6.6.4 + +
+### Updated content + +
+ +#### CMS +- [Add callout about overriding image function in Plugins extension docs](https://github.com/strapi/documentation/pull/2601) +- [Extend strapi.console documentation](https://github.com/strapi/documentation/pull/2600) +- [Document pluginOptions in Models](https://github.com/strapi/documentation/pull/2598) +- [Improve strapi-generate docs further](https://github.com/strapi/documentation/pull/2595) +- [Expand strapi generate documentation](https://github.com/strapi/documentation/pull/2593) +- [Document release statuses in Releases feature page](https://github.com/strapi/documentation/pull/2592) + +#### Cloud +- [Add cancellation section in Cloud docs](https://github.com/strapi/documentation/pull/2599) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add mention about building the website in Quick Start Guide](https://github.com/strapi/documentation/pull/2590) + +#### Cloud +- [Update Strapi Cloud settings screenshots](https://github.com/strapi/documentation/pull/2585) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + mariekirsch + + + meganelacheny + + + pwizla + +
+
+
+ +## 6.6.3 + +
+### Updated content + +
+ +#### Cloud +- [Canny widget](https://github.com/strapi/documentation/pull/2575) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix incorrect wording in the description of the `findOne()` method](https://github.com/strapi/documentation/pull/2586) +- [Fix broken line breaks in step-by-step file](https://github.com/strapi/documentation/pull/2580) +- [Fix strapi network mismatch issues in Docker instructions](https://github.com/strapi/documentation/pull/2578) + +#### Repository +- [Fix duplicate footer](https://github.com/strapi/documentation/pull/2589) +- [Fix Amplitude tracking experiment CDN](https://github.com/strapi/documentation/pull/2574) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 6.6.2 + +
+### Updated content + +
+ +#### CMS +- [Conditional Fields (stable release)](https://github.com/strapi/documentation/pull/2554) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Remove duplicated sections in Preview docs](https://github.com/strapi/documentation/pull/2568) +- [Use new notation for accessing plugin config](https://github.com/strapi/documentation/pull/2562) + +#### Repository +- [New tooltips in table of content](https://github.com/strapi/documentation/pull/2561) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.6.1 + +
+### New content + +
+ +#### CMS +- [Add repeatable components/Document Service API breaking change](https://github.com/strapi/documentation/pull/2551) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Add link to blog article about webhooks and Next.js](https://github.com/strapi/documentation/pull/2549) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + pwizla + +
+
+
+ +## 6.6.0 + +
+### New content + +
+ +#### CMS +- [Conditional Fields (beta)](https://github.com/strapi/documentation/pull/2539) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Add tip about using copy markdown button and LLMs.txt files](https://github.com/strapi/documentation/pull/2543) +- [Expandable card docs wrapper](https://github.com/strapi/documentation/pull/2541) +- [Add configuration parameter to allow Kapa analytics](https://github.com/strapi/documentation/pull/2540) +- [Add inline property to custom Badge component](https://github.com/strapi/documentation/pull/2538) +- [Increase "Ask AI" modal width to 720px](https://github.com/strapi/documentation/pull/2536) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + meganelacheny + + + pwizla + +
+
+
+ +## 6.5.0 + +
+### New content + +
+ +#### Repository +- [Add LLMs.txt and LLMs-full.txt generation](https://github.com/strapi/documentation/pull/2507) + +We've started adding support to the Strapi Docs. You can find the files in the footer or access them directly via the following links: +- [`llms.txt`](https://docs.strapi.io/llms.txt) +- [`llms-full.txt`](https://docs.strapi.io/llms-full.txt) + +![LLM files in the footer](/img/assets/llms/llms-footer.png) + +### Updated content + +
+ +#### CMS +- [Update app creation flow to include Growth free trial](https://github.com/strapi/documentation/pull/2496) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Admin Panel API typo in example](https://github.com/strapi/documentation/pull/2508) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + abdallahmz + + + martinschilliger + + + pwizla + +
+
+
+ + +## 6.4.0 + +This release marks some significant additions and rewrites. We've rethought the dev-related content in the CMS docs, with a **clearer table of contents** for the development, configuration, and customization aspects of Strapi. + +We've also added a handy ** Copy Markdown** button to the navigation bar on the right, so you can easily copy & paste raw Markdown content from the page into your favorite LLM! + +Enjoy, and watch out for more AI-related features soon 👀 + +
+ +### New content + +
+ +#### Repository +- [Add "Copy Markdown" button](https://github.com/strapi/documentation/pull/2498) + +### Updated content + +
+ +#### CMS +- [Dev-related content rework, iteration #2 (admin panel configuration and customization)](https://github.com/strapi/documentation/pull/2505) +- [Dev-related content rework, iteration #1](https://github.com/strapi/documentation/pull/2501) +- [Content-type Builder revamp (stable release)](https://github.com/strapi/documentation/pull/2480) + +### Chore, fixes, typos, and other improvements + +
+ +#### Cloud +- [Cloud Free plan edits for CMS docs ](https://github.com/strapi/documentation/pull/2500) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + mariekirsch + + + meganelacheny + + + pwizla + +
+
+
+ +## 6.3.1 + +
+### Updated content + +
+ +#### Cloud +- [Free Cloud plan](https://github.com/strapi/documentation/pull/2492) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + pwizla + +
+
+
+ +## 6.3.0 + +
+### New content + +
+ +#### CMS +- [Homepage API](https://github.com/strapi/documentation/pull/2474) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Remove Node 18 support and misc. cleanup](https://github.com/strapi/documentation/pull/2486) +- [Remove obsolete version attribute from Docker guide](https://github.com/strapi/documentation/pull/2485) +- [Viewable API tokens in the admin panel](https://github.com/strapi/documentation/pull/2484) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.2.2 + +
+### Updated content + +
+ +#### CMS +- [Content-type Builder revamp (beta release)](https://github.com/strapi/documentation/pull/2479) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Update theme extension (colors) in admin panel customization](https://github.com/strapi/documentation/pull/2478) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + meganelacheny + + + soheilnikroo + +
+
+
+ +## 6.2.1 + +
+### Updated content + +
+ +#### CMS +- [Add Guideflows to feature pages](https://github.com/strapi/documentation/pull/2473) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Display required version for audit logs, data export and import, and relations reordering](https://github.com/strapi/documentation/pull/2475) +- [Add link to external guide about deploying Strapi on Azure](https://github.com/strapi/documentation/pull/2472) +- [Fix screenshot description in Cloud projects overview](https://github.com/strapi/documentation/pull/2471) + +#### Cloud +- [Fix various Cloud docs typos](https://github.com/strapi/documentation/pull/2476) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.2.0 + +
+### Updated content + +
+ +#### CMS +- [Rewrite Custom fields documentation as a feature page](https://github.com/strapi/documentation/pull/2469) +- [Add `files` to Strapi Client docs](https://github.com/strapi/documentation/pull/2463) + +#### Repository + +- [Move contribution link to secondary table of contents on larger viewports](https://github.com/strapi/documentation/pull/2460) +- [New tabs design](https://github.com/strapi/documentation/pull/2459) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Fix plugin init command](https://github.com/strapi/documentation/pull/2467) +- [Remove unused plugins files](https://github.com/strapi/documentation/pull/2462) +- [Update suggested npm production Dockerfile](https://github.com/strapi/documentation/pull/2458) + +#### Cloud +- [Add caution about custom domains and Strapi Cloud assets URLs](https://github.com/strapi/documentation/pull/2470) + +#### Repository +- [Fix identity cards design](https://github.com/strapi/documentation/pull/2461) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.1.0 + +
+### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [New design for features & plugins identity cards](https://github.com/strapi/documentation/pull/2456) +- [Fix issue #2378](https://github.com/strapi/documentation/pull/2454) +- [Update SSO badge style](https://github.com/strapi/documentation/pull/2453) +- [Add missing factory method in TypeScript development example](https://github.com/strapi/documentation/pull/2452) + +#### Repository +- [Fix `key` token color in code blocks](https://github.com/strapi/documentation/pull/2455) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + kasperjha + + + pwizla + +
+
+
+ +## 6.0.1 + +
+ +### Chore, fixes, typos, and other improvements + +
+ +#### CMS +- [Improve cors documentation](https://github.com/strapi/documentation/pull/2444) +- [fix broken link in preview.md](https://github.com/strapi/documentation/pull/2450) +- [Update step-by-step.md for Strapi 5 migration](https://github.com/strapi/documentation/pull/2449) +- [Add cross links for admin panel configuration and customization](https://github.com/strapi/documentation/pull/2447) +- [Unhide Testing page](https://github.com/strapi/documentation/pull/2446) + +#### Cloud +- [Adding a small note about Cloud sidegrade and display new ui](https://github.com/strapi/documentation/pull/2451) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 6.0.0 + +
+### New content + +
+ +#### CMS +- [Add Design System breaking changes summary](https://github.com/strapi/documentation/pull/2435) + +### Updated content + +
+ +#### CMS +- [Add custom logo doc in Admin Panel page + link in Admin Panel Customi…](https://github.com/strapi/documentation/pull/2439) +- [Preview: Side panel (stable, CMS) ](https://github.com/strapi/documentation/pull/2411) + +#### Cloud +- [Various Cloud docs updates](https://github.com/strapi/documentation/pull/2440) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Add support for dark mode to new homepage cards](https://github.com/strapi/documentation/pull/2442) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + meganelacheny + + + pwizla + +
+
+
+ + +## 6.0.0-beta.5 + +
+### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Fixes AI button blurry box shadow](https://github.com/strapi/documentation/pull/2426) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + HichamELBSI + +
+
+
+ + +## 6.0.0-beta.4 + +
+ +### Updated content + +
+ +#### CMS +- [Update Content Manager to mention editing relations on the fly](https://github.com/strapi/documentation/pull/2406) +- [Preview: Side panel](https://github.com/strapi/documentation/pull/2400) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [Improve homepage "Ask AI" button effect](https://github.com/strapi/documentation/pull/2424) +- [Third draft of iteration #1 for new homepage](https://github.com/strapi/documentation/pull/2422) +- [Second draft of iteration #1 for new homepage](https://github.com/strapi/documentation/pull/2420) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + pwizla + +
+
+
+ +## 6.0.0-beta.3 +
+ +### Updated content + +
+ +#### Strapi Cloud +- [New Cloud plans (CMS docs)](https://github.com/strapi/documentation/pull/2396) + +### Chore, fixes, typos, and other improvements + +
+ +#### Repository +- [First draft of Iteration #1 for new homepage](https://github.com/strapi/documentation/pull/2416) +- [Apply `` component where necessary](https://github.com/strapi/documentation/pull/2415) +- [Fix pagination_next values](https://github.com/strapi/documentation/pull/2414) +- [Mention lifecycle hooks blog article](https://github.com/strapi/documentation/pull/2413) +- [Mention blog article about lifecycle functions](https://github.com/strapi/documentation/pull/2412) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + kibwashere + + + pwizla + +
+
+
+ +## 6.0.0-beta.2 + +
+### Updated content + +
+ +#### CMS + +- [Add missing TypeScript pages](https://github.com/strapi/documentation/pull/2402) +- [Mention codemods on breaking changes pages](https://github.com/strapi/documentation/pull/2393) + +### Chore, fixes, typos, and other improvements + +
+ +#### CMS + +- [Remove integration guides](https://github.com/strapi/documentation/pull/2390) + +#### Repository +- [Mermaid fallback](https://github.com/strapi/documentation/pull/2403) +- [Update release notes script](https://github.com/strapi/documentation/pull/2395) +- [Add ExternalLink custom component](https://github.com/strapi/documentation/pull/2389) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + pwizla + +
+
+
+ +## 6.0.0-beta.1 + +
+ +Version 6.0.0 of Strapi Docs is the biggest rewrite of documentation to date!
This release includes: + +- _Merge of Dev Docs & User Guide_: You now have one documentation per Strapi product: CMS and Cloud. +- _New Features section & pages_: Everything feature-related is in the new “Features” section of the CMS doc's navigation and each feature is now fully documented in one page. +- _Simplified navigation_: Many users reported frustration because of the too many levels and inconsistent behaviours in the navigation—both issues have been fixed and the navigation design has been improved for better readability. +- _More visuals throughout the docs_: We're slowly adding new interactive demos in pages to offer another way to learn about Strapi. Check out [Admin Panel](/cms/features/admin-panel), [Content Manager](/cms/features/content-manager), and [Content-type Builder](/cms/features/content-type-builder) pages to try the demos! + +Feel free to [share your feedback](https://forms.gle/D1SXb8kYBVR7qijp6)! + +### New content + +
+ +#### CMS Docs +- [CMS folder reorganization](https://github.com/strapi/documentation/pull/2375) +- [New CMS documentation - More improvements & additions](https://github.com/strapi/documentation/pull/2359) +- [Proofread & improve CMS docs pages - pt. 2](https://github.com/strapi/documentation/pull/2369) +- [Proofread & improve CMS docs pages - pt. 1](https://github.com/strapi/documentation/pull/2350) +- [RBAC & SSO (Dev Docs) rework for CMS Docs](https://github.com/strapi/documentation/pull/2347) +- [New Features pages with User Guide content](https://github.com/strapi/documentation/pull/2288) +- [New Features pages with Dev Docs content](https://github.com/strapi/documentation/pull/2309) +- [CMS Docs (alpha)](https://github.com/strapi/documentation/pull/2340) + +### Chore, fixes, typos, and other improvements + +- [🎨 More design fixes for CMS Docs](https://github.com/strapi/documentation/pull/2366) +- [🎨 Design fixes for the new design](https://github.com/strapi/documentation/pull/2276) +- [🎨 New design](https://github.com/strapi/documentation/pull/2245) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + meganelacheny + + + pwizla + +
+
+
+ +## 5.8.0 + +
+### New content + +
+ +#### Repository +- [Add a guide on how to create components for plugins](https://github.com/strapi/documentation/pull/2433) + +### Updated content + +
+ +#### Cloud +- [Project settings: Variables page revamp (pt. 2)](https://github.com/strapi/documentation/pull/2425) + +#### Repository +- [Add use case for handling database migrations with TypeScript](https://github.com/strapi/documentation/pull/2432) +- [Add Email plugin ratelimiting configuration options](https://github.com/strapi/documentation/pull/2377) + +### Chore, fixes, typos, and other improvements + +
+ +#### Cloud +- [Add callout for downgrade/upgrade Cloud plans](https://github.com/strapi/documentation/pull/2428) + +#### Repository +- [Fix broken link to Strapi client README](https://github.com/strapi/documentation/pull/2436) +- [Fix missing location for content-type generation command in Store and Access Data (plugins dev) guide](https://github.com/strapi/documentation/pull/2434) +- [Fix Node versions in installation snippet](https://github.com/strapi/documentation/pull/2431) +- [Convert example in Store and Access Data guide from ES to DS](https://github.com/strapi/documentation/pull/2430) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 5.7.0 + +
+ +### Updated content + +
+ +#### Dev Docs & User Guide + +- [Preview: Side panel](https://github.com/strapi/documentation/pull/2410) + +#### User Guide + +- [Update Content Manager to mention editing relations on the fly](https://github.com/strapi/documentation/pull/2407) + +#### Strapi Cloud + +- [Strapi Cloud settings: Environment Variables revamp](https://github.com/strapi/documentation/pull/2419) + +### Chore, fixes, typos, and other improvements + +
+ +#### Strapi Cloud + +- [Use new Cloud plans screenshot](https://github.com/strapi/documentation/pull/2418) + +#### Repository + +- [Added disabled option for LiveEditor so that it does not steal focus - Closes issue #2409](https://github.com/strapi/documentation/pull/2423) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 5.6.3 + +
+ +### Updated content + +
+ +#### Dev Docs +- [Enhanced webhooks docs](https://github.com/strapi/documentation/pull/2391) + +#### Strapi Cloud +- [New Cloud plans](https://github.com/strapi/documentation/pull/2394) + +### Chore, fixes, typos, and other improvements + +
+ +#### Dev Docs +- [Fix descriptions for database parameters in CLI installation](https://github.com/strapi/documentation/pull/2404) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + Goldbee2 + + + kibwashere + + + ssganesh035 + +
+
+
+ +## 5.6.2 + +### Updated content + +#### Dev Docs + +- [Setting up local plugin in Strapi without the Plugin SDK](https://github.com/strapi/documentation/pull/2392) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + Bassel17 + +
+
+
+ +## 5.6.1 + +### Chore, fixes, typos, and other improvements + +#### Dev Docs +- [Update admin-panel-api.md](https://github.com/strapi/documentation/pull/2383) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + Rosalko + +
+
+
+ +## 5.6.0 + +### New content + +#### Dev Docs + +- [Strapi Client library](https://github.com/strapi/documentation/pull/2373) + +### Updated content + +#### Dev Docs + +- [Pregenerated API tokens](https://github.com/strapi/documentation/pull/2380) + +### Chore, fixes, typos, and other improvements + +#### Dev Docs + +- [Rename SDK to Client in files and diagrams](https://github.com/strapi/documentation/pull/2381) +- [Add missing TypeScript version to Admin Panel API code example](https://github.com/strapi/documentation/pull/2372) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + maccomaccomaccomacco + + + oktapodia + + + pwizla + +
+
+
+ +## 5.5.4 + +### Chore, fixes, typos, and other improvements + +#### Dev Docs +- [Update Doc Service API middleware example](https://github.com/strapi/documentation/pull/2368) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + Gkleinereva + +
+
+
+ +## 5.5.3 + +### Chore, fixes, typos, and other improvements + +#### Dev Docs +- [Fix incorrect import of unstable_useContentManagerContext in Helper-plugin migration reference](https://github.com/strapi/documentation/pull/2367) +- [Fix typo in v4 → v5 step-by-step for GraphQL plugin](https://github.com/strapi/documentation/pull/2360) +- [Fix bug in the middlewares example](https://github.com/strapi/documentation/pull/2358) +- [Fix populate examples for Document Service API](https://github.com/strapi/documentation/pull/2356) + +#### Strapi Cloud +- [Add last successful deployment’s date of the Production environment](https://github.com/strapi/documentation/pull/2361) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 5.5.2 + +
+ +### Chore, fixes, typos, and other improvements + +#### Dev Docs +- [Add graphQL landingPage configuration and update Apollo playground to sandbox](https://github.com/strapi/documentation/pull/2343) +- [Add the --verbose option to the data transfer command description](https://github.com/strapi/documentation/pull/2352) +- [Removing the note about unmodified fields on the update](https://github.com/strapi/documentation/pull/2351) +- [Fix typo in admonition](https://github.com/strapi/documentation/pull/2349) +- [Fix Document Service API example typo](https://github.com/strapi/documentation/pull/2348) + +#### Strapi Cloud +- [Update Cloud backups (restoration timestamp)](https://github.com/strapi/documentation/pull/2346) +- [Add the SSO badge for the new, paid add-on](https://github.com/strapi/documentation/pull/2341) +- [Update text for add environment button](https://github.com/strapi/documentation/pull/2299) + +#### Repository +- [Add Amplitude's browser SDK and web experiment for future A/B testing](https://github.com/strapi/documentation/pull/2345) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 5.5.1 + +
+ +### Chore, fixes, typos, and other improvements + +#### User Guide +- [Update User Guide intro. for stable new homepage](https://github.com/strapi/documentation/pull/2338) + +#### Dev Docs +- [Fix typo in react-router-dom-6.md](https://github.com/strapi/documentation/pull/2337) +- [Use yarn/npm tabs in Strapi CLI examples](https://github.com/strapi/documentation/pull/2332) + +#### Strapi Cloud +- [Remove account preferences section from cloud docs](https://github.com/strapi/documentation/pull/2333) + + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + giu1io + + + johannesscheiermann + + + pwizla + +
+
+
+ +## 5.5.0 + + The Strapi Docs website now has a brand new design! We hope you like it as much as we loved creating it. +Please feel free to [share your feedback](https://forms.gle/9NM8npMGoTkYetxGA). + +### Updated content + +#### User Guide +- [Mention new admin panel homepage and update screenshots](https://github.com/strapi/documentation/pull/2322) + +### Chore, fixes, typos, and other improvements + +#### Dev Docs +- [fix locale prerequisites](https://github.com/strapi/documentation/pull/2320) +- [fix wrong import](https://github.com/strapi/documentation/pull/2319) +- [Fix SDK plugin init command example in the SDK reference](https://github.com/strapi/documentation/pull/2318) +- [SDK beta callout](https://github.com/strapi/documentation/pull/2317) + +#### Strapi Cloud +- [Add section about importing env vars](https://github.com/strapi/documentation/pull/2326) +- [Adding notes about GitLab groups](https://github.com/strapi/documentation/pull/2323) + +#### Repository +- [Update docs content for Preview switching from beta to stable](https://github.com/strapi/documentation/pull/2325) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 5.4.0 + +
+ +### New content + +
+ +#### Repository +- [First iteration of Growth plan](https://github.com/strapi/documentation/pull/2303) + +### Chore, fixes, typos, and other improvements + +#### Dev Docs +- [Add a cross-link to the "commonly asked questions" about Strapi 5 article from the blog](https://github.com/strapi/documentation/pull/2313) +- [Add watchIgnoreFiles demo](https://github.com/strapi/documentation/pull/2312) +- [Fix unit testing docs for Strapi 5](https://github.com/strapi/documentation/pull/2308) +- [Mention Preview is under a feature flag](https://github.com/strapi/documentation/pull/2307) + +*** + +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ +## 5.3.0 + +
+ +### New content + +
+ +#### Dev Docs +- [Setting up the Preview feature](https://github.com/strapi/documentation/pull/2295) + +#### User Guide +- [Previewing content in the Content Manager](https://github.com/strapi/documentation/pull/2295) + +### Updated content + +
+ +#### Strapi Cloud +- [Rename a project](https://github.com/strapi/documentation/pull/2300) + +### Chore, fixes, typos, and other improvements + +
+ +#### Dev Docs +- [Update cross-link to U&P plugin from dev docs routes documentation](https://github.com/strapi/documentation/pull/2305) + +#### Strapi Cloud +- [Update Cloud plans screenshot](https://github.com/strapi/documentation/pull/2304) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + AtallahFatma + + + meganelacheny + + + pwizla + +
+
+
+ +## 5.2.2 + +
+ +### Chore, fixes, typos, and other improvements + +#### Dev Docs + +- [Collapse prerequisites and display step 1 in Quick Start Guide](https://github.com/strapi/documentation/pull/2296) + +#### Strapi Cloud +- [Design system v2 and new header in cloud docs](https://github.com/strapi/documentation/pull/2298) +- [Deleted old cloud assets](https://github.com/strapi/documentation/pull/2297) +- [Add restoration timestamp to docs and ressources](https://github.com/strapi/documentation/pull/2292) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 +
+ + giu1io + + + olegStrapier + + + pierreburgy + +
+
+
+ + +## 5.2.1 + +
+ +### Updated content + +- [Add `strapi cloud environment link` to Cloud CLI](https://github.com/strapi/documentation/pull/2282) +- [Add new Cloud regions](https://github.com/strapi/documentation/pull/2290) + +### Chore, fixes, typos, and other improvements + +#### Dev Docs +- [Add useTypescriptMigrations](https://github.com/strapi/documentation/pull/2283) +- [Fix typo in retro-compatibility flag value](https://github.com/strapi/documentation/pull/2294) +- [Fix typo in example code for injectComponent in Admin Panel API docs ](https://github.com/strapi/documentation/pull/2287) +- [Fix outdated mention of Gold plan in SSO docs](https://github.com/strapi/documentation/pull/2286) +- [Fix locale param. example in Interactive Query Builder](https://github.com/strapi/documentation/pull/2285) +- [Fix discardDraft() Document Service API example](https://github.com/strapi/documentation/pull/2284) + +#### Strapi Cloud +- [Update credit cards handling](https://github.com/strapi/documentation/pull/2262) + +#### Repository +- [Add release notes script](https://github.com/strapi/documentation/pull/2289) + +*** +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+
+ + +## 5.2.0 + +
+ +### New content + +
+ +#### Dev Docs + +- [Add WIP API Reference and Guides for TypeScript](https://github.com/strapi/documentation/pull/2266) + +### Updated content + +
+ +#### Dev Docs + +- [Add Knex Config function support](https://github.com/strapi/documentation/pull/2252) + +#### User Guide + +- [Integration between the Releases and Review Workflows features](https://github.com/strapi/documentation/pull/2273) + +### Chore, fixes, typos, and other improvements + +
+ +#### Cloud + +- [Minor Cloud Docs changes](https://github.com/strapi/documentation/pull/2264) +- [Remove Strapi 5 warning for Cloud in FAQ](https://github.com/strapi/documentation/pull/2272) +- [Move custom cloud provider config warnings higher](https://github.com/strapi/documentation/pull/2278) + +#### Dev Docs + +- [Fix example request for update method in Document Service API](https://github.com/strapi/documentation/pull/2275) + +#### Repo + +- [Align navbar search box with 100% width](https://github.com/strapi/documentation/pull/2280) + +*** + +This release was made possible thanks to the following contributors. Thank you! 🫶 + + + +
+
+ +## 5.1.3 + +
+ +### Chore, fixes, typos, and other improvements + +- [Improve instructions for upgrading to Apollo v4](https://github.com/strapi/documentation/pull/2271) +- [Fix code example in breaking change for new response format](https://github.com/strapi/documentation/pull/2270) +- [Update names of removed mutations in GraphQL breaking change](https://github.com/strapi/documentation/pull/2269) +- [Fix typo in a snippet used in Cloud docs](https://github.com/strapi/documentation/pull/2268) + +*** + +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+ + laurenskling + + + xxtf1z + +
+ +
+
+ +## 5.1.2 + +
+ +### Updated content + +
+ +#### Dev Docs + +- [Add support for 'latest' parameter in the upgrade tool](https://github.com/strapi/documentation/pull/2259) +- [Add example code and resulting screenshot for theme extension](https://github.com/strapi/documentation/pull/2261) + +### Chore, fixes, typos, and other improvements + +#### Strapi Cloud + +- [Update cloud deployment logs screen](https://github.com/strapi/documentation/pull/2263) +- [Update confirmation modal text in Cloud Update Repository](https://github.com/strapi/documentation/pull/2258) + +#### Repository + +- [Restore bigger font-size for categories title in sidebar](https://github.com/strapi/documentation/pull/2260) + +*** + +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+ + Convly + + + giu1io + + + pwizla + + +
+ +
+
+ +## 5.1.1 + +
+ +### Updated content + +
+ +#### Strapi Cloud + +* [List environments with Cloud CLI](https://github.com/strapi/documentation/pull/2239) + +#### Dev Docs + +* [`publicationAt` breaking change](https://github.com/strapi/documentation/pull/2249) + +### Chore, fixes, typos, and other improvements + +#### Strapi Cloud + +* [Update wording on purchasable extra Seats](https://github.com/strapi/documentation/pull/2238) + +#### Dev Docs + +* [Clarify sorting for relational fields in the Content Manager list view](https://github.com/strapi/documentation/pull/2224) +* [Fix typo for `v4CompatibilityMode` flag](https://github.com/strapi/documentation/pull/2257) +* [Fix step-by-step v4 → v5 migration (v4CompatibilityMode flag)](https://github.com/strapi/documentation/pull/2255) +* [Update environment declaration in Docker guide](https://github.com/strapi/documentation/pull/2253) +* [Fix createStrapi method in TypeScript development documentation](https://github.com/strapi/documentation/pull/2248) +* [Fix links in the REST API documentation](https://github.com/strapi/documentation/pull/2247) +* [Fix CheckPagePermissions code example in helper-plugin deprecation guide](https://github.com/strapi/documentation/pull/2244) +* [Fix typo for init command in Plugin SDK](https://github.com/strapi/documentation/pull/2243) +* [Add link to ms package for examples for JWT expiresIn](https://github.com/strapi/documentation/pull/2242) + +#### Repository + +* [Update LICENSE](https://github.com/strapi/documentation/pull/2251) + + +*** + +This release was made possible thanks to the following contributors. Thank you! 🫶 + + + +
+
+ +## 5.1.0 + +
+ +### New content + +
+ +#### Cloud Docs + +* [Multi-Environments](https://github.com/strapi/documentation/pull/2229) + +### Updated content + +
+ +#### User Guide + +* [Mention Blocked status for Releases](https://github.com/strapi/documentation/pull/2235) + +#### Dev Docs + +* [Clarify helper-plugin migration guide](https://github.com/strapi/documentation/pull/2230) + +### Chore, fixes, typos, and other improvements + +
+ +#### Dev Docs + +* [Fix creating a custom provider example](https://github.com/strapi/documentation/pull/2237) +* [Fix pagination_next for first page of categories](https://github.com/strapi/documentation/pull/2234) +* [Fix SEO issues](https://github.com/strapi/documentation/pull/2233) +* [Fix links to strapi codebase](https://github.com/strapi/documentation/pull/2226) +* [Fix code example in general deployment guidelines](https://github.com/strapi/documentation/pull/2231) +* [Fix grammar in TypeScript development docs](https://github.com/strapi/documentation/pull/2232) + +*** + +This release was made possible thanks to the following contributors. Thank you! 🫶 + +
+ + + ChristopheCVB + + + imcarlosguerrero + + + stefanhuber + + + butcherZ + + + jhoward1994 + + + meganelacheny + + + pwizla + + +
+ +
+
+ +## 5.0.0 + +_The following is an extensive list of all the pull requests that were merged since we started working on Strapi 5 documentation. For a quicker tour, please refer to the [What's new page](/whats-new)._ + +### New content + +
+ +#### Dev Docs + +* [Breaking change for database columns](https://github.com/strapi/documentation/pull/2221) +* [Content Manager APIs](https://github.com/strapi/documentation/pull/2220) +* [Breaking change for removing the "shared population strategy" for components & dynamic zones](https://github.com/strapi/documentation/pull/2204) +* [Templates](https://github.com/strapi/documentation/pull/2192) +* [Upgrade section revamp](https://github.com/strapi/documentation/pull/2153) +* [Custom U&P providers](https://github.com/strapi/documentation/pull/2138) +* [Breaking change for server.proxy config](https://github.com/strapi/documentation/pull/2131) +* [New "Upgrades" section (replaces updates & migration) for Strapi 5](https://github.com/strapi/documentation/pull/2126) +* [New proxy configuration feature](https://github.com/strapi/documentation/pull/2124) +* [lockIcon → licenseOnly breaking change](https://github.com/strapi/documentation/pull/2123) +* [Breaking change for default input validation](https://github.com/strapi/documentation/pull/2096) +* [Entity Service → Document Service: Breaking change + migration reference](https://github.com/strapi/documentation/pull/2093) +* [Plugins migration summary](https://github.com/strapi/documentation/pull/2089) +* [Breaking change for better-sqlite3](https://github.com/strapi/documentation/pull/2083) +* [Breaking change for Admin RBAC updates](https://github.com/strapi/documentation/pull/2082) +* [Breaking change for model config path uses uid](https://github.com/strapi/documentation/pull/2055) +* [Breaking change for upgrade from apollo v3 to apollo v4](https://github.com/strapi/documentation/pull/2053) +* [Breaking change for removed `localizations` field](https://github.com/strapi/documentation/pull/2050) +* [Breaking change for server log level configuration](https://github.com/strapi/documentation/pull/2049) +* [Breaking change for the removed webpack aliases](https://github.com/strapi/documentation/pull/2047) +* [Breaking change for strict requirements on configuration filenames](https://github.com/strapi/documentation/pull/2009) +* [Breaking change about removed support for some env-only options](https://github.com/strapi/documentation/pull/2007) +* [Breaking change for no findPage() method in Document Service API](https://github.com/strapi/documentation/pull/2006) +* [Breaking change for sorting by id](https://github.com/strapi/documentation/pull/1999) +* [Breaking change for Vite as default bundler](https://github.com/strapi/documentation/pull/1998) +* [Breaking change for U&P register.allowedFields](https://github.com/strapi/documentation/pull/1997) +* [Breaking change for CM redux store](https://github.com/strapi/documentation/pull/1995) +* [Breaking change for `strapi.container`](https://github.com/strapi/documentation/pull/1994) +* [Breaking change for i18n CM locale parameter](https://github.com/strapi/documentation/pull/1991) +* [Breaking change for strapi exports](https://github.com/strapi/documentation/pull/1989) +* [Breaking change for removal of `isSupportedImage`](https://github.com/strapi/documentation/pull/1988) +* [Breaking change about react-router-dom 6](https://github.com/strapi/documentation/pull/1987) +* [Upgrade tool](https://github.com/strapi/documentation/pull/1945) +* [Document Service](https://github.com/strapi/documentation/pull/1935) +* [Breaking change for fetch](https://github.com/strapi/documentation/pull/1915) +* [Breaking change for MySQL v5 support drop](https://github.com/strapi/documentation/pull/1892) +* [Init. breaking changes pages for Strapi v4 → v5 migration](https://github.com/strapi/documentation/pull/1896) +* [New v5 Dev Docs structure](https://github.com/strapi/documentation/pull/1811) + +#### User Guide + +* [Updated screenshots & last updates in User Guide](https://github.com/strapi/documentation/pull/2207) +* [Releases settings](https://github.com/strapi/documentation/pull/2120) + +#### Cloud Docs + +* [Port existing Cloud docs content from v4 website to website](https://github.com/strapi/documentation/pull/2154) +* [Make main categories clickable in breadcrumbs](https://github.com/strapi/documentation/pull/2198) + +#### Global + +* [AI widget](https://github.com/strapi/documentation/pull/1898) +* [Tagging system](https://github.com/strapi/documentation/pull/2076) +* [New homepage](https://github.com/strapi/documentation/pull/2087) + +### Updated content + +
+ +#### Dev Docs + +* [Remove shared population strategy for dynamic zones](https://github.com/strapi/documentation/pull/2222) +* [Update breaking change for default server level log](https://github.com/strapi/documentation/pull/2216) +* [Update breaking change for reserved attributes and content-types names](https://github.com/strapi/documentation/pull/2215) +* [Update breaking change for `is-supported-image`](https://github.com/strapi/documentation/pull/2214) +* [Update codemods list](https://github.com/strapi/documentation/pull/2212) +* [Update some v5 migration and Plugin SDK docs](https://github.com/strapi/documentation/pull/2210) +* [Add more before examples for helper plugin migration](https://github.com/strapi/documentation/pull/2209) +* [Plugin migration updates](https://github.com/strapi/documentation/pull/2208) +* [Update the Quick Start Guide with Cloud CLI and new CLI prompts](https://github.com/strapi/documentation/pull/2203) +* [Update sdk-plugin init with new options](https://github.com/strapi/documentation/pull/2202) +* [Update helper plugin migration doc](https://github.com/strapi/documentation/pull/2200) +* [Update backend customization examples to Document Service API](https://github.com/strapi/documentation/pull/2196) +* [Add scope and warning details to the upgrade tool guide](https://github.com/strapi/documentation/pull/2195) +* [More examples for middlewares context to Document Service API](https://github.com/strapi/documentation/pull/2189) +* [Deprecate integration guides](https://github.com/strapi/documentation/pull/2173) +* [Transfer deployment guides to external resources](https://github.com/strapi/documentation/pull/2172) +* [Database lifecycles vs. Document Service middlewares](https://github.com/strapi/documentation/pull/2170) +* [Admin panel customization section rework](https://github.com/strapi/documentation/pull/2162) +* [Update REST API additional resources with new links and call to write](https://github.com/strapi/documentation/pull/2148) +* [Updates to the CLI installation guide](https://github.com/strapi/documentation/pull/2121) +* [FAQ section for 'Cannot find module @strapi/XXX' build error](https://github.com/strapi/documentation/pull/2116) +* [Update upgrade tool documentation with codemods updates](https://github.com/strapi/documentation/pull/2112) +* [Plugin CLI update for @strapi/sdk-plugin package](https://github.com/strapi/documentation/pull/2109) +* [Updates to relations in API docs](https://github.com/strapi/documentation/pull/2100) +* [Update doc service doc to match latest changes being prepared](https://github.com/strapi/documentation/pull/2074) +* [GraphQL updates](https://github.com/strapi/documentation/pull/2051) +* [REST API updates (incl. i18n and breaking changes)](https://github.com/strapi/documentation/pull/2038) +* [(no-)watch-admin and bundler updates](https://github.com/strapi/documentation/pull/2037) +* [Turn the TypeScript page into a section](https://github.com/strapi/documentation/pull/1913) +* [New Dev Docs introduction](https://github.com/strapi/documentation/pull/1911) +* [Update supported databases](https://github.com/strapi/documentation/pull/1887) + +#### User Guide + +* [Make main categories clickable in breadcrumbs](https://github.com/strapi/documentation/pull/2197) +* [Update whole content in User Guide](https://github.com/strapi/documentation/pull/2193) +* [Update Draft & Publish](https://github.com/strapi/documentation/pull/2027) + +#### Cloud Docs + +* [Make main categories clickable in breadcrumbs](https://github.com/strapi/documentation/pull/2198) + +### Chore, fixes, typos, and other improvements + +* [AI bot improvements](https://github.com/strapi/documentation/pull/2142) + +*** + +This release was made possible thanks to the following contributors. Thank you! 🫶 + + + +
diff --git a/docusaurus/docs/release-notes.md b/docusaurus/docs/release-notes.md index 95f1be6228..ec87bfb242 100644 --- a/docusaurus/docs/release-notes.md +++ b/docusaurus/docs/release-notes.md @@ -31,3500 +31,8 @@ New versions (minor or patch) are generally released weekly, on Wednesdays. _Reminder: Version numbers on this page are for the Strapi Docs package. The latest Strapi CMS version is [5.48.1](https://github.com/strapi/strapi/releases/tag/v5.48.1)._ -## 6.28.0 - -
-### New content - -
- -#### Repository -- [Document the Billing portal page and update tax guidance for Canada and India](https://github.com/strapi/documentation/pull/3239) -- [Add "Inki" Claude Code plugin: research, write, review, submit Strapi Docs update](https://github.com/strapi/documentation/pull/3200) - -### Updated content - -
- -#### CMS -- [Document paginated upload files endpoint in the REST API](https://github.com/strapi/documentation/pull/3261) -- [Document documentId support in Users & Permissions relation updates](https://github.com/strapi/documentation/pull/3252) -- [Cms/document factory controller overrides](https://github.com/strapi/documentation/pull/3228) -- [Document the upgrade to command for targeting a specific version](https://github.com/strapi/documentation/pull/3222) -- [Document --install-deps and --no-install-deps CLI flags](https://github.com/strapi/documentation/pull/3221) - -#### Cloud -- [Cloud logs revamp](https://github.com/strapi/documentation/pull/3253) - -#### Repository -- [Document Strapi Cloud upload size limits](https://github.com/strapi/documentation/pull/3231) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Normalize Cloud configuration paths](https://github.com/strapi/documentation/pull/3250) -- [Update parameter name from 'id' to 'documentId'](https://github.com/strapi/documentation/pull/3236) -- [Clarify dynamic zone fragment populate syntax](https://github.com/strapi/documentation/pull/3233) -- [Fix `delete()` row description in REST client API reference](https://github.com/strapi/documentation/pull/3226) -- [Fix `count()` description and remove stray backtick in Document Service API](https://github.com/strapi/documentation/pull/3225) - -#### Repository -- [Rename Inki autonomy flag to `--non-interactive`](https://github.com/strapi/documentation/pull/3257) -- [Detect emphasis, button-icon, and admonition conventions in Inki style review](https://github.com/strapi/documentation/pull/3256) -- [Require Inki orchestrators to invoke sub-skills and bump to 0.2.1](https://github.com/strapi/documentation/pull/3255) -- [Detect title/content scope mismatch and inbound links in Inki review](https://github.com/strapi/documentation/pull/3244) -- [Add Cloud Advanced page type and template to Inki outline-checker](https://github.com/strapi/documentation/pull/3243) -- [Detect em dash HTML entities in Inki style-lint](https://github.com/strapi/documentation/pull/3242) -- [Inki v0.2: end-to-end document workflow, review agents, run logging, and authoring tooling](https://github.com/strapi/documentation/pull/3234) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - - - -## 6.27.0 - -
-### New content - -
- -#### CMS -- [Strapi MCP server for content management](https://github.com/strapi/documentation/pull/3194) - -### Updated content - -
- -- [Update Users & Permissions documentation](https://github.com/strapi/documentation/pull/3169) -- [Add deleteMany method documentation to Document Service API](https://github.com/strapi/documentation/pull/3206) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Document optional admin JWT secret for API-only deployments](https://github.com/strapi/documentation/pull/3218) -- [Fix Marketplace custom fields links in CMS feature docs](https://github.com/strapi/documentation/pull/3210) -- [Add v5 to v4 rollback FAQ entry to migration documentation](https://github.com/strapi/documentation/pull/3202) - -#### Repository -- [Make Notion logging idempotent by date for docs self-healing](https://github.com/strapi/documentation/pull/3217) -- [Fix self-healing metrics: track Doc PR fate retroactively](https://github.com/strapi/documentation/pull/3216) -- [Move the MCP server Plugin API reference to plugins-development](https://github.com/strapi/documentation/pull/3214) -- [Ignore local superpowers artifacts in .gitignore](https://github.com/strapi/documentation/pull/3198) -- [Add Need help admonition with support link on CMS and Cloud intros](https://github.com/strapi/documentation/pull/3197) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - andrii-bodnar - - - pwizla - - - singhvishalkr - -
-
-
- - - - -## 6.26.0 - -
-### New content - -
- -#### Cloud -- [Add middleware customization guide for Strapi Cloud production environment](https://github.com/strapi/documentation/pull/3148) - -### Updated content - -
- -#### CMS -- [Document nested sort within populate for join-table relations](https://github.com/strapi/documentation/pull/3186) -- [Update Docker documentation with production setup and troubleshooting](https://github.com/strapi/documentation/pull/3109) - -#### Cloud -- [Environment clearing for Strapi Cloud](https://github.com/strapi/documentation/pull/3180) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add TypeScript workaround for Document Service relational operators](https://github.com/strapi/documentation/pull/3189) -- [Replace unimplemented GraphQL aggregations docs with warning](https://github.com/strapi/documentation/pull/3183) -- [Add tip about filtering by assignee and review stage in list view](https://github.com/strapi/documentation/pull/3170) - -#### Repository -- [Prevent editors from running Prettier](https://github.com/strapi/documentation/pull/3182) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - - - -## 6.25.0 - -
-### Updated content - -
- -#### CMS -- [Document admin translation contribution path in FAQ](https://github.com/strapi/documentation/pull/3165) -- [Explain middleware on every core route for one content-type](https://github.com/strapi/documentation/pull/3152) -- [Document Content Manager Edit View context hook on Admin Panel API page](https://github.com/strapi/documentation/pull/3146) -- [Document `tsconfig` setup for local TypeScript plugins](https://github.com/strapi/documentation/pull/3121) -- [Add `addRichTextBlocks` to Content Manager API documentation](https://github.com/strapi/documentation/pull/3100) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Update sendmail provider description after Nodemailer switch](https://github.com/strapi/documentation/pull/3164) -- [Update live preview to include support for media](https://github.com/strapi/documentation/pull/3158) -- [Distinguish admin extensions from server plugin overrides](https://github.com/strapi/documentation/pull/3155) -- [Document `__component` for dynamic zones on REST create](https://github.com/strapi/documentation/pull/3153) -- [Document React admin dependencies for v4 upgrades](https://github.com/strapi/documentation/pull/3151) -- [Document dynamic zone __component in REST update section](https://github.com/strapi/documentation/pull/3150) -- [Align public middleware example with maxAge configuration](https://github.com/strapi/documentation/pull/3149) -- [Document locale parameter for Entity Service CRUD](https://github.com/strapi/documentation/pull/3147) -- [Note that REST filter examples need populate to surface traversed relations](https://github.com/strapi/documentation/pull/3144) -- [Document ADMIN_PATH and STRAPI_ADMIN_BACKEND_URL environment variables](https://github.com/strapi/documentation/pull/3143) -- [Document AWS RDS IAM auth with short-lived tokens](https://github.com/strapi/documentation/pull/3141) -- [Document concurrentUploadSize upload plugin option](https://github.com/strapi/documentation/pull/3138) -- [Update pnpm mention to warn about Strapi Cloud compatibility](https://github.com/strapi/documentation/pull/3135) -- [Clarify nested component required metadata gap in OpenAPI guide](https://github.com/strapi/documentation/pull/3128) - -#### Repository -- [Add conditional retrieval budgets and drafting guardrails to agent prompts](https://github.com/strapi/documentation/pull/3167) -- [Track ask_user router decisions in Notion metrics for docs self-healing system](https://github.com/strapi/documentation/pull/3166) -- [Add native Kapa dark mode support](https://github.com/strapi/documentation/pull/3159) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - - - -## 6.24.0 - -
-### New content - -
- -#### CMS -- [Document the `/users` endpoints](https://github.com/strapi/documentation/pull/3027) -- [Admin tokens](https://github.com/strapi/documentation/pull/2992) - -### Updated content - -
- -#### CMS -- [Clarify TypeScript Jest entrypoint for harness](https://github.com/strapi/documentation/pull/3125) -- [Add install step after clone in test-locally walkthrough for Data Transfer](https://github.com/strapi/documentation/pull/3122) -- [Add sharp configuration details for Media Library](https://github.com/strapi/documentation/pull/3102) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Align Document Service note with connect payloads](https://github.com/strapi/documentation/pull/3129) -- [Note that internal entity-validator is not public API](https://github.com/strapi/documentation/pull/3120) -- [Add missing Draft & Publish availability note to methods overview](https://github.com/strapi/documentation/pull/3119) -- [Add sanitization warning to Document Service API page](https://github.com/strapi/documentation/pull/3114) -- [Mention sorting by publish status in Content Manager List View](https://github.com/strapi/documentation/pull/3113) -- [Document polymorphic relations support in Document Service API populate](https://github.com/strapi/documentation/pull/3112) -- [Update plugin Component examples to use non-deprecated import pattern](https://github.com/strapi/documentation/pull/3111) -- [Fix OpenAPI example id type to string](https://github.com/strapi/documentation/pull/3107) -- [Document Deploy widget on homepage](https://github.com/strapi/documentation/pull/3106) - -#### Repository -- [Widen self-healing deduplication to scan all doc PRs](https://github.com/strapi/documentation/pull/3116) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - - - -## 6.23.0 - -
-### New content - -
- -#### CMS -- [Add recap pages for AI features](https://github.com/strapi/documentation/pull/3091) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add a tip to AI for devs page to cross-link agents.md files](https://github.com/strapi/documentation/pull/3104) -- [Update database transactions page to use Document Service API](https://github.com/strapi/documentation/pull/3097) -- [Document populate support in Document Service API `delete()` operations](https://github.com/strapi/documentation/pull/3094) -- [Add note about Vite `.mts` ESM syntax support](https://github.com/strapi/documentation/pull/3080) - -#### Cloud -- [Reactivate the subscription flow for Strapi Cloud](https://github.com/strapi/documentation/pull/3101) - -#### Repository -- [Docs self-healing workflow improvements: Split Notion rejection metrics into Triage and Router](https://github.com/strapi/documentation/pull/3095) -- [Add Notion metrics logging for self-healing runs](https://github.com/strapi/documentation/pull/3079) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - mariekirsch - - - pwizla - -
-
-
- - - - -## 6.22.0 - -
-### New - -
- -#### CMS -- [Document responseType option for useFetchClient in plugins](https://github.com/strapi/documentation/pull/3081) - -#### Repo -- [Add docs self-healing workflow](https://github.com/strapi/documentation/pull/3059) - -### Updated content - -
- -#### CMS -- [Add admin user management CLI commands + group CLI commands by category](https://github.com/strapi/documentation/pull/3061) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Document transfer checksum verification and asset idle timeout](https://github.com/strapi/documentation/pull/3077) -- [Mention improved transfer CLI progress display](https://github.com/strapi/documentation/pull/3076) -- [Document unique username generation for auth provider registration](https://github.com/strapi/documentation/pull/3075) -- [Document AWS S3 credential format with deprecation notice](https://github.com/strapi/documentation/pull/3068) -- [Document signed URL behavior for S3 private buckets](https://github.com/strapi/documentation/pull/3067) -- [Cross-link best practices for high-performance Strapi blog post](https://github.com/strapi/documentation/pull/3060) -- [Remove yarn from main pages](https://github.com/strapi/documentation/pull/3042) - -#### Repository -- [Fix auto-labeling: infra-only PRs always labeled as chore](https://github.com/strapi/documentation/pull/3085) -- [Docs self-healing workflow improvements: Auto-ignore rejected PRs for future runs](https://github.com/strapi/documentation/pull/3084) -- [Docs self-healing workflow improvements: Add dry run mode](https://github.com/strapi/documentation/pull/3082) -- [Docs self-healing workflow improvements: Exclude translations, bots, dependency upgrades](https://github.com/strapi/documentation/pull/3078) -- [Docs self-healing workflow improvements: Add Slack notification](https://github.com/strapi/documentation/pull/3072) -- [Docs self-healing workflow improvements: Add ignore list](https://github.com/strapi/documentation/pull/3070) -- [Docs self-healing workflow improvements: Skip `flag: documentation` PRs and run Tue-Sat only](https://github.com/strapi/documentation/pull/3066) -- [Docs self-healing workflow improvements: Add ultra-light Haiku triage before Router](https://github.com/strapi/documentation/pull/3065) -- [Docs self-healing workflow improvements: Split into Haiku Router + Sonnet Drafter](https://github.com/strapi/documentation/pull/3064) -- [Docs self-healing workflow improvements: Pre-filter PRs before Claude](https://github.com/strapi/documentation/pull/3062) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - cache-your-dreams - - - pwizla - -
-
-
- - - - -## 6.21.0 - -
-### New content - -
- -#### CMS -- [Document `@strapi/utils`](https://github.com/strapi/documentation/pull/3032) - -#### Repository -- [Add directory export/import instructions for the Data Management feature](https://github.com/strapi/documentation/pull/3043) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Clarify S3 URL construction priority for compatible providers](https://github.com/strapi/documentation/pull/3055) -- [Clarify populate and pagination combination](https://github.com/strapi/documentation/pull/3048) -- [Add FAQ entry about disabling foreign key creation in databases](https://github.com/strapi/documentation/pull/3047) -- [Use lockfile-based installs and document alternative base image for Docker](https://github.com/strapi/documentation/pull/3046) -- [Add supported browsers for Strapi Admin in Quick Start Guide prerequisites](https://github.com/strapi/documentation/pull/3045) -- [Preserve relations in fill from another locale feature](https://github.com/strapi/documentation/pull/3041) -- [Add openapi.json route documentation (#2143) (#2159)](https://github.com/strapi/documentation/pull/2759) - -#### Repository -- [Expand config abbreviations in agent prompts and authoring guides](https://github.com/strapi/documentation/pull/3057) -- [Merge AGENTS.md and CLAUDE.md](https://github.com/strapi/documentation/pull/3044) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - - - -## 6.20.0 - -
-### New content - -
- -#### Repository -- [Add CLAUDE.MD](https://github.com/strapi/documentation/pull/3033) -- [Add Integrity Checker](https://github.com/strapi/documentation/pull/3031) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix Dockerfile by adjusting WORKDIR in production dockerfile](https://github.com/strapi/documentation/pull/3036) -- [Review workflows stage to permissions](https://github.com/strapi/documentation/pull/3024) - -#### Cloud -- [One time password update](https://github.com/strapi/documentation/pull/3037) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - - - -## 6.19.0 - -
-### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [fix: export includes 3rd party providers assets](https://github.com/strapi/documentation/pull/3022) -- [Add tips for List View and Edit View usage of `documentId` in Content Manager](https://github.com/strapi/documentation/pull/3021) - -#### Repository -- [Allow agents to do a single round of self-check after PR creation](https://github.com/strapi/documentation/pull/3019) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - nclsndr - - - pwizla - -
-
-
- - - - -## 6.18.1 - -
-### Updated content - -
- -#### CMS -- [Refresh the Quick Start Guide](https://github.com/strapi/documentation/pull/3017) -- [Add more information about the `arrayLimit` parameter from the `strapi::query` middleware](https://github.com/strapi/documentation/pull/3010) -- [Improve the admin panel extension page](https://github.com/strapi/documentation/pull/3003) - -#### Cloud -- [VAT handling on Strapi Cloud](https://github.com/strapi/documentation/pull/3011) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Extend warning about data loss when using DTS import](https://github.com/strapi/documentation/pull/3005) -- [Fix plugins extension page](https://github.com/strapi/documentation/pull/3000) - -#### Cloud -- [Downgrading with an organization repository](https://github.com/strapi/documentation/pull/3009) -- [Update project creation page](https://github.com/strapi/documentation/pull/3008) -- [Update deletion reasons](https://github.com/strapi/documentation/pull/3007) - -#### Repository -- [Ensure the Style Checker spots em dashes](https://github.com/strapi/documentation/pull/3002) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - innerdvations - - - mariekirsch - - - pwizla - -
-
-
- - -## 6.18.0 - -
-### New content - -
- -#### CMS -- [Fully rework and expand the server API part of the plugins development documentation](https://github.com/strapi/documentation/pull/2991) -- [Fully rework and expand the admin panel API part of the plugins development documentation](https://github.com/strapi/documentation/pull/2920) - -### Updated content - -
- -#### CMS -- [Document list view filters for Draft & Publish](https://github.com/strapi/documentation/pull/2998) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix some inconsistencies between docs and codebase for Server API](https://github.com/strapi/documentation/pull/2996) -- [Fix middleware file path in upload documentation](https://github.com/strapi/documentation/pull/2993) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - evrys - - - maccomaccomaccomacco - - - pwizla - -
-
-
- - - - -## 6.17.1 - -
-### New content - -
- -#### Repository -- [Add Outline generator and Drafter tools](https://github.com/strapi/documentation/pull/2947) - -### Updated content - -
- -#### CMS -- [Expand Email documentation with Nodemailer v8 options](https://github.com/strapi/documentation/pull/2988) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add relation open modal setting for content-manager configure the view](https://github.com/strapi/documentation/pull/2986) - -#### Repository -- [Improve Drafter instructions: avoid em dashes, add code highlights](https://github.com/strapi/documentation/pull/2989) -- [Ensure the Outline UX Analyzer tool is included in auto-chain mode](https://github.com/strapi/documentation/pull/2985) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - markkaylor - - - pwizla - -
-
-
- - -## 6.17.0 - -
-### New content - -
- -#### Repository -- [Add auto-chain mode to Docs AI creation/review tools](https://github.com/strapi/documentation/pull/2980) -- [Add Cursor rules and refine core project instructions](https://github.com/strapi/documentation/pull/2978) - -### Updated content - -
- -#### CMS -- [Add `strictParams` and custom Content API parameters](https://github.com/strapi/documentation/pull/2974) -- [Improve REST API population page UX](https://github.com/strapi/documentation/pull/2971) -- [SDK plugin v6](https://github.com/strapi/documentation/pull/2919) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix inconsistent database requirements](https://github.com/strapi/documentation/pull/2976) -- [Update example request URL in REST API documentation](https://github.com/strapi/documentation/pull/2972) - -#### Repository -- [Update Cursor rules to include auto-chain mode](https://github.com/strapi/documentation/pull/2981) -- [Fix bug in Strapi CMS release notes link generation](https://github.com/strapi/documentation/pull/2970) -- [Fix auto-labelling of PRs by source and content-type](https://github.com/strapi/documentation/pull/2969) -- [Fix branch naming rules](https://github.com/strapi/documentation/pull/2967) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.16.1 - -
-### Updated content - -
- -#### CMS -- [Update docs with persistent list view settings for the Content Manager](https://github.com/strapi/documentation/pull/2959) -- [Add extended AWS S3 provider configuration](https://github.com/strapi/documentation/pull/2949) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add `.strapi/` folder to "fix build issues with the generated types" TypeScript code example](https://github.com/strapi/documentation/pull/2963) -- [Add `--non-interactive` and `--enable-ab-tests` flags for CLI installation](https://github.com/strapi/documentation/pull/2957) -- [Update findOne method to use new document structure](https://github.com/strapi/documentation/pull/2950) -- [Update locale.md (POST requests)](https://github.com/strapi/documentation/pull/2948) -- [Add new `--no-build-admin` parameter for `strapi-develop` CLI](https://github.com/strapi/documentation/pull/2946) - -#### Repository -- [Add instructions for URLs validation to Router tool](https://github.com/strapi/documentation/pull/2960) -- [Improve Router output (tables, instructions for pipeline)](https://github.com/strapi/documentation/pull/2956) -- [Improve Drafter tool for API pages](https://github.com/strapi/documentation/pull/2955) -- [Clarify CMS vs. Docs version numbers in release notes](https://github.com/strapi/documentation/pull/2954) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - Bellian - - - bart-webleads - - - pwizla - -
-
-
- -
- - -## 6.16.0 - -
-### New content - -
- -#### Repository -- [Add Router documentation tool](https://github.com/strapi/documentation/pull/2933) -- [Add Outliner tools for PR reviews](https://github.com/strapi/documentation/pull/2932) - -### Updated content - -
- -#### CMS -- [Fix outdated `strapi develop` parameter docs](https://github.com/strapi/documentation/pull/2938) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add direct links to most asked integration pages](https://github.com/strapi/documentation/pull/2935) -- [Fix `ip` middleware not appearing in Configurations > Middlewares secondary sidebar](https://github.com/strapi/documentation/pull/2937) - -#### Repository -- [Re-introduce Routing summary in details for documentation specialists (Router tool)](https://github.com/strapi/documentation/pull/2942) -- [Improvements to Router tool ](https://github.com/strapi/documentation/pull/2941) -- [Replace `migration-template.md` with `breaking-change-template.md`](https://github.com/strapi/documentation/pull/2931) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - pwizla - -
-
-
- - -## 6.15.1 - -
-### New content - -
- -#### CMS - -- [Add focal point documentation to media library page](https://github.com/strapi/documentation/pull/2930) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix typo in "Populate and Select" documentation](https://github.com/strapi/documentation/pull/2929) -- [Reorganize Media Library providers documentation](https://github.com/strapi/documentation/pull/2922) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - leon-win - - - markkaylor - - - pwizla - -
-
-
- - -## 6.15.0 - -
-### New content - -
- -#### CMS -- [Add docs for Media Library retroactive AI generation](https://github.com/strapi/documentation/pull/2918) - -#### Repository -- [First documentation automation tools: agents.md, templates, and style checker](https://github.com/strapi/documentation/pull/2923) - -### Updated content - -
- -#### CMS -- [Fix favicon docs](https://github.com/strapi/documentation/pull/2899) - -#### Repository -- [Add global Annotation for naming conventions (kebab-case and more)](https://github.com/strapi/documentation/pull/2926) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Update supported Node versions](https://github.com/strapi/documentation/pull/2917) - -#### Cloud -- [Clarify API request counting in usage billing documentation](https://github.com/strapi/documentation/pull/2924) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - mariekirsch - - - markkaylor - - - pwizla - -
-
-
- - -## 6.14.1 - -
-### Updated content - -
- -#### CMS -- [Fix Admin Panel API example that used deprecated helper plugin](https://github.com/strapi/documentation/pull/2910) - -#### Cloud -- [Cloud yearly plans](https://github.com/strapi/documentation/pull/2901) -- [Data transfer between Cloud environments](https://github.com/strapi/documentation/pull/2891) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Doc bugfix: documents().update expects documentId param outside of data](https://github.com/strapi/documentation/pull/2909) - -#### Cloud -- [Manage beta badge for Cloud features](https://github.com/strapi/documentation/pull/2913) -- [Update custom domain saving options](https://github.com/strapi/documentation/pull/2906) - - -#### Repository -- [Close corresponding milestone with automated release script](https://github.com/strapi/documentation/pull/2916) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - mariekirsch - - - mephinet - - - pwizla - -
-
-
- -## 6.14.0 - -
-### New content - -
- -#### Repository -- [Add hosted MCP server for docs](https://github.com/strapi/documentation/pull/2889) - -### Updated content - -
- -#### Repository -- [Document auth fix for 5.24.0+](https://github.com/strapi/documentation/pull/2764) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Suggest using NPM for package manager when deploying to Kubernetes](https://github.com/strapi/documentation/pull/2533) - -#### Cloud -- [Update API request limits for the free Cloud plan](https://github.com/strapi/documentation/pull/2893) -- [Update region availability for Cloud](https://github.com/strapi/documentation/pull/2892) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - mariekirsch - - - pwizla - - - soheilnikroo - -
-
-
- - -## 6.13.0 - -
-### New content - -
- -#### Repository -- [Add `` component](https://github.com/strapi/documentation/pull/2883) - -### Updated content - -
- -#### CMS -- [Checklist in SSO configuration documentation](https://github.com/strapi/documentation/pull/2882) -- [Document Service API intro rework: more details, updated structure](https://github.com/strapi/documentation/pull/2880) -- [Lifecycle functions rework: structure change, more details & examples](https://github.com/strapi/documentation/pull/2878) -- [Tip about nested page hierarchies in Content-type Builder documentation](https://github.com/strapi/documentation/pull/2876) -- [More details regarding image uploading](https://github.com/strapi/documentation/pull/2875) -- [Add example to Theme extension documentation](https://github.com/strapi/documentation/pull/2850) -- [Add TypeScript example and deliverability tip to Email documentation](https://github.com/strapi/documentation/pull/2839) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Notify users about Apollo In Memory Cache ID](https://github.com/strapi/documentation/pull/2884) -- [Add types for Backend Customization Custom Routes](https://github.com/strapi/documentation/pull/2879) - -#### Repository -- [Fix unneeded margin on first-in-the-list custom docs card component](https://github.com/strapi/documentation/pull/2881) -- [Remove Amplitude-related elements](https://github.com/strapi/documentation/pull/2873) -- [Fix main content layout shift](https://github.com/strapi/documentation/pull/2872) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - meganelacheny - - - pwizla - - - unrevised6419 - -
-
-
- - -## 6.12.0 - -
-### New content - -
- -#### CMS -- [Add a guide about using RBAC from plugins](https://github.com/strapi/documentation/pull/2788) - -#### Repository -- [LLMs-code.txt](https://github.com/strapi/documentation/pull/2819) - -### Updated content - -
- -#### CMS -- [Update and add details & examples in GraphQL API migration guides](https://github.com/strapi/documentation/pull/2828) -- [Expand caution callout for media asset relations](https://github.com/strapi/documentation/pull/2822) -- [Aggregations section in GraphQL API documentation](https://github.com/strapi/documentation/pull/2810) - -#### Cloud -- [Clarify differences between accessing API on self-hosted VS Cloud hosted app](https://github.com/strapi/documentation/pull/2818) - -#### Repository -- [Add more information about `allowedHosts` for servers using Vite](https://github.com/strapi/documentation/pull/2813) -- [Fix main content alignment "flash"](https://github.com/strapi/documentation/pull/2812) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix mistake in Middleware documentation](https://github.com/strapi/documentation/pull/2820) - -#### Cloud -- [Save & deploy for Node version](https://github.com/strapi/documentation/pull/2808) - -#### Repository -- [Mention `/_health` endpoint in server config. & deployment docs](https://github.com/strapi/documentation/pull/2816) -- [Add warning for DATABASE_ environment variables](https://github.com/strapi/documentation/pull/2809) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.11.0 - -
-### New content - -
- -#### Repository -- [Add "Open with… [LLM]" buttons](https://github.com/strapi/documentation/pull/2794) - -### Updated content - -
- -#### CMS -- [Add security configuration documentation for Media Library](https://github.com/strapi/documentation/pull/2790) -- [Add information & configuration example in Email feature page](https://github.com/strapi/documentation/pull/2801) -- [Add information on controllers & routes](https://github.com/strapi/documentation/pull/2797) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Include `` components content in `llms.txt`](https://github.com/strapi/documentation/pull/2803) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - araksyagevorgyan - - - meganelacheny - - - pwizla - -
-
-
- - -## 6.10.1 - -
-### Updated content - -
- -#### CMS -- [More clarity and precisions on multi relations support](https://github.com/strapi/documentation/pull/2796) -- [AI-powered i18n](https://github.com/strapi/documentation/pull/2773) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix outdated example in Understanding populate guide](https://github.com/strapi/documentation/pull/2798) -- [Add tip about older `npx create-strapi-app@latest` installation command](https://github.com/strapi/documentation/pull/2795) - -#### Repository -- [Disable Kapa widget feedback](https://github.com/strapi/documentation/pull/2793) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - meganelacheny - - - pwizla - -
-
-
- - -## 6.10.0 - -
-### New content - -
- -#### Repository -- [Replace Algolia search with MeiliSearch](https://github.com/strapi/documentation/pull/2783) -- [Add a "News Ticker" to homepage](https://github.com/strapi/documentation/pull/2766) - -### Updated content - -
- -#### CMS -- [Add rate limiting documentation for users-permissions plugin](https://github.com/strapi/documentation/pull/2782) - -#### Repository -- [Add contribution program links to footer and top nav](https://github.com/strapi/documentation/pull/2781) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Fix S key in Ask AI modal triggering the MeiliSearch modal](https://github.com/strapi/documentation/pull/2786) -- [Docs Contribution Program: updates in PR template & contribution guide](https://github.com/strapi/documentation/pull/2784) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - crasite - - - meganelacheny - - - pwizla - -
-
-
- - -## 6.9.5 - -
-### Updated content - -
- -#### CMS -- [Rework the Unit testing page for Strapi 5](https://github.com/strapi/documentation/pull/2712) - -### Chore, fixes, typos, and other improvements - -
- -#### Cloud -- [Save & deploy for update repository](https://github.com/strapi/documentation/pull/2767) - -#### Repository -- [Fix code block buttons overlapping content](https://github.com/strapi/documentation/pull/2772) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - mariekirsch - - - pwizla - -
-
-
- -## 6.9.4 - -
- -### Chore, fixes, typos, and other improvements - -
- -#### Cloud -- [Update Cloud docs for passwordless authentication](https://github.com/strapi/documentation/pull/2765) -- [Display Subscription ID in the project settings](https://github.com/strapi/documentation/pull/2761) -- [Update Usage & Billing with Free Plan details](https://github.com/strapi/documentation/pull/2762) - -#### CMS -- [Update Homepage customization page to add layout customization tips](https://github.com/strapi/documentation/pull/2741) -- [Add FAQ entry for MCP](https://github.com/strapi/documentation/pull/2754) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.9.3 - -
-### New content - -
- -#### CMS -- [Strapi AI for Content-Type Builder](https://github.com/strapi/documentation/pull/2737) -- [Strapi AI for Media Library](https://github.com/strapi/documentation/pull/2751) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add information about disabling Strapi AI](https://github.com/strapi/documentation/pull/2749) -- [Fix `secrets.encryptionKey` in API tokens docs](https://github.com/strapi/documentation/pull/2743) - -#### Cloud -- [Save & deploy for domains](https://github.com/strapi/documentation/pull/2746) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 6.9.2 - -
-### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [fix: proxy breaking change in server example](https://github.com/strapi/documentation/pull/2731) - -#### Cloud -- [Fix reactivate subscription errors](https://github.com/strapi/documentation/pull/2734) -- [Save & deploy on branch change](https://github.com/strapi/documentation/pull/2730) -- [Save & deploy Cloud environment variables](https://github.com/strapi/documentation/pull/2729) -- [Add note about cloud project reactivation](https://github.com/strapi/documentation/pull/2701) - -#### Repository -- [Fix badges display & positioning](https://github.com/strapi/documentation/pull/2740) -- [Automatically add proper `source:` and `pr:` labels to PRs](https://github.com/strapi/documentation/pull/2735) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 6.9.1 - -
-### Updated content - -
- -#### CMS -- [Fix Strapi TypeScript import example](https://github.com/strapi/documentation/pull/2721) -- [Explain `unique` parameter behavior with Draft & Publish](https://github.com/strapi/documentation/pull/2716) -- [Add session management documentation](https://github.com/strapi/documentation/pull/2709) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add additional context to the admin locales and translations page](https://github.com/strapi/documentation/pull/2717) -- [Fix CMS Quick Start for NPM compatibility](https://github.com/strapi/documentation/pull/2710) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 6.9.1 - -
-### Updated content - -
- -#### CMS -- [Fix Strapi TypeScript import example](https://github.com/strapi/documentation/pull/2721) -- [Explain `unique` parameter behavior with Draft & Publish](https://github.com/strapi/documentation/pull/2716) -- [Add session management documentation](https://github.com/strapi/documentation/pull/2709) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add additional context to the admin locales and translations page](https://github.com/strapi/documentation/pull/2717) -- [Fix CMS Quick Start for NPM compatibility](https://github.com/strapi/documentation/pull/2710) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 6.9.0 - -
-### New content - -
- -#### Repository -- [Add new "TL;DR" component to all relevant pages](https://github.com/strapi/documentation/pull/2702) - -### Updated content - -
- -#### CMS -- [Live Preview improvements](https://github.com/strapi/documentation/pull/2690) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Update docker.md](https://github.com/strapi/documentation/pull/2707) -- [Fix old Strapi code base links wrongly referencing master branch](https://github.com/strapi/documentation/pull/2704) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - pwizla - - - the-clint - -
-
-
- -## 6.8.1 - -
-### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix typo in Content-type definition for credentials in TypeScript docs code example](https://github.com/strapi/documentation/pull/2697) - -#### Repository -- [Automatically tag PRs: `internal` or `contribution`](https://github.com/strapi/documentation/pull/2691) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - busybox11 - - - pwizla - -
-
-
- - -## 6.8.0 - -
-### New content - -
- -#### Repository -- [Contextual AI for codeblocks](https://github.com/strapi/documentation/pull/2675) -- [Add AI Toolbar](https://github.com/strapi/documentation/pull/2673) -- [Add starter questions to Kapa AI modal](https://github.com/strapi/documentation/pull/2672) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Fix the strapi/strapi contributing link](https://github.com/strapi/documentation/pull/2686) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - guptadeepak8 - - - pwizla - -
-
-
- - -## 6.7.0 - -
-### New content - -
- -#### CMS -- [Open API spec generation](https://github.com/strapi/documentation/pull/2665) - -### Updated content - -
- -#### CMS -- [Update Admin Panel and Homepage customization pages with new widgets and new guided tour UI](https://github.com/strapi/documentation/pull/2671) -- [Update controller sanitization](https://github.com/strapi/documentation/pull/2661) -- [Document flat archive structure for import and export](https://github.com/strapi/documentation/pull/2658) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix no search results for `db.query`](https://github.com/strapi/documentation/pull/2667) -- [Fix typo in lifecycle functions documentation](https://github.com/strapi/documentation/pull/2660) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - devios327 - - - maccomaccomaccomacco - - - pwizla - -
-
-
- -## 6.6.6 - -
-### New content - -
- -#### CMS -- [Add experimental firstPublishedAt configuration](https://github.com/strapi/documentation/pull/2636) -- [Update admin panel doc to add new 'Reset guided tour' setting](https://github.com/strapi/documentation/pull/2612) - -#### Cloud -- [Transfer ownership feature in Strapi Cloud docs](https://github.com/strapi/documentation/pull/2611) -- [Download backup on Strapi Cloud](https://github.com/strapi/documentation/pull/2582) - -### Updated content - -
- -#### CMS -- [Clarify `database` vs. `filename` usage in database configuration](https://github.com/strapi/documentation/pull/2657) -- [Database configuration: callout with information on data.db path](https://github.com/strapi/documentation/pull/2655) -- [Expand service docs to mention methods wrap core methods from Document Service API](https://github.com/strapi/documentation/pull/2648) -- [Clarify Content Manager API typing](https://github.com/strapi/documentation/pull/2646) -- [Note in Server about keep alive configuration](https://github.com/strapi/documentation/pull/2645) -- [Improve PostgreSQL database config. example](https://github.com/strapi/documentation/pull/2643) -- [Improve environment variables page](https://github.com/strapi/documentation/pull/2639) -- [Add advanced queries and policies guides to GraphQL docs](https://github.com/strapi/documentation/pull/2634) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix 'v4CompatibilityMode' typo for Strapi 5 migration in step by step guide](https://github.com/strapi/documentation/pull/2640) -- [Fix 'v4CompatibilityMode' typo for Strapi 5 migration](https://github.com/strapi/documentation/pull/2635) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.6.5 - -
-### New content - -
- -#### Cloud -- [Async project creation on Strapi Cloud](https://github.com/strapi/documentation/pull/2581) - -### Updated content - -
- -#### CMS -- [Improve GraphQL queries explanations (Flat vs. Relay-style)](https://github.com/strapi/documentation/pull/2621) -- [Explain there's only one GraphQL endpoint and how to customize its URL](https://github.com/strapi/documentation/pull/2617) -- [GraphQL & REST API: more information on operators & more examples](https://github.com/strapi/documentation/pull/2615) -- [Update Preview feature docs to mention Desktop/Mobile switch](https://github.com/strapi/documentation/pull/2607) -- [Better explain the move to `documentId`](https://github.com/strapi/documentation/pull/2604) -- [Expand and improve Client docs](https://github.com/strapi/documentation/pull/2602) -- [Mention that the Document Service API `findOne` returns `null` if no document found](https://github.com/strapi/documentation/pull/2614) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Fix MermaidWithFallback diagram display](https://github.com/strapi/documentation/pull/2609) -- [Fix tabs display with long labels](https://github.com/strapi/documentation/pull/2605) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 6.6.4 - -
-### Updated content - -
- -#### CMS -- [Add callout about overriding image function in Plugins extension docs](https://github.com/strapi/documentation/pull/2601) -- [Extend strapi.console documentation](https://github.com/strapi/documentation/pull/2600) -- [Document pluginOptions in Models](https://github.com/strapi/documentation/pull/2598) -- [Improve strapi-generate docs further](https://github.com/strapi/documentation/pull/2595) -- [Expand strapi generate documentation](https://github.com/strapi/documentation/pull/2593) -- [Document release statuses in Releases feature page](https://github.com/strapi/documentation/pull/2592) - -#### Cloud -- [Add cancellation section in Cloud docs](https://github.com/strapi/documentation/pull/2599) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add mention about building the website in Quick Start Guide](https://github.com/strapi/documentation/pull/2590) - -#### Cloud -- [Update Strapi Cloud settings screenshots](https://github.com/strapi/documentation/pull/2585) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - mariekirsch - - - meganelacheny - - - pwizla - -
-
-
- -## 6.6.3 - -
-### Updated content - -
- -#### Cloud -- [Canny widget](https://github.com/strapi/documentation/pull/2575) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix incorrect wording in the description of the `findOne()` method](https://github.com/strapi/documentation/pull/2586) -- [Fix broken line breaks in step-by-step file](https://github.com/strapi/documentation/pull/2580) -- [Fix strapi network mismatch issues in Docker instructions](https://github.com/strapi/documentation/pull/2578) - -#### Repository -- [Fix duplicate footer](https://github.com/strapi/documentation/pull/2589) -- [Fix Amplitude tracking experiment CDN](https://github.com/strapi/documentation/pull/2574) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 6.6.2 - -
-### Updated content - -
- -#### CMS -- [Conditional Fields (stable release)](https://github.com/strapi/documentation/pull/2554) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Remove duplicated sections in Preview docs](https://github.com/strapi/documentation/pull/2568) -- [Use new notation for accessing plugin config](https://github.com/strapi/documentation/pull/2562) - -#### Repository -- [New tooltips in table of content](https://github.com/strapi/documentation/pull/2561) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.6.1 - -
-### New content - -
- -#### CMS -- [Add repeatable components/Document Service API breaking change](https://github.com/strapi/documentation/pull/2551) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Add link to blog article about webhooks and Next.js](https://github.com/strapi/documentation/pull/2549) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - pwizla - -
-
-
- -## 6.6.0 - -
-### New content - -
- -#### CMS -- [Conditional Fields (beta)](https://github.com/strapi/documentation/pull/2539) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Add tip about using copy markdown button and LLMs.txt files](https://github.com/strapi/documentation/pull/2543) -- [Expandable card docs wrapper](https://github.com/strapi/documentation/pull/2541) -- [Add configuration parameter to allow Kapa analytics](https://github.com/strapi/documentation/pull/2540) -- [Add inline property to custom Badge component](https://github.com/strapi/documentation/pull/2538) -- [Increase "Ask AI" modal width to 720px](https://github.com/strapi/documentation/pull/2536) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - meganelacheny - - - pwizla - -
-
-
- -## 6.5.0 - -
-### New content - -
- -#### Repository -- [Add LLMs.txt and LLMs-full.txt generation](https://github.com/strapi/documentation/pull/2507) - -We've started adding support to the Strapi Docs. You can find the files in the footer or access them directly via the following links: -- [`llms.txt`](https://docs.strapi.io/llms.txt) -- [`llms-full.txt`](https://docs.strapi.io/llms-full.txt) - -![LLM files in the footer](/img/assets/llms/llms-footer.png) - -### Updated content - -
- -#### CMS -- [Update app creation flow to include Growth free trial](https://github.com/strapi/documentation/pull/2496) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Admin Panel API typo in example](https://github.com/strapi/documentation/pull/2508) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - abdallahmz - - - martinschilliger - - - pwizla - -
-
-
- - -## 6.4.0 - -This release marks some significant additions and rewrites. We've rethought the dev-related content in the CMS docs, with a **clearer table of contents** for the development, configuration, and customization aspects of Strapi. - -We've also added a handy ** Copy Markdown** button to the navigation bar on the right, so you can easily copy & paste raw Markdown content from the page into your favorite LLM! - -Enjoy, and watch out for more AI-related features soon 👀 - -
- -### New content - -
- -#### Repository -- [Add "Copy Markdown" button](https://github.com/strapi/documentation/pull/2498) - -### Updated content - -
- -#### CMS -- [Dev-related content rework, iteration #2 (admin panel configuration and customization)](https://github.com/strapi/documentation/pull/2505) -- [Dev-related content rework, iteration #1](https://github.com/strapi/documentation/pull/2501) -- [Content-type Builder revamp (stable release)](https://github.com/strapi/documentation/pull/2480) - -### Chore, fixes, typos, and other improvements - -
- -#### Cloud -- [Cloud Free plan edits for CMS docs ](https://github.com/strapi/documentation/pull/2500) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - mariekirsch - - - meganelacheny - - - pwizla - -
-
-
- -## 6.3.1 - -
-### Updated content - -
- -#### Cloud -- [Free Cloud plan](https://github.com/strapi/documentation/pull/2492) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - pwizla - -
-
-
- -## 6.3.0 - -
-### New content - -
- -#### CMS -- [Homepage API](https://github.com/strapi/documentation/pull/2474) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Remove Node 18 support and misc. cleanup](https://github.com/strapi/documentation/pull/2486) -- [Remove obsolete version attribute from Docker guide](https://github.com/strapi/documentation/pull/2485) -- [Viewable API tokens in the admin panel](https://github.com/strapi/documentation/pull/2484) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.2.2 - -
-### Updated content - -
- -#### CMS -- [Content-type Builder revamp (beta release)](https://github.com/strapi/documentation/pull/2479) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Update theme extension (colors) in admin panel customization](https://github.com/strapi/documentation/pull/2478) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - meganelacheny - - - soheilnikroo - -
-
-
- -## 6.2.1 - -
-### Updated content - -
- -#### CMS -- [Add Guideflows to feature pages](https://github.com/strapi/documentation/pull/2473) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Display required version for audit logs, data export and import, and relations reordering](https://github.com/strapi/documentation/pull/2475) -- [Add link to external guide about deploying Strapi on Azure](https://github.com/strapi/documentation/pull/2472) -- [Fix screenshot description in Cloud projects overview](https://github.com/strapi/documentation/pull/2471) - -#### Cloud -- [Fix various Cloud docs typos](https://github.com/strapi/documentation/pull/2476) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.2.0 - -
-### Updated content - -
- -#### CMS -- [Rewrite Custom fields documentation as a feature page](https://github.com/strapi/documentation/pull/2469) -- [Add `files` to Strapi Client docs](https://github.com/strapi/documentation/pull/2463) - -#### Repository - -- [Move contribution link to secondary table of contents on larger viewports](https://github.com/strapi/documentation/pull/2460) -- [New tabs design](https://github.com/strapi/documentation/pull/2459) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Fix plugin init command](https://github.com/strapi/documentation/pull/2467) -- [Remove unused plugins files](https://github.com/strapi/documentation/pull/2462) -- [Update suggested npm production Dockerfile](https://github.com/strapi/documentation/pull/2458) - -#### Cloud -- [Add caution about custom domains and Strapi Cloud assets URLs](https://github.com/strapi/documentation/pull/2470) - -#### Repository -- [Fix identity cards design](https://github.com/strapi/documentation/pull/2461) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.1.0 - -
-### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [New design for features & plugins identity cards](https://github.com/strapi/documentation/pull/2456) -- [Fix issue #2378](https://github.com/strapi/documentation/pull/2454) -- [Update SSO badge style](https://github.com/strapi/documentation/pull/2453) -- [Add missing factory method in TypeScript development example](https://github.com/strapi/documentation/pull/2452) - -#### Repository -- [Fix `key` token color in code blocks](https://github.com/strapi/documentation/pull/2455) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - kasperjha - - - pwizla - -
-
-
- -## 6.0.1 - -
- -### Chore, fixes, typos, and other improvements - -
- -#### CMS -- [Improve cors documentation](https://github.com/strapi/documentation/pull/2444) -- [fix broken link in preview.md](https://github.com/strapi/documentation/pull/2450) -- [Update step-by-step.md for Strapi 5 migration](https://github.com/strapi/documentation/pull/2449) -- [Add cross links for admin panel configuration and customization](https://github.com/strapi/documentation/pull/2447) -- [Unhide Testing page](https://github.com/strapi/documentation/pull/2446) - -#### Cloud -- [Adding a small note about Cloud sidegrade and display new ui](https://github.com/strapi/documentation/pull/2451) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 6.0.0 - -
-### New content - -
- -#### CMS -- [Add Design System breaking changes summary](https://github.com/strapi/documentation/pull/2435) - -### Updated content - -
- -#### CMS -- [Add custom logo doc in Admin Panel page + link in Admin Panel Customi…](https://github.com/strapi/documentation/pull/2439) -- [Preview: Side panel (stable, CMS) ](https://github.com/strapi/documentation/pull/2411) - -#### Cloud -- [Various Cloud docs updates](https://github.com/strapi/documentation/pull/2440) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Add support for dark mode to new homepage cards](https://github.com/strapi/documentation/pull/2442) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - meganelacheny - - - pwizla - -
-
-
- - -## 6.0.0-beta.5 - -
-### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Fixes AI button blurry box shadow](https://github.com/strapi/documentation/pull/2426) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - HichamELBSI - -
-
-
- - -## 6.0.0-beta.4 - -
- -### Updated content - -
- -#### CMS -- [Update Content Manager to mention editing relations on the fly](https://github.com/strapi/documentation/pull/2406) -- [Preview: Side panel](https://github.com/strapi/documentation/pull/2400) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [Improve homepage "Ask AI" button effect](https://github.com/strapi/documentation/pull/2424) -- [Third draft of iteration #1 for new homepage](https://github.com/strapi/documentation/pull/2422) -- [Second draft of iteration #1 for new homepage](https://github.com/strapi/documentation/pull/2420) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - pwizla - -
-
-
- -## 6.0.0-beta.3 -
- -### Updated content - -
- -#### Strapi Cloud -- [New Cloud plans (CMS docs)](https://github.com/strapi/documentation/pull/2396) - -### Chore, fixes, typos, and other improvements - -
- -#### Repository -- [First draft of Iteration #1 for new homepage](https://github.com/strapi/documentation/pull/2416) -- [Apply `` component where necessary](https://github.com/strapi/documentation/pull/2415) -- [Fix pagination_next values](https://github.com/strapi/documentation/pull/2414) -- [Mention lifecycle hooks blog article](https://github.com/strapi/documentation/pull/2413) -- [Mention blog article about lifecycle functions](https://github.com/strapi/documentation/pull/2412) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - kibwashere - - - pwizla - -
-
-
- -## 6.0.0-beta.2 - -
-### Updated content - -
- -#### CMS - -- [Add missing TypeScript pages](https://github.com/strapi/documentation/pull/2402) -- [Mention codemods on breaking changes pages](https://github.com/strapi/documentation/pull/2393) - -### Chore, fixes, typos, and other improvements - -
- -#### CMS - -- [Remove integration guides](https://github.com/strapi/documentation/pull/2390) - -#### Repository -- [Mermaid fallback](https://github.com/strapi/documentation/pull/2403) -- [Update release notes script](https://github.com/strapi/documentation/pull/2395) -- [Add ExternalLink custom component](https://github.com/strapi/documentation/pull/2389) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - pwizla - -
-
-
- -## 6.0.0-beta.1 - -
- -Version 6.0.0 of Strapi Docs is the biggest rewrite of documentation to date!
This release includes: - -- _Merge of Dev Docs & User Guide_: You now have one documentation per Strapi product: CMS and Cloud. -- _New Features section & pages_: Everything feature-related is in the new “Features” section of the CMS doc's navigation and each feature is now fully documented in one page. -- _Simplified navigation_: Many users reported frustration because of the too many levels and inconsistent behaviours in the navigation—both issues have been fixed and the navigation design has been improved for better readability. -- _More visuals throughout the docs_: We're slowly adding new interactive demos in pages to offer another way to learn about Strapi. Check out [Admin Panel](/cms/features/admin-panel), [Content Manager](/cms/features/content-manager), and [Content-type Builder](/cms/features/content-type-builder) pages to try the demos! - -Feel free to [share your feedback](https://forms.gle/D1SXb8kYBVR7qijp6)! - -### New content - -
- -#### CMS Docs -- [CMS folder reorganization](https://github.com/strapi/documentation/pull/2375) -- [New CMS documentation - More improvements & additions](https://github.com/strapi/documentation/pull/2359) -- [Proofread & improve CMS docs pages - pt. 2](https://github.com/strapi/documentation/pull/2369) -- [Proofread & improve CMS docs pages - pt. 1](https://github.com/strapi/documentation/pull/2350) -- [RBAC & SSO (Dev Docs) rework for CMS Docs](https://github.com/strapi/documentation/pull/2347) -- [New Features pages with User Guide content](https://github.com/strapi/documentation/pull/2288) -- [New Features pages with Dev Docs content](https://github.com/strapi/documentation/pull/2309) -- [CMS Docs (alpha)](https://github.com/strapi/documentation/pull/2340) - -### Chore, fixes, typos, and other improvements - -- [🎨 More design fixes for CMS Docs](https://github.com/strapi/documentation/pull/2366) -- [🎨 Design fixes for the new design](https://github.com/strapi/documentation/pull/2276) -- [🎨 New design](https://github.com/strapi/documentation/pull/2245) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - meganelacheny - - - pwizla - -
-
-
- -## 5.8.0 - -
-### New content - -
- -#### Repository -- [Add a guide on how to create components for plugins](https://github.com/strapi/documentation/pull/2433) - -### Updated content - -
- -#### Cloud -- [Project settings: Variables page revamp (pt. 2)](https://github.com/strapi/documentation/pull/2425) - -#### Repository -- [Add use case for handling database migrations with TypeScript](https://github.com/strapi/documentation/pull/2432) -- [Add Email plugin ratelimiting configuration options](https://github.com/strapi/documentation/pull/2377) - -### Chore, fixes, typos, and other improvements - -
- -#### Cloud -- [Add callout for downgrade/upgrade Cloud plans](https://github.com/strapi/documentation/pull/2428) - -#### Repository -- [Fix broken link to Strapi client README](https://github.com/strapi/documentation/pull/2436) -- [Fix missing location for content-type generation command in Store and Access Data (plugins dev) guide](https://github.com/strapi/documentation/pull/2434) -- [Fix Node versions in installation snippet](https://github.com/strapi/documentation/pull/2431) -- [Convert example in Store and Access Data guide from ES to DS](https://github.com/strapi/documentation/pull/2430) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 5.7.0 - -
- -### Updated content - -
- -#### Dev Docs & User Guide - -- [Preview: Side panel](https://github.com/strapi/documentation/pull/2410) - -#### User Guide - -- [Update Content Manager to mention editing relations on the fly](https://github.com/strapi/documentation/pull/2407) - -#### Strapi Cloud - -- [Strapi Cloud settings: Environment Variables revamp](https://github.com/strapi/documentation/pull/2419) - -### Chore, fixes, typos, and other improvements - -
- -#### Strapi Cloud - -- [Use new Cloud plans screenshot](https://github.com/strapi/documentation/pull/2418) - -#### Repository - -- [Added disabled option for LiveEditor so that it does not steal focus - Closes issue #2409](https://github.com/strapi/documentation/pull/2423) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 5.6.3 - -
- -### Updated content - -
- -#### Dev Docs -- [Enhanced webhooks docs](https://github.com/strapi/documentation/pull/2391) - -#### Strapi Cloud -- [New Cloud plans](https://github.com/strapi/documentation/pull/2394) - -### Chore, fixes, typos, and other improvements - -
- -#### Dev Docs -- [Fix descriptions for database parameters in CLI installation](https://github.com/strapi/documentation/pull/2404) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - Goldbee2 - - - kibwashere - - - ssganesh035 - -
-
-
- -## 5.6.2 - -### Updated content - -#### Dev Docs - -- [Setting up local plugin in Strapi without the Plugin SDK](https://github.com/strapi/documentation/pull/2392) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - Bassel17 - -
-
-
- -## 5.6.1 - -### Chore, fixes, typos, and other improvements - -#### Dev Docs -- [Update admin-panel-api.md](https://github.com/strapi/documentation/pull/2383) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - Rosalko - -
-
-
- -## 5.6.0 - -### New content - -#### Dev Docs - -- [Strapi Client library](https://github.com/strapi/documentation/pull/2373) - -### Updated content - -#### Dev Docs - -- [Pregenerated API tokens](https://github.com/strapi/documentation/pull/2380) - -### Chore, fixes, typos, and other improvements - -#### Dev Docs - -- [Rename SDK to Client in files and diagrams](https://github.com/strapi/documentation/pull/2381) -- [Add missing TypeScript version to Admin Panel API code example](https://github.com/strapi/documentation/pull/2372) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - maccomaccomaccomacco - - - oktapodia - - - pwizla - -
-
-
- -## 5.5.4 - -### Chore, fixes, typos, and other improvements - -#### Dev Docs -- [Update Doc Service API middleware example](https://github.com/strapi/documentation/pull/2368) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - Gkleinereva - -
-
-
- -## 5.5.3 - -### Chore, fixes, typos, and other improvements - -#### Dev Docs -- [Fix incorrect import of unstable_useContentManagerContext in Helper-plugin migration reference](https://github.com/strapi/documentation/pull/2367) -- [Fix typo in v4 → v5 step-by-step for GraphQL plugin](https://github.com/strapi/documentation/pull/2360) -- [Fix bug in the middlewares example](https://github.com/strapi/documentation/pull/2358) -- [Fix populate examples for Document Service API](https://github.com/strapi/documentation/pull/2356) - -#### Strapi Cloud -- [Add last successful deployment’s date of the Production environment](https://github.com/strapi/documentation/pull/2361) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 5.5.2 - -
- -### Chore, fixes, typos, and other improvements - -#### Dev Docs -- [Add graphQL landingPage configuration and update Apollo playground to sandbox](https://github.com/strapi/documentation/pull/2343) -- [Add the --verbose option to the data transfer command description](https://github.com/strapi/documentation/pull/2352) -- [Removing the note about unmodified fields on the update](https://github.com/strapi/documentation/pull/2351) -- [Fix typo in admonition](https://github.com/strapi/documentation/pull/2349) -- [Fix Document Service API example typo](https://github.com/strapi/documentation/pull/2348) - -#### Strapi Cloud -- [Update Cloud backups (restoration timestamp)](https://github.com/strapi/documentation/pull/2346) -- [Add the SSO badge for the new, paid add-on](https://github.com/strapi/documentation/pull/2341) -- [Update text for add environment button](https://github.com/strapi/documentation/pull/2299) - -#### Repository -- [Add Amplitude's browser SDK and web experiment for future A/B testing](https://github.com/strapi/documentation/pull/2345) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 5.5.1 - -
- -### Chore, fixes, typos, and other improvements - -#### User Guide -- [Update User Guide intro. for stable new homepage](https://github.com/strapi/documentation/pull/2338) - -#### Dev Docs -- [Fix typo in react-router-dom-6.md](https://github.com/strapi/documentation/pull/2337) -- [Use yarn/npm tabs in Strapi CLI examples](https://github.com/strapi/documentation/pull/2332) - -#### Strapi Cloud -- [Remove account preferences section from cloud docs](https://github.com/strapi/documentation/pull/2333) - - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - giu1io - - - johannesscheiermann - - - pwizla - -
-
-
- -## 5.5.0 - - The Strapi Docs website now has a brand new design! We hope you like it as much as we loved creating it. -Please feel free to [share your feedback](https://forms.gle/9NM8npMGoTkYetxGA). - -### Updated content - -#### User Guide -- [Mention new admin panel homepage and update screenshots](https://github.com/strapi/documentation/pull/2322) - -### Chore, fixes, typos, and other improvements - -#### Dev Docs -- [fix locale prerequisites](https://github.com/strapi/documentation/pull/2320) -- [fix wrong import](https://github.com/strapi/documentation/pull/2319) -- [Fix SDK plugin init command example in the SDK reference](https://github.com/strapi/documentation/pull/2318) -- [SDK beta callout](https://github.com/strapi/documentation/pull/2317) - -#### Strapi Cloud -- [Add section about importing env vars](https://github.com/strapi/documentation/pull/2326) -- [Adding notes about GitLab groups](https://github.com/strapi/documentation/pull/2323) - -#### Repository -- [Update docs content for Preview switching from beta to stable](https://github.com/strapi/documentation/pull/2325) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 5.4.0 - -
- -### New content - -
- -#### Repository -- [First iteration of Growth plan](https://github.com/strapi/documentation/pull/2303) - -### Chore, fixes, typos, and other improvements - -#### Dev Docs -- [Add a cross-link to the "commonly asked questions" about Strapi 5 article from the blog](https://github.com/strapi/documentation/pull/2313) -- [Add watchIgnoreFiles demo](https://github.com/strapi/documentation/pull/2312) -- [Fix unit testing docs for Strapi 5](https://github.com/strapi/documentation/pull/2308) -- [Mention Preview is under a feature flag](https://github.com/strapi/documentation/pull/2307) - -*** - -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- -## 5.3.0 - -
- -### New content - -
- -#### Dev Docs -- [Setting up the Preview feature](https://github.com/strapi/documentation/pull/2295) - -#### User Guide -- [Previewing content in the Content Manager](https://github.com/strapi/documentation/pull/2295) - -### Updated content - -
- -#### Strapi Cloud -- [Rename a project](https://github.com/strapi/documentation/pull/2300) - -### Chore, fixes, typos, and other improvements - -
- -#### Dev Docs -- [Update cross-link to U&P plugin from dev docs routes documentation](https://github.com/strapi/documentation/pull/2305) - -#### Strapi Cloud -- [Update Cloud plans screenshot](https://github.com/strapi/documentation/pull/2304) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - AtallahFatma - - - meganelacheny - - - pwizla - -
-
-
- -## 5.2.2 - -
- -### Chore, fixes, typos, and other improvements - -#### Dev Docs - -- [Collapse prerequisites and display step 1 in Quick Start Guide](https://github.com/strapi/documentation/pull/2296) - -#### Strapi Cloud -- [Design system v2 and new header in cloud docs](https://github.com/strapi/documentation/pull/2298) -- [Deleted old cloud assets](https://github.com/strapi/documentation/pull/2297) -- [Add restoration timestamp to docs and ressources](https://github.com/strapi/documentation/pull/2292) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 -
- - giu1io - - - olegStrapier - - - pierreburgy - -
-
-
- - -## 5.2.1 - -
- -### Updated content - -- [Add `strapi cloud environment link` to Cloud CLI](https://github.com/strapi/documentation/pull/2282) -- [Add new Cloud regions](https://github.com/strapi/documentation/pull/2290) - -### Chore, fixes, typos, and other improvements - -#### Dev Docs -- [Add useTypescriptMigrations](https://github.com/strapi/documentation/pull/2283) -- [Fix typo in retro-compatibility flag value](https://github.com/strapi/documentation/pull/2294) -- [Fix typo in example code for injectComponent in Admin Panel API docs ](https://github.com/strapi/documentation/pull/2287) -- [Fix outdated mention of Gold plan in SSO docs](https://github.com/strapi/documentation/pull/2286) -- [Fix locale param. example in Interactive Query Builder](https://github.com/strapi/documentation/pull/2285) -- [Fix discardDraft() Document Service API example](https://github.com/strapi/documentation/pull/2284) - -#### Strapi Cloud -- [Update credit cards handling](https://github.com/strapi/documentation/pull/2262) - -#### Repository -- [Add release notes script](https://github.com/strapi/documentation/pull/2289) - -*** -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
-
- - -## 5.2.0 - -
- -### New content - -
- -#### Dev Docs - -- [Add WIP API Reference and Guides for TypeScript](https://github.com/strapi/documentation/pull/2266) - -### Updated content - -
- -#### Dev Docs - -- [Add Knex Config function support](https://github.com/strapi/documentation/pull/2252) - -#### User Guide - -- [Integration between the Releases and Review Workflows features](https://github.com/strapi/documentation/pull/2273) - -### Chore, fixes, typos, and other improvements - -
- -#### Cloud - -- [Minor Cloud Docs changes](https://github.com/strapi/documentation/pull/2264) -- [Remove Strapi 5 warning for Cloud in FAQ](https://github.com/strapi/documentation/pull/2272) -- [Move custom cloud provider config warnings higher](https://github.com/strapi/documentation/pull/2278) - -#### Dev Docs - -- [Fix example request for update method in Document Service API](https://github.com/strapi/documentation/pull/2275) - -#### Repo - -- [Align navbar search box with 100% width](https://github.com/strapi/documentation/pull/2280) - -*** - -This release was made possible thanks to the following contributors. Thank you! 🫶 - - - -
-
- -## 5.1.3 - -
- -### Chore, fixes, typos, and other improvements - -- [Improve instructions for upgrading to Apollo v4](https://github.com/strapi/documentation/pull/2271) -- [Fix code example in breaking change for new response format](https://github.com/strapi/documentation/pull/2270) -- [Update names of removed mutations in GraphQL breaking change](https://github.com/strapi/documentation/pull/2269) -- [Fix typo in a snippet used in Cloud docs](https://github.com/strapi/documentation/pull/2268) - -*** - -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
- - laurenskling - - - xxtf1z - -
- -
-
- -## 5.1.2 - -
- -### Updated content - -
- -#### Dev Docs - -- [Add support for 'latest' parameter in the upgrade tool](https://github.com/strapi/documentation/pull/2259) -- [Add example code and resulting screenshot for theme extension](https://github.com/strapi/documentation/pull/2261) - -### Chore, fixes, typos, and other improvements - -#### Strapi Cloud - -- [Update cloud deployment logs screen](https://github.com/strapi/documentation/pull/2263) -- [Update confirmation modal text in Cloud Update Repository](https://github.com/strapi/documentation/pull/2258) - -#### Repository - -- [Restore bigger font-size for categories title in sidebar](https://github.com/strapi/documentation/pull/2260) - -*** - -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
- - Convly - - - giu1io - - - pwizla - - -
- -
-
- -## 5.1.1 - -
- -### Updated content - -
- -#### Strapi Cloud - -* [List environments with Cloud CLI](https://github.com/strapi/documentation/pull/2239) - -#### Dev Docs - -* [`publicationAt` breaking change](https://github.com/strapi/documentation/pull/2249) - -### Chore, fixes, typos, and other improvements - -#### Strapi Cloud - -* [Update wording on purchasable extra Seats](https://github.com/strapi/documentation/pull/2238) - -#### Dev Docs - -* [Clarify sorting for relational fields in the Content Manager list view](https://github.com/strapi/documentation/pull/2224) -* [Fix typo for `v4CompatibilityMode` flag](https://github.com/strapi/documentation/pull/2257) -* [Fix step-by-step v4 → v5 migration (v4CompatibilityMode flag)](https://github.com/strapi/documentation/pull/2255) -* [Update environment declaration in Docker guide](https://github.com/strapi/documentation/pull/2253) -* [Fix createStrapi method in TypeScript development documentation](https://github.com/strapi/documentation/pull/2248) -* [Fix links in the REST API documentation](https://github.com/strapi/documentation/pull/2247) -* [Fix CheckPagePermissions code example in helper-plugin deprecation guide](https://github.com/strapi/documentation/pull/2244) -* [Fix typo for init command in Plugin SDK](https://github.com/strapi/documentation/pull/2243) -* [Add link to ms package for examples for JWT expiresIn](https://github.com/strapi/documentation/pull/2242) - -#### Repository - -* [Update LICENSE](https://github.com/strapi/documentation/pull/2251) - - -*** - -This release was made possible thanks to the following contributors. Thank you! 🫶 - - - -
-
- -## 5.1.0 - -
- -### New content - -
- -#### Cloud Docs - -* [Multi-Environments](https://github.com/strapi/documentation/pull/2229) - -### Updated content - -
- -#### User Guide - -* [Mention Blocked status for Releases](https://github.com/strapi/documentation/pull/2235) - -#### Dev Docs - -* [Clarify helper-plugin migration guide](https://github.com/strapi/documentation/pull/2230) - -### Chore, fixes, typos, and other improvements - -
- -#### Dev Docs - -* [Fix creating a custom provider example](https://github.com/strapi/documentation/pull/2237) -* [Fix pagination_next for first page of categories](https://github.com/strapi/documentation/pull/2234) -* [Fix SEO issues](https://github.com/strapi/documentation/pull/2233) -* [Fix links to strapi codebase](https://github.com/strapi/documentation/pull/2226) -* [Fix code example in general deployment guidelines](https://github.com/strapi/documentation/pull/2231) -* [Fix grammar in TypeScript development docs](https://github.com/strapi/documentation/pull/2232) - -*** - -This release was made possible thanks to the following contributors. Thank you! 🫶 - -
- - - ChristopheCVB - - - imcarlosguerrero - - - stefanhuber - - - butcherZ - - - jhoward1994 - - - meganelacheny - - - pwizla - - -
- -
-
- -## 5.0.0 - -_The following is an extensive list of all the pull requests that were merged since we started working on Strapi 5 documentation. For a quicker tour, please refer to the [What's new page](/whats-new)._ - -### New content - -
- -#### Dev Docs - -* [Breaking change for database columns](https://github.com/strapi/documentation/pull/2221) -* [Content Manager APIs](https://github.com/strapi/documentation/pull/2220) -* [Breaking change for removing the "shared population strategy" for components & dynamic zones](https://github.com/strapi/documentation/pull/2204) -* [Templates](https://github.com/strapi/documentation/pull/2192) -* [Upgrade section revamp](https://github.com/strapi/documentation/pull/2153) -* [Custom U&P providers](https://github.com/strapi/documentation/pull/2138) -* [Breaking change for server.proxy config](https://github.com/strapi/documentation/pull/2131) -* [New "Upgrades" section (replaces updates & migration) for Strapi 5](https://github.com/strapi/documentation/pull/2126) -* [New proxy configuration feature](https://github.com/strapi/documentation/pull/2124) -* [lockIcon → licenseOnly breaking change](https://github.com/strapi/documentation/pull/2123) -* [Breaking change for default input validation](https://github.com/strapi/documentation/pull/2096) -* [Entity Service → Document Service: Breaking change + migration reference](https://github.com/strapi/documentation/pull/2093) -* [Plugins migration summary](https://github.com/strapi/documentation/pull/2089) -* [Breaking change for better-sqlite3](https://github.com/strapi/documentation/pull/2083) -* [Breaking change for Admin RBAC updates](https://github.com/strapi/documentation/pull/2082) -* [Breaking change for model config path uses uid](https://github.com/strapi/documentation/pull/2055) -* [Breaking change for upgrade from apollo v3 to apollo v4](https://github.com/strapi/documentation/pull/2053) -* [Breaking change for removed `localizations` field](https://github.com/strapi/documentation/pull/2050) -* [Breaking change for server log level configuration](https://github.com/strapi/documentation/pull/2049) -* [Breaking change for the removed webpack aliases](https://github.com/strapi/documentation/pull/2047) -* [Breaking change for strict requirements on configuration filenames](https://github.com/strapi/documentation/pull/2009) -* [Breaking change about removed support for some env-only options](https://github.com/strapi/documentation/pull/2007) -* [Breaking change for no findPage() method in Document Service API](https://github.com/strapi/documentation/pull/2006) -* [Breaking change for sorting by id](https://github.com/strapi/documentation/pull/1999) -* [Breaking change for Vite as default bundler](https://github.com/strapi/documentation/pull/1998) -* [Breaking change for U&P register.allowedFields](https://github.com/strapi/documentation/pull/1997) -* [Breaking change for CM redux store](https://github.com/strapi/documentation/pull/1995) -* [Breaking change for `strapi.container`](https://github.com/strapi/documentation/pull/1994) -* [Breaking change for i18n CM locale parameter](https://github.com/strapi/documentation/pull/1991) -* [Breaking change for strapi exports](https://github.com/strapi/documentation/pull/1989) -* [Breaking change for removal of `isSupportedImage`](https://github.com/strapi/documentation/pull/1988) -* [Breaking change about react-router-dom 6](https://github.com/strapi/documentation/pull/1987) -* [Upgrade tool](https://github.com/strapi/documentation/pull/1945) -* [Document Service](https://github.com/strapi/documentation/pull/1935) -* [Breaking change for fetch](https://github.com/strapi/documentation/pull/1915) -* [Breaking change for MySQL v5 support drop](https://github.com/strapi/documentation/pull/1892) -* [Init. breaking changes pages for Strapi v4 → v5 migration](https://github.com/strapi/documentation/pull/1896) -* [New v5 Dev Docs structure](https://github.com/strapi/documentation/pull/1811) - -#### User Guide - -* [Updated screenshots & last updates in User Guide](https://github.com/strapi/documentation/pull/2207) -* [Releases settings](https://github.com/strapi/documentation/pull/2120) - -#### Cloud Docs - -* [Port existing Cloud docs content from v4 website to website](https://github.com/strapi/documentation/pull/2154) -* [Make main categories clickable in breadcrumbs](https://github.com/strapi/documentation/pull/2198) - -#### Global - -* [AI widget](https://github.com/strapi/documentation/pull/1898) -* [Tagging system](https://github.com/strapi/documentation/pull/2076) -* [New homepage](https://github.com/strapi/documentation/pull/2087) - -### Updated content - -
- -#### Dev Docs - -* [Remove shared population strategy for dynamic zones](https://github.com/strapi/documentation/pull/2222) -* [Update breaking change for default server level log](https://github.com/strapi/documentation/pull/2216) -* [Update breaking change for reserved attributes and content-types names](https://github.com/strapi/documentation/pull/2215) -* [Update breaking change for `is-supported-image`](https://github.com/strapi/documentation/pull/2214) -* [Update codemods list](https://github.com/strapi/documentation/pull/2212) -* [Update some v5 migration and Plugin SDK docs](https://github.com/strapi/documentation/pull/2210) -* [Add more before examples for helper plugin migration](https://github.com/strapi/documentation/pull/2209) -* [Plugin migration updates](https://github.com/strapi/documentation/pull/2208) -* [Update the Quick Start Guide with Cloud CLI and new CLI prompts](https://github.com/strapi/documentation/pull/2203) -* [Update sdk-plugin init with new options](https://github.com/strapi/documentation/pull/2202) -* [Update helper plugin migration doc](https://github.com/strapi/documentation/pull/2200) -* [Update backend customization examples to Document Service API](https://github.com/strapi/documentation/pull/2196) -* [Add scope and warning details to the upgrade tool guide](https://github.com/strapi/documentation/pull/2195) -* [More examples for middlewares context to Document Service API](https://github.com/strapi/documentation/pull/2189) -* [Deprecate integration guides](https://github.com/strapi/documentation/pull/2173) -* [Transfer deployment guides to external resources](https://github.com/strapi/documentation/pull/2172) -* [Database lifecycles vs. Document Service middlewares](https://github.com/strapi/documentation/pull/2170) -* [Admin panel customization section rework](https://github.com/strapi/documentation/pull/2162) -* [Update REST API additional resources with new links and call to write](https://github.com/strapi/documentation/pull/2148) -* [Updates to the CLI installation guide](https://github.com/strapi/documentation/pull/2121) -* [FAQ section for 'Cannot find module @strapi/XXX' build error](https://github.com/strapi/documentation/pull/2116) -* [Update upgrade tool documentation with codemods updates](https://github.com/strapi/documentation/pull/2112) -* [Plugin CLI update for @strapi/sdk-plugin package](https://github.com/strapi/documentation/pull/2109) -* [Updates to relations in API docs](https://github.com/strapi/documentation/pull/2100) -* [Update doc service doc to match latest changes being prepared](https://github.com/strapi/documentation/pull/2074) -* [GraphQL updates](https://github.com/strapi/documentation/pull/2051) -* [REST API updates (incl. i18n and breaking changes)](https://github.com/strapi/documentation/pull/2038) -* [(no-)watch-admin and bundler updates](https://github.com/strapi/documentation/pull/2037) -* [Turn the TypeScript page into a section](https://github.com/strapi/documentation/pull/1913) -* [New Dev Docs introduction](https://github.com/strapi/documentation/pull/1911) -* [Update supported databases](https://github.com/strapi/documentation/pull/1887) - -#### User Guide - -* [Make main categories clickable in breadcrumbs](https://github.com/strapi/documentation/pull/2197) -* [Update whole content in User Guide](https://github.com/strapi/documentation/pull/2193) -* [Update Draft & Publish](https://github.com/strapi/documentation/pull/2027) - -#### Cloud Docs - -* [Make main categories clickable in breadcrumbs](https://github.com/strapi/documentation/pull/2198) - -### Chore, fixes, typos, and other improvements - -* [AI bot improvements](https://github.com/strapi/documentation/pull/2142) - -*** - -This release was made possible thanks to the following contributors. Thank you! 🫶 +--- - +

See older release notes for all previous Strapi Docs versions (5.x and 6.x).

diff --git a/docusaurus/docs/snippets/_cookbook-foodadvisor.md b/docusaurus/docs/snippets/_cookbook-foodadvisor.md new file mode 100644 index 0000000000..fed2e23676 --- /dev/null +++ b/docusaurus/docs/snippets/_cookbook-foodadvisor.md @@ -0,0 +1,3 @@ +:::callout 🏗 About these examples +These examples are built around , which is no longer Strapi's featured demo application (it has been superseded by ). What matters here is understanding the backend mechanisms being demonstrated, not FoodAdvisor itself. These pages will be revisited to use LaunchPad. +::: diff --git a/docusaurus/docs/whats-new.md b/docusaurus/docs/whats-new.md index 907f4a2d00..839035a414 100644 --- a/docusaurus/docs/whats-new.md +++ b/docusaurus/docs/whats-new.md @@ -6,33 +6,24 @@ custom_edit_url: null # What's new in Strapi docs? -Strapi 5 brings many new features and improvements, and this page quickly highlights the most important documentation changes. +We gave the Strapi documentation a fresh new look and a set of features designed to make reading, navigating, and reusing the docs easier. Here is a quick tour of what changed. - The **[Draft & Publish](/cms/features/draft-and-publish)** feature has been fully reworked. When Draft & Publish is enabled, the Content Manager edit view shows 2 different tabs, one for the draft version and one for the published version, and both can handle different content. + **3 reading modes.** Switch any page between **Elegant mode** (the default, fully styled reading experience), **Markdown mode** (a flat, raw-text view that is easy to copy), and **AI mode** (a summary-oriented view built for working with AI assistants). The switcher sits at the top of every documentation page. - The new **[Content History](/cms/features/content-history)** feature allows you to view and restore previous versions of your content from the Content Manager. + **Content-width selector.** Prefer a narrower column for comfortable reading or a wider one to see more at once? A floating control lets you adjust the content width to your taste, and your choice is remembered as you browse. - The new **[Preview](/cms/features/preview)** feature allows you to preview your content in your front end application directly from Strapi's admin panel. + **Collapsible sidebars.** Both the left navigation and the right "On this page" table of contents can now be collapsed, so you can focus on the content and reclaim screen space whenever you need it. - Strapi 5 now use **[documents](/cms/api/document)** and introduces a new **[Document Service API](/cms/api/document-service)** to replace the Entity Service API from v4, leveraging the new Draft & Publish system and paving the way for more upcoming features. + **A brand-new homepage.** The [documentation homepage](/) was redesigned from scratch, with clearer entry points to the CMS and Cloud docs, an interactive API explorer, and quick links to the most popular sections. - The **[REST API](/cms/api/rest)** and **[GraphQL API](/cms/api/graphql)** have been updated, with a simplified response data format for both and partial support for Relay-style queries for GraphQL. + **2-column layout for API references.** The [REST API](/cms/api/rest), [GraphQL API](/cms/api/graphql), and [Document Service API](/cms/api/document-service) reference pages now use a 2-column layout: the description and parameters on the left, and the request and response examples on the right, so you can read and try at the same time. - The **[Strapi Client](/cms/api/client)** library simplifies interactions with your Strapi back end, providing a way to fetch, create, update, and delete content. + **Clean Markdown for AI agents.** Every page is also available as clean Markdown, with all the layout components resolved into plain text so AI assistants and tools get parseable content. There are three ways to get it: - The **[OpenAPI package](/cms/api/openapi)** lets you programmatically generate a specification describing your Strapi APIs. +- Use the **View as Markdown** option in the toolbar below the page title (in Elegant and AI modes). +- In **Markdown mode**, click the **View this page as .md** button next to that toolbar. +- Or go straight to the Markdown URL by adding `.md` to any page address, for example [docs.strapi.io/cms/api/rest.md](/cms/api/rest.md). - The **[Plugin SDK](/cms/plugins-development/plugin-sdk)** is a new CLI tool that helps you develop and publish Strapi plugins. +You can also point tools at the aggregated [llms.txt](/llms.txt), [llms-full.txt](/llms-full.txt), and [llms-code.txt](/llms-code.txt) files. - Another whole new CLI **[upgrade tool](/cms/upgrade-tool)** will help you migrate to any patch, minor, and major version of Strapi, automating most of the common tasks through codemods. - - Also, we have some resources ready to help you **[upgrade to Strapi 5](/cms/migration/v4-to-v5/introduction-and-faq)**, including a [step-by-step guide](/cms/migration/v4-to-v5/step-by-step), a list of [breaking changes](/cms/migration/v4-to-v5/breaking-changes) and [specific resources](/cms/migration/v4-to-v5/additional-resources/introduction) to read for when you will consider upgrading to Strapi 5. - - We introduced a new **tagging system** to provide another layer of information architecture. Tags can be found at the bottom of each page. Clicking on a tag will point you to an index page listing all pages with the same tag. The list of all available tags is visible by visiting the [/tags](/tags) page. - - You will also soon find more **official guides** and more references to **external resources** (contributor documentation, design system documentation, and blog articles) throughout the docs pages. - - Also, last but not least, **Strapi Docs now work even better with AI**: - -* First, you might have noticed that the search bar now sits in the left sidebar and combines 2 buttons: the left button, ** Search**, triggers a regular search, while the right part is our new AI-based chatbot! Click ** Ask AI** to ask your questions. The chatbot keeps the context of previous answers, so you can ask follow-up questions as long as you don't close the chatbot window. You can also use the Ask AI button on any code block to get detailed explanations. -* You can also use the AI toolbar at the top of each page, which includes a ** Copy Markdown** button to copy raw Markdown content from the page into anything, and quick access to our [`llms.txt`](/llms.txt) and [`llms-full.txt`](/llms-full.txt) files, so you can better use Strapi Docs with your favorite LLM. + **Page feedback widget.** Tell us what works and what does not, directly from the docs. You can leave general feedback using the widget at the bottom of each page, or select some text or code and click the floating **Leave feedback** button to send specific feedback about that content. Your input goes straight to the docs team. diff --git a/docusaurus/docusaurus.config.js b/docusaurus/docusaurus.config.js index b6d27bdc9c..b682238fc3 100644 --- a/docusaurus/docusaurus.config.js +++ b/docusaurus/docusaurus.config.js @@ -31,6 +31,35 @@ const config = { themes: ['@docusaurus/theme-live-codeblock', '@docusaurus/theme-mermaid'], + headTags: [ + { + // Anti-FOUC: apply saved content width before React hydrates + tagName: 'script', + attributes: {}, + innerHTML: '(function(){try{var w=localStorage.getItem("strapi-content-width");if(w)document.documentElement.dataset.contentWidth=w}catch(e){}})();', + }, + { + // Anti-FOUC: apply saved view mode before React hydrates + tagName: 'script', + attributes: {}, + innerHTML: '(function(){try{var m=localStorage.getItem("strapi-view-mode");if(m&&m!=="ai")document.documentElement.dataset.viewMode=m;else document.documentElement.dataset.viewMode="elegant"}catch(e){document.documentElement.dataset.viewMode="elegant"}})();', + }, + { + // Anti-FOUC: apply the saved left-sidebar collapsed state before React + // hydrates, so a collapsed sidebar doesn't flash open on every page load. + tagName: 'script', + attributes: {}, + innerHTML: '(function(){try{if(localStorage.getItem("strapi-sidebar-collapsed")==="true")document.documentElement.dataset.sidebarCollapsed="true"}catch(e){}})();', + }, + { + // Anti-FOUC: apply the saved right-sidebar (TOC) collapsed state before + // React hydrates, so a collapsed TOC doesn't flash open on every page load. + tagName: 'script', + attributes: {}, + innerHTML: '(function(){try{if(localStorage.getItem("strapi-toc-collapsed")==="true")document.documentElement.dataset.tocCollapsed="true"}catch(e){}})();', + }, + ], + scripts: [ { src: '/js/redirector.js', @@ -89,26 +118,7 @@ const config = { 'data-modal-disclaimer': 'Disclaimer: Answers are AI-generated and might be inaccurate. Please ensure you double-check the information provided by visiting source pages.', 'data-project-color': '#4945FF', - 'data-project-color-dark': '#7B79FF', 'data-button-bg-color': '#32324D', - // Dark mode: sync with Docusaurus theme toggle - 'data-color-scheme': 'auto', - 'data-color-scheme-selector': "[data-theme='dark']", - // Light mode palette (defaults are fine, override only what we need) - 'data-surface-color': '#ffffff', - 'data-surface-elevated-color': '#f8f9fa', - 'data-text-color': '#212529', - 'data-text-muted-color': '#868e96', - 'data-border-color': '#dee2e6', - 'data-anchor-color': '#4945FF', - // Dark mode palette - 'data-surface-color-dark': '#181826', - 'data-surface-elevated-color-dark': '#212134', - 'data-surface-hover-color-dark': '#2a2a3e', - 'data-text-color-dark': '#e4e4e7', - 'data-text-muted-color-dark': '#a1a1a9', - 'data-border-color-dark': '#3f3f45', - 'data-anchor-color-dark': '#7B79FF', 'data-modal-example-questions': "How to create a Strapi project?,How does population work?,How to customize the admin panel?,Explain the Growth plan benefits", // 'data-modal-override-open-class-search': 'DocSearch-Button', // 'data-modal-title-search': 'Search Strapi Docs', @@ -116,7 +126,7 @@ const config = { // 'data-search-mode-enabled': true, 'data-modal-override-open-class': 'kapa-widget-button', 'data-modal-title-ask-ai': 'Ask your question', - 'data-modal-border-radius': '4px', + 'data-modal-border-radius': '16px', 'data-submit-query-button-bg-color': '#4945FF', 'data-modal-body-padding-top': '20px', 'data-user-analytics-cookie-enabled': true, diff --git a/docusaurus/package.json b/docusaurus/package.json index 3d69b66b5f..4b5d26614b 100644 --- a/docusaurus/package.json +++ b/docusaurus/package.json @@ -1,6 +1,6 @@ { "name": "strapi-docs", - "version": "6.28.0", + "version": "7.0.0", "private": true, "scripts": { "docusaurus": "docusaurus", @@ -31,6 +31,7 @@ "@docusaurus/preset-classic": "3.5.2", "@docusaurus/theme-live-codeblock": "3.5.2", "@docusaurus/theme-mermaid": "3.5.2", + "@kapaai/react-sdk": "^0.9.9", "@mdx-js/react": "^3.0.0", "@octokit/rest": "^22.0.0", "axios": "1.13.5", @@ -53,6 +54,8 @@ "qs": "^6.11.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-markdown": "^10.1.0", + "remark-gfm": "^4.0.1", "sass": ">=1.58.3 <2.0.0" }, "devDependencies": { diff --git a/docusaurus/plugins/llms-generator-plugin.js b/docusaurus/plugins/llms-generator-plugin.js index 458710ffd7..d9991692b9 100644 --- a/docusaurus/plugins/llms-generator-plugin.js +++ b/docusaurus/plugins/llms-generator-plugin.js @@ -11,10 +11,17 @@ function llmsGeneratorPlugin(context, options) { // Dynamic import server-side with the right path const DocusaurusLlmsGenerator = require(path.resolve(__dirname, '../scripts/generate-llms')); + // Build an absolute site URL (e.g. https://docs.strapi.io) so page URLs + // and the Source: lines in the .md files are fully-qualified rather than + // `//cms/...`. siteConfig.url is the origin; baseUrl is the path prefix. + const origin = (context.siteConfig.url || '').replace(/\/$/, ''); + const basePath = (baseUrl || '/').replace(/\/$/, ''); + const absoluteBaseUrl = `${origin}${basePath}`; + const generator = new DocusaurusLlmsGenerator({ docsDir: options.docsDir || 'docs', sidebarPath: options.sidebarPath || 'sidebars.js', - baseUrl: baseUrl || context.siteConfig.url, + baseUrl: absoluteBaseUrl, outputDir: outDir, siteName: options.siteName || context.siteConfig.title }); diff --git a/docusaurus/scripts/generate-llms-code.js b/docusaurus/scripts/generate-llms-code.js index 5f25c48ca8..f5438f5ead 100644 --- a/docusaurus/scripts/generate-llms-code.js +++ b/docusaurus/scripts/generate-llms-code.js @@ -31,6 +31,10 @@ try { }; } +// Shared extractor for code carried inside API layout components +// (, ) whose code lives in props, not Markdown fences. +const { extractApiComponentSnippets } = require('./lib/api-components'); + const DEFAULT_DOCS = [ 'cms/admin-panel-customization/bundlers', 'cms/backend-customization/middlewares', @@ -768,7 +772,30 @@ class DocusaurusLlmsCodeGenerator { } }); - return { snippets: snippets.filter((snippet) => Boolean(snippet.code)), sectionAnchors }; + // Code carried inside / components lives in props, so the + // fence scanner above never sees it. Pull it out via the shared extractor and + // append as regular snippets so API pages (REST, Document Service, Entity + // Service, GraphQL...) are no longer skipped. + const apiSnippets = extractApiComponentSnippets(content).map((s) => ({ + section: s.section || title, + language: s.language || '', + options: {}, + description: s.description || '', + useCase: null, + fallbackUsed: false, + code: s.code, + filePath: null, + variantGroupId: s.variantGroupId || null, + tabLabel: s.tabLabel || null, + tabValue: null, + context: [], + startLine: null, + endLine: null, + })); + + const allSnippets = snippets.concat(apiSnippets); + + return { snippets: allSnippets.filter((snippet) => Boolean(snippet.code)), sectionAnchors }; } deriveSnippetTitle(snippet, index) { diff --git a/docusaurus/scripts/generate-llms.js b/docusaurus/scripts/generate-llms.js index 567372d0cd..797aec5104 100644 --- a/docusaurus/scripts/generate-llms.js +++ b/docusaurus/scripts/generate-llms.js @@ -1,6 +1,10 @@ const fs = require('fs-extra'); const path = require('path'); const matter = require('gray-matter'); +// Shared JSX/prop scanners (single source of truth, also used by +// generate-llms-code.js). These supersede the previously-duplicated helpers +// and additionally fix a template-literal interpolation bug. +const apiComponents = require('./lib/api-components'); class DocusaurusLlmsGenerator { constructor(config = {}) { @@ -26,30 +30,124 @@ class DocusaurusLlmsGenerator { const llmsFullTxt = this.generateLlmsFullTxt(pages); await fs.writeFile(path.join(this.outputDir, 'llms-full.txt'), llmsFullTxt); + console.log('📄 Generating per-page Markdown (.md)...'); + const mdCount = await this.writePerPageMarkdown(pages); + console.log('✅ LLMs files successfully generated !'); console.log(` - ${this.outputDir}/llms.txt`); console.log(` - ${this.outputDir}/llms-full.txt`); + console.log(` - ${mdCount} per-page .md files`); } catch (error) { console.error('❌ Error while trying to generate LLMs files:', error); throw error; } } + /** + * Write one clean-Markdown file per page next to its HTML in the build, so + * agents can fetch e.g. /cms/api/rest.md. Reuses the same cleaned content as + * llms-full.txt (lots A–H), so there is a single Markdown source of truth. + * + * Only runs against a real build output dir — skipped when writing to + * `static/` (the dev/standalone path) to avoid polluting the source tree with + * hundreds of generated files. Returns the number of files written. + */ + async writePerPageMarkdown(pages) { + // Guard: don't scatter .md files into the source `static/` folder (dev runs + // and `node scripts/generate-llms.js` default there). Only emit for builds. + const outName = path.basename(this.outputDir); + if (outName === 'static') { + console.log(' (skipped per-page .md: output dir is static/, not a build)'); + return 0; + } + + let count = 0; + for (const page of pages) { + const relPath = page.url + .replace(/^https?:\/\/[^/]+\//, '') // strip origin + .replace(/^\/+/, '') // leading slashes + .replace(/\/+$/, ''); // trailing slash + if (!relPath) continue; // homepage: handled by HTML only + + const outFile = path.join(this.outputDir, `${relPath}.md`); + // The cleaned content often already starts with the page's H1 (kept from + // the markdown). Drop a leading H1 so we don't print the title twice. + const contentNoH1 = page.content.replace(/^\s*#\s+.+\n+/, ''); + const body = [ + `# ${page.title}`, + '', + `> Source: ${page.url}`, + '', + contentNoH1, + '', + ].join('\n'); + + try { + await fs.ensureDir(path.dirname(outFile)); + await fs.writeFile(outFile, body, 'utf-8'); + count++; + } catch (error) { + console.warn(`⚠️ Failed to write ${outFile}: ${error.message}`); + } + } + return count; + } + async extractAllPages() { const pages = []; - + // Track which docIds were already emitted so the filesystem sweep below + // doesn't duplicate pages already pulled in via the sidebar. + this.seenDocIds = new Set(); + // Load sidebar configuration const sidebarConfig = this.loadSidebarConfig(); - - // Parses every sidebar + + // Parses every sidebar (gives a sensible primary ordering/structure) for (const [sidebarName, sidebarItems] of Object.entries(sidebarConfig)) { await this.processItems(sidebarItems, pages); } + // The sidebar only lists a subset of pages: many docs are surfaced through + // generated-index categories or summary tables (e.g. the 52 v4→v5 + // breaking-change pages), so they never appear in the sidebar tree and were + // missing from the output entirely. Sweep the filesystem and emit any page + // not already covered, so llms-full.txt reflects the whole docs set. + await this.processUncoveredFiles(pages); + // Sort pages by URL for a consistent and clear order return pages.sort((a, b) => a.url.localeCompare(b.url)); } + /** + * Emit every cms/ and cloud/ doc file not already covered by the sidebar + * walk. Skips AGENTS guides and templates. Handles both .md and .mdx and + * index files (dir/index.md → docId = dir). + */ + async processUncoveredFiles(pages) { + const docIds = await this.discoverAllDocIds(); + for (const docId of docIds) { + if (this.seenDocIds.has(docId)) continue; + await this.processDocPage(docId, pages); + } + } + + /** Recursively list docIds under cms/ and cloud/ (no extension, no /index). */ + async discoverAllDocIds() { + const roots = ['cms', 'cloud']; + const ids = []; + for (const root of roots) { + const rootDir = path.join(this.docsDir, root); + if (!(await fs.pathExists(rootDir))) continue; + const files = await this.getAllMdFiles(rootDir, root); + for (const file of files) { + let id = file.replace(/\\/g, '/').replace(/\.mdx?$/i, ''); + id = id.replace(/\/index$/i, ''); + ids.push(id); + } + } + return ids; + } + loadSidebarConfig() { try { // Deletes cache to reload config @@ -78,10 +176,10 @@ class DocusaurusLlmsGenerator { if (stat.isDirectory()) { const subFiles = await this.getAllMdFiles(fullPath, path.join(prefix, item)); files.push(...subFiles); - } else if (item.endsWith('.md')) { + } else if (/\.mdx?$/i.test(item)) { // Skip agent guides and templates const rel = path.join(prefix, item).replace(/\\/g, '/'); - if (/(^|\/)AGENTS(\.|\.md$)/.test(rel) || /(^|\/)templates\//.test(rel)) { + if (/(^|\/)AGENTS(\.|\.mdx?$)/.test(rel) || /(^|\/)templates\//.test(rel)) { continue; } files.push(path.join(prefix, item)); @@ -122,7 +220,7 @@ class DocusaurusLlmsGenerator { const fileContent = await fs.readFile(filePath, 'utf-8'); const { data: frontmatter, content } = matter(fileContent); - const pageUrl = this.generatePageUrl(docId); + const pageUrl = this.generatePageUrl(docId, frontmatter.slug); const tldr = this.extractTldr(content); pages.push({ @@ -134,7 +232,8 @@ class DocusaurusLlmsGenerator { content: this.cleanContent(content), frontmatter }); - + if (this.seenDocIds) this.seenDocIds.add(docId); + break; // Stops once a file is found } catch (error) { console.warn(`⚠️ Error while handling file ${filePath}:`, error.message); @@ -143,8 +242,15 @@ class DocusaurusLlmsGenerator { } } - generatePageUrl(docId) { - // Deletes common prefixes and generates proper URL + generatePageUrl(docId, slug) { + // A `slug` in the front matter overrides the doc-id-based path (e.g. + // cloud/getting-started/cloud-fundamentals is served at /cloud/cloud-fundamentals). + // Honor it so the URL — and the per-page .md path / llms.txt link — match + // the real page location. An absolute slug starts with '/'. + if (slug) { + const cleanSlug = String(slug).replace(/^\/+/, '').replace(/\/+$/, ''); + return `${this.baseUrl}/${cleanSlug}`; + } const cleanId = docId.replace(/^(docs\/|pages\/)/, ''); return `${this.baseUrl}/${cleanId}`; } @@ -203,33 +309,658 @@ class DocusaurusLlmsGenerator { .trim(); } + /** + * Inline components imported from /docs/snippets/*.md. These are used + * self-closing (e.g. , , ) and would + * otherwise be deleted by the generic stripper, dropping their snippet + * content (which never appears elsewhere since snippets aren't in the + * sidebar). Reads the import lines, resolves each snippet file, strips its + * frontmatter, and substitutes the Markdown wherever the component is used. + */ + inlineSnippetComponents(content) { + // Build a map: ComponentName -> resolved snippet file path. + const importRe = /^import\s+([A-Za-z0-9_]+)\s+from\s+['"]([^'"]*snippets\/[^'"]+\.mdx?)['"]\s*;?\s*$/gm; + const snippetMap = {}; + let m; + while ((m = importRe.exec(content)) !== null) { + snippetMap[m[1]] = m[2]; + } + const names = Object.keys(snippetMap); + if (names.length === 0) return content; + + let result = content; + for (const name of names) { + const importPath = snippetMap[name]; + // Resolve: paths are like '/docs/snippets/foo.md' (root-absolute) or + // relative ('../snippets/foo.md'). Map to a real file under the repo. + let snippetContent = this.readSnippetFile(importPath); + if (snippetContent === null) continue; + // Strip the snippet's own frontmatter and import/export lines. + snippetContent = snippetContent + .replace(/^---[\s\S]*?---\n/, '') + .replace(/^import\s+.*$/gm, '') + .replace(/^export\s+.*$/gm, '') + .trim(); + + // Replace both self-closing () and paired (...) + // usages with the snippet content. Props (e.g. components={...}) are + // dropped — the textual content is what matters for the LLM output. + const selfClosing = new RegExp(`<${name}\\b[^>]*?/>`, 'g'); + const paired = new RegExp(`<${name}\\b[^>]*?>[\\s\\S]*?<\\/${name}>`, 'g'); + result = result + .replace(paired, `\n\n${snippetContent}\n\n`) + .replace(selfClosing, `\n\n${snippetContent}\n\n`); + } + + return result; + } + + /** Read a snippet file referenced by an import path, or null if not found. */ + readSnippetFile(importPath) { + // Candidate locations, in order of likelihood. + const idx = importPath.indexOf('snippets/'); + const relFromSnippets = idx !== -1 ? importPath.slice(idx) : importPath; // snippets/foo.md + const candidates = [ + // '/docs/snippets/foo.md' → docsDir/snippets/foo.md + path.join(this.docsDir, relFromSnippets), + // already-absolute-ish '/docs/...' resolved from repo root (docsDir parent) + path.join(this.docsDir, importPath.replace(/^\/?docs\//, '')), + importPath.replace(/^\//, ''), + ]; + for (const c of candidates) { + try { + if (fs.existsSync(c)) { + return fs.readFileSync(c, 'utf-8'); + } + } catch (e) { /* try next */ } + } + return null; + } + cleanContent(content) { - return content + // Inline snippet-backed components BEFORE imports are stripped: components + // imported from /docs/snippets/*.md are used self-closing (e.g. , + // ), so the stripper would delete them and their snippet + // content — which is never emitted otherwise, as snippets aren't in the + // sidebar. Resolve the imports and inline the snippet Markdown in place. + content = this.inlineSnippetComponents(content); + + let cleaned = content // Deletes frontmatter metadata .replace(/^---[\s\S]*?---\n/, '') - // Deletes React/MDX components - .replace(/<[A-Z][a-zA-Z]*[^>]*>[\s\S]*?<\/[A-Z][a-zA-Z]*>/g, '') - .replace(/<[A-Z][a-zA-Z]*[^>]*\/>/g, '') // Deletes imports .replace(/^import\s+.*$/gm, '') // Deletes exports - .replace(/^export\s+.*$/gm, '') - // Cleans up empty lines - .replace(/\n\s*\n\s*\n/g, '\n\n') + .replace(/^export\s+.*$/gm, ''); + + // Transform components into readable text + cleaned = this.transformEndpointComponents(cleaned); + + // Transform legacy // into readable text + cleaned = this.transformApiCallComponents(cleaned); + + // Transform inline content-bearing components (e.g. ) into + // Markdown BEFORE the generic stripper deletes them along with their props. + cleaned = this.transformInlineComponents(cleaned); + + // Preserve the `title=` prop of title-bearing paired components (their + // children survive the stripper, but the title — a section/step heading — + // would otherwise be lost). + cleaned = this.transformTitledComponents(cleaned); + + // Remove remaining React/MDX components (balanced tag matching) + cleaned = this.stripJsxComponents(cleaned); + + // Cleans up empty lines + cleaned = cleaned.replace(/\n\s*\n\s*\n/g, '\n\n').trim(); + + return cleaned; + } + + /** + * Transform or children + * into structured, LLM-readable text. + */ + transformEndpointComponents(content) { + const result = []; + let remaining = content; + + while (true) { + const startIdx = remaining.indexOf('......... + * into structured, LLM-readable text. + */ + transformApiCallComponents(content) { + const result = []; + let remaining = content; + + while (true) { + const startIdx = remaining.indexOf(']+>/g, '').trim()); + lines.push(''); + } + + // Parameters + const params = this.extractArrayProp(propsString, 'params'); + if (params) { + lines.push('**Parameters:**'); + const paramItems = this.parseSimpleArray(params); + for (const param of paramItems) { + const name = this.getObjectField(param, 'name'); + const type = this.getObjectField(param, 'type'); + const required = param.includes("required: true") || param.includes("required:true"); + const desc = this.extractHtmlDescription(param, 'description'); + lines.push(`- \`${name}\` (${type}${required ? ', required' : ''}): ${desc}`); + } + lines.push(''); + } + + // Code examples + const codeTabs = this.extractArrayProp(propsString, 'codeTabs'); + if (codeTabs) { + const tabs = this.parseSimpleArray(codeTabs); + for (const tab of tabs) { + const label = this.getObjectField(tab, 'label') || 'Example'; + const code = this.extractTemplateLiteral(tab, 'code') || this.getObjectField(tab, 'code') || ''; + lines.push(`**${label}:**`); + lines.push('```'); + lines.push(code.trim()); + lines.push('```'); + lines.push(''); + } + } + + // Responses + const responses = this.extractArrayProp(propsString, 'responses'); + if (responses) { + const respItems = this.parseSimpleArray(responses); + for (const resp of respItems) { + const status = this.getObjectField(resp, 'status') || '200'; + const statusText = this.getObjectField(resp, 'statusText') || 'OK'; + + lines.push(`**Response ${status} ${statusText}:**`); + lines.push('```json'); + + // Try to extract body — could be a JSON.stringify call or a template literal + const body = this.extractResponseBody(resp); + lines.push(body.trim()); + lines.push('```'); + lines.push(''); + } + } + + // Children (extra notes, admonitions, etc.) + if (children && children.trim()) { + lines.push(children.trim()); + lines.push(''); + } + + return lines.join('\n'); + } + + /** + * Transform legacy children into readable text. + * Children typically contain ```code``` + * and ```code```. + */ + apiCallToText(children) { + if (!children || !children.trim()) return ''; + + const lines = []; + + // Extract Request blocks + const requestMatch = children.match(/]*title="([^"]*)"[^>]*>([\s\S]*?)<\/Request>/); + if (requestMatch) { + lines.push(`**${requestMatch[1] || 'Request'}:**`); + // The content is typically markdown with code blocks — keep it + lines.push(requestMatch[2].trim()); + lines.push(''); + } + + // Extract Response blocks + const responseMatch = children.match(/]*title="([^"]*)"[^>]*>([\s\S]*?)<\/Response>/); + if (responseMatch) { + lines.push(`**${responseMatch[1] || 'Response'}:**`); + lines.push(responseMatch[2].trim()); + lines.push(''); + } + + // If no Request/Response found, just return the children with tags stripped + if (lines.length === 0) { + return children.replace(/<\/?(?:Request|Response)[^>]*>/g, '').trim(); + } + + return lines.join('\n'); + } + + /** + * Remove remaining JSX components that weren't specially handled. + * Uses bracket-counting instead of broken regex. + */ + stripJsxComponents(content) { + // Match self-closing components: + // Use iterative approach to handle nested angle brackets in props + let result = content; + + // Simple self-closing tags (no nested < in props) + result = result.replace(/<[A-Z][a-zA-Z]*\s[^<]*?\/>/g, ''); + // Self-closing tags with no props + result = result.replace(/<[A-Z][a-zA-Z]*\s*\/>/g, ''); + + // Opening + closing pairs: iteratively remove innermost first + let prev = ''; + while (prev !== result) { + prev = result; + // Match components that don't contain other uppercase components inside + result = result.replace(/<([A-Z][a-zA-Z]*)[^>]*>([^<]*(?:<(?![A-Z/])[^<]*)*)<\/\1>/g, (match, tag, inner) => { + // Keep the inner text content (strip the wrapper tags) + return inner.trim(); + }); + } + + // Clean up any remaining bare closing tags + result = result.replace(/<\/[A-Z][a-zA-Z]*>/g, ''); + + return result; + } + + /** + * Transform inline content-bearing components into Markdown before the + * generic stripper removes them. Currently handles , whose + * label + URL live in props (so it is otherwise deleted wholesale, losing + * ~530 links across the docs). + */ + transformInlineComponents(content) { + let result = content; + + // → [LABEL](URL). Props may appear in + // either order, with single or double quotes, optional trailing slash, and + // arbitrary whitespace/newlines. Match the whole self-closing tag, then pull + // `to` and `text` out individually. + result = result.replace(/]*?)\/>/g, (match, props) => { + const to = this.extractStringProp(props, 'to'); + const text = this.extractStringProp(props, 'text'); + if (to && text) return `[${text}](${to})`; + if (to) return `[${to}](${to})`; + if (text) return text; + return ''; + }); + + // → a Markdown + // bullet linking to the page. These navigation cards (148 of them, all + // self-closing) are otherwise deleted, dropping the landing-page structure. + result = result.replace(/]*?)\/>/g, (match, props) => { + const title = this.extractStringProp(props, 'title'); + const description = this.extractStringProp(props, 'description'); + const link = this.extractStringProp(props, 'link'); + if (!title && !link) return ''; + const label = title || link; + const linked = link ? `[${label}](${link})` : label; + return description ? `- ${linked}: ${description}` : `- ${linked}`; + }); + + // + // Carries the "affects plugins? / handled by a codemod?" facts in props (52 + // uses on v4→v5 breaking-change pages). Render them as a short fact list. + result = result.replace(/]*?)\/>/g, (match, props) => { + // Boolean props can appear bare (e.g. `plugins`) or as plugins={true}. + const hasFlag = (name) => + new RegExp(`(?:^|\\s)${name}(?=\\s|$|=)`).test(props) && + !new RegExp(`${name}=\\{?false`).test(props); + const plugins = hasFlag('plugins'); + const codemodPartly = hasFlag('codemodPartly'); + const codemod = hasFlag('codemod'); + const codemodName = this.extractStringProp(props, 'codemodName'); + const codemodLink = this.extractStringProp(props, 'codemodLink'); + const info = this.extractStringProp(props, 'info'); + + const pluginsAnswer = plugins ? 'Yes' : 'No'; + let codemodAnswer = 'No'; + if (codemodPartly) codemodAnswer = 'Partly'; + else if (codemod || codemodName) codemodAnswer = 'Yes'; + + const lines = [ + `- Is this breaking change affecting plugins? ${pluginsAnswer}`, + `- Is this breaking change automatically handled by a codemod? ${codemodAnswer}`, + ]; + if (codemodName && codemodLink) { + lines.push(` - Codemod: [${codemodName}](${codemodLink})`); + } else if (codemodName) { + lines.push(` - Codemod: \`${codemodName}\``); + } else if (codemodLink) { + lines.push(` - Codemod: [the codemod's code](${codemodLink})`); + } + if (info) lines.push(`- ${info}`); + return lines.join('\n'); + }); + + return result; + } + + /** + * For paired components that carry a heading/label in a `title=` prop + * (StepDetails, SubtleCallout, IdentityCardItem), surface that title as a + * bold line before the children. The generic stripper keeps the children but + * drops the title, losing the step/section heading. Uses the bracket-aware + * extractJsxBlock so nested components and braces in props are handled. + */ + transformTitledComponents(content) { + const TITLED = ['StepDetails', 'SubtleCallout', 'IdentityCardItem']; + let result = content; + + for (const name of TITLED) { + const out = []; + let remaining = result; + while (true) { + const startIdx = remaining.indexOf(`<${name}`); + if (startIdx === -1) { out.push(remaining); break; } + out.push(remaining.substring(0, startIdx)); + + const extracted = this.extractJsxBlock(remaining, startIdx, name); + if (!extracted) { + out.push(remaining.substring(startIdx, startIdx + name.length + 1)); + remaining = remaining.substring(startIdx + name.length + 1); + continue; + } + + const { propsString, children, fullMatch } = extracted; + const title = this.extractStringProp(propsString, 'title'); + const body = (children || '').trim(); + const pieces = []; + if (title) pieces.push(`**${title}**`); + if (body) pieces.push(body); + // Surround with blank lines so the title reads as its own block. + out.push(pieces.length ? `\n${pieces.join('\n\n')}\n` : body); + + remaining = remaining.substring(startIdx + fullMatch.length); + } + result = out.join(''); + } + + return result; + } + + // ---- Prop extraction helpers ---- + + // These prop scanners now delegate to the shared module (single source of + // truth, also used by generate-llms-code.js). The shared versions fix a + // template-literal interpolation bug present in the old inline copies. + extractStringProp(propsString, propName) { + return apiComponents.extractStringProp(propsString, propName); + } + + extractArrayProp(propsString, propName) { + return apiComponents.extractArrayProp(propsString, propName); + } + + parseSimpleArray(arrayContent) { + return apiComponents.parseSimpleArray(arrayContent); + } + + getObjectField(objString, fieldName) { + return apiComponents.getObjectField(objString, fieldName); + } + + /** + * Extract an HTML-rich description field from a JSX object string. + * Handles descriptions containing , , etc. by finding the matching quote + * through bracket counting instead of simple regex. + */ + extractHtmlDescription(objString, fieldName) { + const patterns = [ + `${fieldName}: '`, + `${fieldName}: "`, + `${fieldName}:'`, + `${fieldName}:"`, + ]; + + let startIdx = -1; + let quote = "'"; + + for (const pat of patterns) { + const idx = objString.indexOf(pat); + if (idx !== -1) { + startIdx = idx + pat.length; + quote = pat[pat.length - 1]; + break; + } + } + + if (startIdx === -1) return ''; + + // Find the matching closing quote, accounting for escaped quotes + let i = startIdx; + const len = objString.length; + while (i < len) { + if (objString[i] === quote && objString[i - 1] !== '\\') { + break; + } + i++; + } + + const raw = objString.substring(startIdx, i); + + // Convert HTML to readable text + return raw + .replace(/]*>([^<]*)<\/a>/g, '$2 ($1)') + .replace(/([^<]*)<\/code>/g, '`$1`') + .replace(/<[^>]+>/g, '') + .replace(/\s+/g, ' ') .trim(); } + /** Extract a template literal field: field: `value` (delegates to shared module). */ + extractTemplateLiteral(objString, fieldName) { + return apiComponents.extractTemplateLiteral(objString, fieldName); + } + + /** Extract response body — handles JSON.stringify(...) calls and template literals */ + extractResponseBody(respString) { + // Check for JSON.stringify call + const stringifyIdx = respString.indexOf('JSON.stringify('); + if (stringifyIdx !== -1) { + // Extract the first argument to JSON.stringify + let i = stringifyIdx + 'JSON.stringify('.length; + let depth = 1; + let inString = null; + const len = respString.length; + const start = i; + + while (i < len && depth > 0) { + const ch = respString[i]; + const prev = i > 0 ? respString[i - 1] : ''; + + if (inString) { + if (ch === inString && prev !== '\\') inString = null; + i++; continue; + } + if (ch === '"' || ch === "'") { inString = ch; i++; continue; } + if (ch === '(' || ch === '{' || ch === '[') { depth++; i++; continue; } + if (ch === ')' || ch === '}' || ch === ']') { + depth--; + if (depth === 0) break; + i++; + continue; + } + i++; + } + + // Get the object literal, try to format it as JSON + const objLiteral = respString.substring(start, i).trim(); + // Remove trailing ", null, 2" args if the closing paren was for stringify + const firstArgEnd = this.findFirstArgEnd(objLiteral); + const firstArg = firstArgEnd !== -1 ? objLiteral.substring(0, firstArgEnd) : objLiteral; + + // Convert JS object literal to approximate JSON + return this.jsObjectToReadableJson(firstArg); + } + + // Check for template literal body + const body = this.extractTemplateLiteral(respString, 'body'); + if (body) return body; + + // Check for string body + const strBody = this.getObjectField(respString, 'body'); + if (strBody) return strBody; + + return '(response body)'; + } + + /** Find end of first argument in a potentially multi-arg string like "obj, null, 2" */ + findFirstArgEnd(str) { + let depth = 0; + let inString = null; + + for (let i = 0; i < str.length; i++) { + const ch = str[i]; + const prev = i > 0 ? str[i - 1] : ''; + + if (inString) { + if (ch === inString && prev !== '\\') inString = null; + continue; + } + if (ch === '"' || ch === "'") { inString = ch; continue; } + if (ch === '{' || ch === '[' || ch === '(') { depth++; continue; } + if (ch === '}' || ch === ']' || ch === ')') { depth--; continue; } + if (ch === ',' && depth === 0) return i; + } + + return -1; + } + + /** Convert a JS object literal to readable JSON-like text */ + jsObjectToReadableJson(jsObj) { + try { + // Simple transforms: unquoted keys -> quoted, single quotes -> double quotes + let json = jsObj + // Add quotes around unquoted keys + .replace(/(\s)(\w+)\s*:/g, '$1"$2":') + // Handle keys at start of line + .replace(/^(\s*)(\w+)\s*:/gm, '$1"$2":') + // Single quotes to double quotes (simple cases) + .replace(/:\s*'([^']*)'/g, ': "$1"') + // Remove trailing commas + .replace(/,(\s*[}\]])/g, '$1'); + + // Try to parse and re-format + const parsed = JSON.parse(json); + return JSON.stringify(parsed, null, 2); + } catch { + // If parsing fails, return the raw object literal cleaned up + return jsObj.trim(); + } + } + generateLlmsTxt(pages) { const lines = [`# ${this.siteName}`, '']; - + pages.forEach(page => { const description = page.description || 'No description available'; - lines.push(`- [${page.title}](${page.url}): ${description}`); + // Point at the clean Markdown twin (.md) rather than the HTML page, + // so agents following llms.txt fetch parseable Markdown directly. Pages + // without a path (e.g. the homepage) keep their original URL. + const mdUrl = this.toMarkdownUrl(page.url); + lines.push(`- [${page.title}](${mdUrl}): ${description}`); }); - + return lines.join('\n'); } + /** Map a page URL to its .md twin, leaving path-less URLs (homepage) as-is. */ + toMarkdownUrl(url) { + if (!url) return url; + if (/\.md$/i.test(url)) return url; + // Has a path beyond the origin? (e.g. https://docs.strapi.io/cms/api/rest) + const m = url.match(/^(https?:\/\/[^/]+)(\/.+?)\/?$/); + if (!m) return url; // origin only → homepage, no .md + return `${m[1]}${m[2]}.md`; + } + generateLlmsFullTxt(pages) { const sections = []; diff --git a/docusaurus/scripts/lib/api-components.js b/docusaurus/scripts/lib/api-components.js new file mode 100644 index 0000000000..4c58f1ce40 --- /dev/null +++ b/docusaurus/scripts/lib/api-components.js @@ -0,0 +1,545 @@ +/** + * Shared helpers for extracting content from the API layout components + * (, , , ) used across the docs. + * + * The code that backs these components lives in their PROPS (e.g. Endpoint's + * `codeTabs={[...]}` and `responses={[...]}`, or fenced code inside the + * children of /), NOT in plain Markdown fences. The + * llms-full.txt generator (generate-llms.js) already turns these into readable + * text; this module exposes pure functions so the llms-code.txt generator + * (generate-llms-code.js) can pull the SAME code out as structured snippets. + * + * Everything here is a pure function (no `this`), so both generators can share + * it without duplicating the JSX-scanning logic. + */ + +'use strict'; + +/** + * Extract a full JSX block starting at `startIdx` for a given component name. + * Handles nested braces/brackets/template literals in props and children. + * Returns { fullMatch, propsString, children } or null. + * + * (Ported verbatim in behavior from generate-llms.js so the two generators + * scan components identically.) + */ +function extractJsxBlock(text, startIdx, componentName) { + let i = startIdx + componentName.length + 1; // skip past `` or `>`) + let depth = { brace: 0, bracket: 0, paren: 0 }; + let inString = null; // null, '"', "'", '`' + // Stack of template-literal interpolation depths: when we enter `${`, we push + // the current brace depth so the matching `}` can pop us back into the + // template literal instead of being counted as a stray closing brace. Without + // this, every `${...}` leaves brace depth permanently unbalanced and the + // opening-tag scan overruns the whole component. + const tplInterp = []; + const propsStart = i; + let selfClosing = false; + let openTagEnd = -1; + + while (i < len) { + const ch = text[i]; + const prev = i > 0 ? text[i - 1] : ''; + + if (inString) { + if (inString === '`') { + // Enter an interpolation `${ ... }` — leave string mode and track depth. + if (ch === '$' && i + 1 < len && text[i + 1] === '{' && prev !== '\\') { + tplInterp.push(inString); + inString = null; + depth.brace++; + i += 2; + continue; + } + if (ch === '`' && prev !== '\\') { + inString = null; + } + } else if (ch === inString && prev !== '\\') { + inString = null; + } + i++; + continue; + } + + if (ch === '"' || ch === "'" || ch === '`') { + inString = ch; + i++; + continue; + } + + if (ch === '{') { depth.brace++; i++; continue; } + if (ch === '}') { + depth.brace--; + // If this `}` closes a template-literal interpolation, resume the + // template literal we suspended on `${`. + if (tplInterp.length > 0) { + inString = tplInterp.pop(); + } + i++; + continue; + } + if (ch === '[') { depth.bracket++; i++; continue; } + if (ch === ']') { depth.bracket--; i++; continue; } + if (ch === '(') { depth.paren++; i++; continue; } + if (ch === ')') { depth.paren--; i++; continue; } + + if (depth.brace === 0 && depth.bracket === 0 && depth.paren === 0) { + if (ch === '/' && i + 1 < len && text[i + 1] === '>') { + selfClosing = true; + openTagEnd = i + 2; + break; + } + if (ch === '>') { + openTagEnd = i + 1; + break; + } + } + + i++; + } + + if (openTagEnd === -1) return null; + + const propsString = text.substring(propsStart, i).trim(); + + if (selfClosing) { + return { + fullMatch: text.substring(startIdx, openTagEnd), + propsString, + children: '', + }; + } + + // Phase 2: Find closing tag + const closingTag = ``; + let tagDepth = 1; + let j = openTagEnd; + const openTag = `<${componentName}`; + + while (j < len && tagDepth > 0) { + if (text.substring(j, j + openTag.length) === openTag) { + tagDepth++; + j += openTag.length; + continue; + } + if (text.substring(j, j + closingTag.length) === closingTag) { + tagDepth--; + if (tagDepth === 0) break; + j += closingTag.length; + continue; + } + j++; + } + + if (tagDepth !== 0) return null; + + const children = text.substring(openTagEnd, j); + const fullEnd = j + closingTag.length; + + return { + fullMatch: text.substring(startIdx, fullEnd), + propsString, + children, + }; +} + +// ---- Prop extraction helpers (pure) ---- + +/** Extract a simple string prop: prop="value" or prop='value' */ +function extractStringProp(propsString, propName) { + const regex = new RegExp(`${propName}=["']([^"']*?)["']`); + const match = propsString.match(regex); + return match ? match[1] : null; +} + +/** Extract an array prop: prop={[...]} — returns the raw string inside [...] */ +function extractArrayProp(propsString, propName) { + const marker = `${propName}={[`; + const idx = propsString.indexOf(marker); + if (idx === -1) return null; + + let i = idx + marker.length; + let depth = 1; + let inString = null; + const tplInterp = []; + const len = propsString.length; + + while (i < len && depth > 0) { + const ch = propsString[i]; + const prev = i > 0 ? propsString[i - 1] : ''; + + if (inString) { + if (inString === '`') { + if (ch === '$' && i + 1 < len && propsString[i + 1] === '{' && prev !== '\\') { + tplInterp.push(inString); + inString = null; + depth++; + i += 2; continue; + } + if (ch === '`' && prev !== '\\') inString = null; + } else if (ch === inString && prev !== '\\') { + inString = null; + } + i++; continue; + } + + if (ch === '"' || ch === "'" || ch === '`') { inString = ch; i++; continue; } + if (ch === '[' || ch === '{' || ch === '(') { depth++; i++; continue; } + if (ch === ']') { depth--; if (depth === 0) break; i++; continue; } + if (ch === '}' || ch === ')') { + depth--; + if (ch === '}' && tplInterp.length > 0) { inString = tplInterp.pop(); } + i++; continue; + } + i++; + } + + return propsString.substring(idx + marker.length, i); +} + +/** Split an array string into individual object items (top-level { ... } blocks) */ +function parseSimpleArray(arrayContent) { + const items = []; + let depth = 0; + let inString = null; + const tplInterp = []; + let start = -1; + + for (let i = 0; i < arrayContent.length; i++) { + const ch = arrayContent[i]; + const prev = i > 0 ? arrayContent[i - 1] : ''; + + if (inString) { + if (inString === '`') { + if (ch === '$' && i + 1 < arrayContent.length && arrayContent[i + 1] === '{' && prev !== '\\') { + tplInterp.push(inString); + inString = null; + depth++; + i++; continue; + } + if (ch === '`' && prev !== '\\') inString = null; + } else if (ch === inString && prev !== '\\') { + inString = null; + } + continue; + } + + if (ch === '"' || ch === "'" || ch === '`') { inString = ch; continue; } + + if (ch === '{') { + if (depth === 0) start = i; + depth++; + } else if (ch === '}') { + depth--; + if (tplInterp.length > 0) { + inString = tplInterp.pop(); + } else if (depth === 0 && start !== -1) { + items.push(arrayContent.substring(start, i + 1)); + start = -1; + } + } + } + + return items; +} + +/** Extract a simple field value from an object string: field: 'value' or field: "value" */ +function getObjectField(objString, fieldName) { + const regex = new RegExp(`${fieldName}:\\s*['"]([\\s\\S]*?)(? 0 ? objString[i - 1] : ''; + // Escaped `\${` and `\`` are literal characters inside the value, not + // interpolation/terminator — skip them. + if (ch === '$' && i + 1 < len && objString[i + 1] === '{' && prev !== '\\') { + depth++; + i += 2; + continue; + } + if (ch === '}' && depth > 0) { + depth--; + i++; + continue; + } + if (ch === '`' && depth === 0 && prev !== '\\') { + return objString.substring(idx, i); + } + i++; + } + + return objString.substring(idx); +} + +// ---- Language inference ---- + +/** + * Map an Endpoint codeTab label (e.g. "cURL", "JavaScript", "GraphQL") to a + * fenced-code language hint for llms-code.txt. + */ +/** + * Un-escape a code string pulled out of a JSX template literal: the MDX source + * escapes backticks and `${` so they don't terminate the literal, but the real + * code uses them literally. + */ +function unescapeTemplateCode(code) { + return code + .replace(/\\`/g, '`') + .replace(/\\\$\{/g, '${'); +} + +function labelToLanguage(label, code) { + const l = (label || '').toLowerCase(); + if (l.includes('curl')) return 'bash'; + if (l.includes('graphql')) return 'graphql'; + if (l.includes('typescript') || l === 'ts') return 'typescript'; + if (l.includes('javascript') || l === 'js' || l.includes('node')) return 'javascript'; + if (l.includes('json')) return 'json'; + if (l.includes('python')) return 'python'; + if (l.includes('php')) return 'php'; + if (l.includes('ruby')) return 'ruby'; + // Label is generic (e.g. "Shorthand", "Example") — guess from the code itself. + return detectLanguageFromCode(code) || 'bash'; +} + +/** + * Best-effort language detection from a code body, used when the codeTab label + * is generic. Conservative: only returns a language on a clear signal. + */ +function detectLanguageFromCode(code) { + if (!code) return null; + const c = code.trim(); + // GraphQL query/mutation block. + if (/^\s*(query|mutation|subscription|fragment)\b/.test(c) || /^\s*\{[\s\S]*\}\s*$/.test(c) && /\b(edges|nodes|node)\b/.test(c)) { + return 'graphql'; + } + // JS/TS signals. + if (/\b(await|const|let|require\(|=>|strapi\.|fetch\(|import\s)/.test(c)) { + return 'javascript'; + } + // Shell / curl. + if (/^\s*(curl|GET|POST|PUT|DELETE|PATCH)\b/.test(c) || /^\s*\$\s/.test(c)) { + return 'bash'; + } + // JSON object/array. + if (/^\s*[{[]/.test(c) && /["}\]]\s*$/.test(c)) { + return 'json'; + } + return null; +} + +/** + * Extract code snippets carried by components in `content`. + * Each snippet: { language, code, description, variantGroupId, tabLabel }. + * + * `codeTabs` entries become request snippets (one per tab, grouped as variants + * of the same endpoint); `responses` entries become JSON response snippets. + */ +function extractEndpointSnippets(content, sectionTitle) { + const snippets = []; + let remaining = content; + let offset = 0; + let endpointIndex = 0; + + while (true) { + const startIdx = remaining.indexOf('// components. + * The code lives in fenced blocks INSIDE the children of Request/Response, so + * we surface those fences with a sensible language + description. + * + * Each snippet: { language, code, description, variantGroupId, tabLabel }. + */ +function extractApiCallSnippets(content, sectionTitle) { + const snippets = []; + let remaining = content; + let offset = 0; + let apiCallIndex = 0; + + while (true) { + const startIdx = remaining.indexOf(']*?(?:title=["']([^"']*)["'])?[^>]*>([\\s\\S]*?)<\\/${part}>`, 'g'); + let m; + while ((m = re.exec(children)) !== null) { + const partTitle = m[1] || part; + const inner = m[2] || ''; + // Pull fenced code blocks out of the part's children. + const fenceRe = /```(\w+)?\n?([\s\S]*?)```/g; + let f; + while ((f = fenceRe.exec(inner)) !== null) { + const lang = f[1] || (part === 'Response' ? 'json' : 'bash'); + const code = (f[2] || '').trim(); + if (code) { + snippets.push({ + language: lang, + code, + description: partTitle, + variantGroupId: `${variantGroupId}:${part.toLowerCase()}`, + tabLabel: partTitle, + }); + } + } + } + } + + offset = startIdx + fullMatch.length; + } + + return snippets; +} + +/** + * Extract all API-component code snippets (Endpoint + ApiCall) from a page's + * content, tagged with the section heading they appear under. + * + * Returns an array of { language, code, description, section, variantGroupId, + * tabLabel }. + */ +function extractApiComponentSnippets(content, currentSectionFor) { + // currentSectionFor(index) → section title for a character offset, or a + // simpler approach: callers usually pass per-section content already. Here we + // operate on the whole doc and attach the nearest preceding heading. + const all = []; + + // Build a quick offset→section map from ## / ### headings. + const headingRe = /^(#{2,4})\s+(.+?)\s*$/gm; + const headings = []; + let hm; + while ((hm = headingRe.exec(content)) !== null) { + headings.push({ index: hm.index, title: hm[2].replace(/\{#[^}]+\}/, '').trim() }); + } + const sectionAt = (idx) => { + let title = ''; + for (const h of headings) { + if (h.index <= idx) title = h.title; else break; + } + return title; + }; + + // For section tagging we need offsets, so re-scan with offsets here. + const tagAndPush = (componentName, extractFn) => { + let offset = 0; + while (true) { + const startIdx = content.indexOf(`<${componentName}`, offset); + if (startIdx === -1) break; + const block = extractJsxBlock(content, startIdx, componentName); + if (!block) { offset = startIdx + componentName.length + 1; continue; } + const section = sectionAt(startIdx); + const localSnippets = extractFn(block.fullMatch, section); + for (const s of localSnippets) { + all.push({ ...s, section }); + } + offset = startIdx + block.fullMatch.length; + } + }; + + tagAndPush('Endpoint', (frag, section) => extractEndpointSnippets(frag, section)); + tagAndPush('ApiCall', (frag, section) => extractApiCallSnippets(frag, section)); + + return all; +} + +module.exports = { + extractJsxBlock, + extractStringProp, + extractArrayProp, + parseSimpleArray, + getObjectField, + extractTemplateLiteral, + labelToLanguage, + extractEndpointSnippets, + extractApiCallSnippets, + extractApiComponentSnippets, +}; diff --git a/docusaurus/sidebars.js b/docusaurus/sidebars.js index bc344ead8d..1b257ab057 100644 --- a/docusaurus/sidebars.js +++ b/docusaurus/sidebars.js @@ -53,6 +53,7 @@ const sidebars = { label: 'Features', collapsible: false, className: 'category-cms-features', + link: { type: 'generated-index', slug: '/cms/features' }, items: [ { type: 'doc', @@ -97,17 +98,11 @@ const sidebars = { type: 'doc', label: 'MCP server', id: 'cms/features/strapi-mcp-server', - customProps: { - new: true, - }, }, { type: 'doc', label: 'Preview', id: 'cms/features/preview', - customProps: { - new: false, - }, }, { type: 'doc', @@ -133,14 +128,12 @@ const sidebars = { type: 'doc', label: 'Users & Permissions', id: 'cms/features/users-permissions', - customProps: { - updated: true, - }, }, { type: 'category', label: 'Strapi plugins', collapsed: true, + link: { type: 'generated-index', slug: '/cms/plugins' }, items: [ { type: 'doc', @@ -166,22 +159,17 @@ const sidebars = { label: 'AI', collapsible: false, className: 'category-cms-ai', + link: { type: 'generated-index', slug: '/cms/ai' }, items: [ { type: 'doc', label: 'Strapi AI for content managers', id: 'cms/ai/for-content-managers', - customProps: { - updated: true, - }, }, { type: 'doc', label: 'AI for developers and docs', id: 'cms/ai/for-developers', - customProps: { - updated: true, - }, }, { type: 'doc', @@ -226,9 +214,6 @@ const sidebars = { type: 'doc', label: 'Strapi Client', id: 'cms/api/client', - customProps: { - new: false, - }, }, 'cms/api/openapi', 'cms/api/graphql', @@ -269,9 +254,6 @@ const sidebars = { type: 'category', label: 'Admin panel', collapsed: true, - customProps: { - updated: false, - }, items: [ { type: 'link', @@ -322,9 +304,6 @@ const sidebars = { type: 'link', label: 'Strapi AI', href: '/cms/configurations/admin-panel#strapi-ai', - customProps: { - new: true, - }, }, { type: 'link', @@ -342,9 +321,6 @@ const sidebars = { { type: 'doc', id: 'cms/configurations/cron', - customProps: { - updated: false, - }, }, { type: 'category', @@ -366,6 +342,17 @@ const sidebars = { 'cms/configurations/middlewares', 'cms/configurations/plugins', 'cms/configurations/server', + { + type: 'category', + label: 'Guides', + link: { type: 'generated-index', title: 'Configuration guides', slug: '/cms/configurations/guides' }, + items: [ + 'cms/configurations/guides/access-cast-environment-variables', + 'cms/configurations/guides/access-configuration-values', + 'cms/configurations/guides/configure-sso', + 'cms/configurations/guides/rbac', + ], + }, ], }, { // Development @@ -417,10 +404,6 @@ const sidebars = { type: 'category', label: 'Admin panel customization', collapsed: true, - customProps: { - updated: false, - // tooltip: 'This section has been reorganized, see details below.', - }, items: [ // { // type: 'html', @@ -462,9 +445,6 @@ const sidebars = { type: 'doc', label: 'Homepage customization', id: 'cms/admin-panel-customization/homepage', - customProps: { - new: false, - }, }, 'cms/error-handling', 'cms/strapi-utils', @@ -513,6 +493,7 @@ const sidebars = { type: 'category', label: 'Plugins development', className: 'category-cms-plugins', + link: { type: 'generated-index', slug: '/cms/plugins-development' }, collapsible: false, collapsed: false, items: [ @@ -540,9 +521,6 @@ const sidebars = { type: 'category', label: 'Admin Panel API', collapsed: true, - customProps: { - new: true, - }, items: [ 'cms/plugins-development/admin-panel-api', 'cms/plugins-development/admin-navigation-settings', @@ -555,9 +533,6 @@ const sidebars = { type: 'doc', id: 'cms/plugins-development/admin-fetch-client', label: 'Fetch client', - customProps: { - new: true, - }, }, ], }, @@ -565,9 +540,6 @@ const sidebars = { type: 'category', label: 'Server API', collapsed: true, - customProps: { - new: true, - }, items: [ 'cms/plugins-development/server-api', 'cms/plugins-development/server-lifecycle', @@ -630,16 +602,10 @@ const sidebars = { type: 'doc', label: 'Cloud fundamentals', id: 'cloud/getting-started/cloud-fundamentals', - customProps: { - new: false, - }, }, { type: 'category', label: 'Project deployment', - customProps: { - updated: false, - }, items: [ { type: 'doc', @@ -648,25 +614,16 @@ const sidebars = { { type: 'doc', id: 'cloud/getting-started/deployment', - customProps: { - updated: false, - }, }, { type: 'doc', id: 'cloud/getting-started/deployment-cli', - customProps: { - new: false, - }, }, ], }, { type: 'doc', id: 'cloud/getting-started/usage-billing', - customProps: { - updated: false, - }, }, // 'cloud/getting-started/caching', { @@ -688,9 +645,6 @@ const sidebars = { type: 'doc', label: 'Project settings', id: 'cloud/projects/settings', - customProps: { - updated: true, - }, }, 'cloud/projects/collaboration', 'cloud/projects/logs', @@ -710,15 +664,13 @@ const sidebars = { collapsible: false, className: 'category-cloud-account', label: 'Account management', + link: { type: 'generated-index', slug: '/cloud/account' }, items: [ 'cloud/account/account-settings', { type: 'doc', id: 'cloud/account/account-billing', label: 'Account billing & invoices', - customProps: { - updated: false, - }, }, ], }, @@ -733,9 +685,6 @@ const sidebars = { type: 'doc', id: 'cloud/cli/cloud-cli', label: 'Strapi Cloud CLI', - customProps: { - new: false, - }, }, ], }, @@ -745,39 +694,28 @@ const sidebars = { collapsible: false, className: 'category-cloud-configurations', label: 'Advanced configuration', + link: { type: 'generated-index', slug: '/cloud/advanced' }, items: [ 'cloud/advanced/database', { type: 'doc', id: 'cloud/advanced/email', label: 'Email provider for Cloud', - customProps: { - new: false, - }, }, { type: 'doc', id: 'cloud/advanced/upload', label: 'Upload provider for Cloud', - customProps: { - new: false, - }, }, { type: 'doc', id: 'cloud/advanced/upload-size-limits', label: 'Upload size limits for Cloud', - customProps: { - new: true, - }, }, { type: 'doc', id: 'cloud/advanced/middlewares', label: 'Middleware configuration for Cloud', - customProps: { - new: false, - }, }, ], }, diff --git a/docusaurus/src/components/AiToolbar/AiToolbar.jsx b/docusaurus/src/components/AiToolbar/AiToolbar.jsx index 401e15c5cd..70b7e426da 100644 --- a/docusaurus/src/components/AiToolbar/AiToolbar.jsx +++ b/docusaurus/src/components/AiToolbar/AiToolbar.jsx @@ -8,10 +8,32 @@ const AiToolbar = () => { 'copy-markdown': 'idle' }); const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const [viewMode, setViewMode] = useState('elegant'); const dropdownRef = useRef(null); + // Track the active view mode (read from the DOM + the view-mode-change event, + // to avoid depending on the React context being an ancestor here). + useEffect(() => { + const read = () => + setViewMode(document.documentElement.dataset.viewMode || 'elegant'); + read(); + const onChange = (e) => + setViewMode((e.detail && e.detail.mode) || document.documentElement.dataset.viewMode || 'elegant'); + window.addEventListener('view-mode-change', onChange); + return () => window.removeEventListener('view-mode-change', onChange); + }, []); + const primaryAction = getPrimaryAction(); - const dropdownActions = getDropdownActions(); + // "View as Markdown" appears in exactly one place at a time: + // - in elegant/AI modes: as a dropdown entry in the toolbar; + // - in markdown mode: as the standalone button to the right of the toolbar + // (and removed from the dropdown to avoid duplication). + const viewMarkdownAction = getDropdownActions().find((a) => a.id === 'view-markdown'); + const isMarkdownMode = viewMode === 'markdown'; + const dropdownActions = getDropdownActions().filter((a) => { + if (a.id === 'view-markdown' && isMarkdownMode) return false; + return true; + }); // Close dropdown when clicking outside useEffect(() => { @@ -68,6 +90,12 @@ const AiToolbar = () => { await executeAction(action, context); }; + // Standalone "View as Markdown" button (right side of the toolbar). + const handleViewMarkdown = async () => { + if (!viewMarkdownAction) return; + await executeAction(viewMarkdownAction, { closeDropdown }); + }; + // Toggle dropdown const toggleDropdown = () => { setIsDropdownOpen(!isDropdownOpen); @@ -127,8 +155,8 @@ const AiToolbar = () => { className={`ai-toolbar__dropdown-item ${action.description ? '' : 'ai-toolbar__dropdown-item--no-description'}`} title={action.description} > - @@ -147,6 +175,20 @@ const AiToolbar = () => { )} + + {/* Standalone "View this page as .md" button — shown ONLY in markdown + mode (in other modes the action lives in the toolbar dropdown). Sits + just to the right of the toolbar group. */} + {viewMarkdownAction && isMarkdownMode && ( + + )} ); }; diff --git a/docusaurus/src/components/AiToolbar/actions/actionRegistry.js b/docusaurus/src/components/AiToolbar/actions/actionRegistry.js index e5a962e219..80d48e5f22 100644 --- a/docusaurus/src/components/AiToolbar/actions/actionRegistry.js +++ b/docusaurus/src/components/AiToolbar/actions/actionRegistry.js @@ -1,10 +1,12 @@ import { copyMarkdownAction } from './copyMarkdown'; +import { viewMarkdownAction } from './viewMarkdown'; import { navigateAction } from './navigate'; import { openLLMAction } from './openLLM'; // Central registry of all available actions export const actionHandlers = { 'copy-markdown': copyMarkdownAction, + 'view-markdown': viewMarkdownAction, navigate: navigateAction, 'open-llm': openLLMAction, }; diff --git a/docusaurus/src/components/AiToolbar/actions/copyMarkdown.js b/docusaurus/src/components/AiToolbar/actions/copyMarkdown.js index 037a224b08..2d4a64047f 100644 --- a/docusaurus/src/components/AiToolbar/actions/copyMarkdown.js +++ b/docusaurus/src/components/AiToolbar/actions/copyMarkdown.js @@ -1,4 +1,4 @@ -import { resolveDocContext, getRawMarkdownUrl } from '../utils/docContext'; +import { resolveDocContext, getRawMarkdownUrl, getCleanMarkdownUrl } from '../utils/docContext'; export const copyMarkdownAction = async (context) => { const { docId, docPath, updateActionState } = context; @@ -9,19 +9,37 @@ export const copyMarkdownAction = async (context) => { } const { docId: resolvedDocId, docPath: resolvedDocPath } = resolveDocContext(docId, docPath); - const markdownUrl = getRawMarkdownUrl({ docId: resolvedDocId, docPath: resolvedDocPath }); - if (!markdownUrl) { + // Prefer the clean, generated per-page .md (JSX resolved, snippets inlined, + // API code surfaced); fall back to the raw MDX on GitHub if the .md isn't + // available (older deploys, or a page not yet generated). + const cleanUrl = getCleanMarkdownUrl(); + const rawUrl = getRawMarkdownUrl({ docId: resolvedDocId, docPath: resolvedDocPath }); + + if (!cleanUrl && !rawUrl) { throw new Error('Unable to determine document path'); } - const response = await fetch(markdownUrl); - - if (!response.ok) { - throw new Error(`Failed to fetch markdown: ${response.status}`); + let markdownContent = null; + if (cleanUrl) { + try { + const res = await fetch(cleanUrl); + if (res.ok) markdownContent = await res.text(); + } catch (e) { + // network/CORS issue — fall back to the raw source below + } + } + if (markdownContent === null) { + if (!rawUrl) { + throw new Error('Unable to determine document path'); + } + const response = await fetch(rawUrl); + if (!response.ok) { + throw new Error(`Failed to fetch markdown: ${response.status}`); + } + markdownContent = await response.text(); } - const markdownContent = await response.text(); await navigator.clipboard.writeText(markdownContent); if (updateActionState) { diff --git a/docusaurus/src/components/AiToolbar/actions/viewMarkdown.js b/docusaurus/src/components/AiToolbar/actions/viewMarkdown.js new file mode 100644 index 0000000000..279193d7a6 --- /dev/null +++ b/docusaurus/src/components/AiToolbar/actions/viewMarkdown.js @@ -0,0 +1,30 @@ +import { resolveDocContext, getCleanMarkdownUrl, getRawMarkdownUrl } from '../utils/docContext'; + +/** + * Open the current page's clean Markdown (`.md`) in a new tab. + * This is the generated, JSX-resolved Markdown (same content as llms-full.txt), + * NOT the raw MDX source. Falls back to the raw GitHub MDX only if the clean + * URL can't be determined (e.g. homepage). + */ +export const viewMarkdownAction = (context) => { + const { docId, docPath, closeDropdown } = context; + + const cleanUrl = getCleanMarkdownUrl(); + let targetUrl = cleanUrl; + + if (!targetUrl) { + const { docId: resolvedDocId, docPath: resolvedDocPath } = resolveDocContext(docId, docPath); + targetUrl = getRawMarkdownUrl({ docId: resolvedDocId, docPath: resolvedDocPath }); + } + + if (!targetUrl) { + console.error('View Markdown action: unable to determine a Markdown URL'); + return; + } + + window.open(targetUrl, '_blank'); + + if (closeDropdown) { + closeDropdown(); + } +}; diff --git a/docusaurus/src/components/AiToolbar/config/aiToolsConfig.js b/docusaurus/src/components/AiToolbar/config/aiToolsConfig.js index adf336d847..a970d02e93 100644 --- a/docusaurus/src/components/AiToolbar/config/aiToolsConfig.js +++ b/docusaurus/src/components/AiToolbar/config/aiToolsConfig.js @@ -7,10 +7,17 @@ export const aiToolsConfig = { { id: 'copy-markdown', label: 'Copy Markdown', - description: 'Copy the raw markdown content of this page', + description: 'Copy the clean markdown content of this page', icon: 'copy', actionType: 'copy-markdown', }, + { + id: 'view-markdown', + label: 'View as Markdown', + description: 'Open this page as clean Markdown (for agents and tools)', + icon: 'markdown-logo', + actionType: 'view-markdown', + }, { id: 'open-chatgpt', label: 'Open with ChatGPT', diff --git a/docusaurus/src/components/AiToolbar/utils/docContext.js b/docusaurus/src/components/AiToolbar/utils/docContext.js index 9bc7744677..ab70ecdff5 100644 --- a/docusaurus/src/components/AiToolbar/utils/docContext.js +++ b/docusaurus/src/components/AiToolbar/utils/docContext.js @@ -38,6 +38,21 @@ export const getRawMarkdownUrl = ({ docId, docPath }) => { return null; }; +/** + * URL of the clean, generated per-page Markdown (the same content as + * llms-full.txt — JSX resolved, snippets inlined, API code surfaced) served at + * `/.md`. This is what agents should consume, as opposed to the + * raw MDX source on GitHub (getRawMarkdownUrl), which still contains , + * , imports, etc. Returns null outside the browser or for the + * homepage. + */ +export const getCleanMarkdownUrl = () => { + if (!isBrowser()) return null; + const cleanPath = window.location.pathname.replace(/^\/|\/$/g, ''); + if (!cleanPath) return null; // homepage: HTML only + return `${window.location.origin}/${cleanPath}.md`; +}; + const TEMPLATE_PATTERN = /\{\{\s*(\w+)\s*\}\}/g; export const applyTemplate = (template, values) => { diff --git a/docusaurus/src/components/Annotation/Annotation.jsx b/docusaurus/src/components/Annotation/Annotation.jsx index 59b6766c85..f8872a1845 100644 --- a/docusaurus/src/components/Annotation/Annotation.jsx +++ b/docusaurus/src/components/Annotation/Annotation.jsx @@ -129,6 +129,18 @@ export function Annotation({ children, id, width = 320 }) { {children} )} + {/* Flat rendering for Markdown view mode: the content is always in the + DOM (hidden in elegant/AI via CSS) so markdown mode can show it inline + below the paragraph, with the toggle button replaced by an asterisk. */} + + {children} + ); } diff --git a/docusaurus/src/components/Annotation/annotation.module.scss b/docusaurus/src/components/Annotation/annotation.module.scss index bd9547bc4c..268807ec45 100644 --- a/docusaurus/src/components/Annotation/annotation.module.scss +++ b/docusaurus/src/components/Annotation/annotation.module.scss @@ -55,6 +55,12 @@ } } + // Flat content, only shown in Markdown view mode (see view-modes.scss). + // Hidden by default so elegant/AI modes are unchanged. + &__flat { + display: none; + } + &__tooltip { display: block; position: var(--strapi-docs-annotation-tooltip-position, absolute); diff --git a/docusaurus/src/components/ApiExplorer/ApiExplorer.jsx b/docusaurus/src/components/ApiExplorer/ApiExplorer.jsx new file mode 100644 index 0000000000..be20123b46 --- /dev/null +++ b/docusaurus/src/components/ApiExplorer/ApiExplorer.jsx @@ -0,0 +1,512 @@ +import React, { useState, useCallback, useRef, useEffect } from 'react'; +import styles from './ApiExplorer.module.scss'; + +/** + * Simulated API data — all responses match actual Strapi v5 behavior. + * Status codes, response shapes, and field names are verified against docs. + */ +const API_DATA = { + rest: { + label: 'REST API', + docBase: '/cms/api/rest', + endpoints: [ + { + method: 'GET', + name: 'List entries', + path: '/api/restaurants?populate=*', + docHash: '#get-all', + response: { + status: 200, + statusText: 'OK', + time: 23, + body: { + data: [ + { + id: 1, + documentId: 'a1b2c3d4e5f6g7h8i9j0klm', + name: 'Biscotte Restaurant', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A cozy place for brunch lovers.' }], + }, + ], + createdAt: '2026-01-15T09:00:00.000Z', + updatedAt: '2026-03-20T14:22:00.000Z', + publishedAt: '2026-01-15T09:05:00.000Z', + locale: 'en', + }, + ], + meta: { + pagination: { page: 1, pageSize: 25, pageCount: 1, total: 1 }, + }, + }, + }, + }, + { + method: 'GET', + name: 'Get entry', + path: '/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm', + docHash: '#get', + response: { + status: 200, + statusText: 'OK', + time: 12, + body: { + data: { + id: 1, + documentId: 'a1b2c3d4e5f6g7h8i9j0klm', + name: 'Biscotte Restaurant', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A cozy place for brunch lovers.' }], + }, + ], + createdAt: '2026-01-15T09:00:00.000Z', + updatedAt: '2026-03-20T14:22:00.000Z', + publishedAt: '2026-01-15T09:05:00.000Z', + locale: 'en', + }, + meta: {}, + }, + }, + }, + { + method: 'POST', + name: 'Create entry', + path: '/api/restaurants', + docHash: '#create', + requestBody: { + data: { + name: 'Restaurant D', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A very short description goes here.' }], + }, + ], + }, + }, + response: { + status: 200, + statusText: 'OK', + time: 45, + body: { + data: { + id: 2, + documentId: 'f6g7h8i9j0k1l2m3n4o5pqr', + name: 'Restaurant D', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A very short description goes here.' }], + }, + ], + createdAt: '2026-04-05T14:30:00.000Z', + updatedAt: '2026-04-05T14:30:00.000Z', + publishedAt: null, + locale: 'en', + }, + meta: {}, + }, + }, + }, + { + method: 'PUT', + name: 'Update entry', + path: '/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm', + docHash: '#update', + requestBody: { + data: { + name: 'BMK Paris Bamako', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A very short description goes here.' }], + }, + ], + }, + }, + response: { + status: 200, + statusText: 'OK', + time: 31, + body: { + data: { + id: 1, + documentId: 'a1b2c3d4e5f6g7h8i9j0klm', + name: 'BMK Paris Bamako', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A very short description goes here.' }], + }, + ], + createdAt: '2026-01-15T09:00:00.000Z', + updatedAt: '2026-04-05T15:00:00.000Z', + publishedAt: '2026-01-15T09:05:00.000Z', + locale: 'en', + }, + meta: {}, + }, + }, + }, + { + method: 'DELETE', + name: 'Delete entry', + path: '/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm', + docHash: '#delete', + response: { + status: 204, + statusText: 'No Content', + time: 18, + body: null, + }, + }, + ], + }, + graphql: { + label: 'GraphQL', + docBase: '/cms/api/graphql', + endpoints: [ + { + method: 'POST', + name: 'Query collection', + path: '/graphql', + docHash: '#queries', + requestBody: `{ + restaurants_connection { + nodes { + documentId + name + } + pageInfo { + page + pageSize + pageCount + total + } + } +}`, + response: { + status: 200, + statusText: 'OK', + time: 35, + body: { + data: { + restaurants_connection: { + nodes: [ + { + documentId: 'a1b2c3d4e5f6g7h8i9j0klm', + name: 'Biscotte Restaurant', + }, + ], + pageInfo: { page: 1, pageSize: 10, pageCount: 1, total: 1 }, + }, + }, + }, + }, + }, + { + method: 'POST', + name: 'Query single', + path: '/graphql', + docHash: '#queries', + requestBody: `{ + restaurant(documentId: "a1b2c3d4e5f6g7h8i9j0klm") { + name + description + } +}`, + response: { + status: 200, + statusText: 'OK', + time: 18, + body: { + data: { + restaurant: { + name: 'Biscotte Restaurant', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A cozy place for brunch lovers.' }], + }, + ], + }, + }, + }, + }, + }, + { + method: 'POST', + name: 'Mutation create', + path: '/graphql', + docHash: '#mutations', + requestBody: `mutation { + createRestaurant(data: { + name: "Pizzeria Arrivederci" + }) { + documentId + name + } +}`, + response: { + status: 200, + statusText: 'OK', + time: 42, + body: { + data: { + createRestaurant: { + documentId: 'f6g7h8i9j0k1l2m3n4o5pqr', + name: 'Pizzeria Arrivederci', + }, + }, + }, + }, + }, + ], + }, + document: { + label: 'Document Service', + docBase: '/cms/api/document-service', + endpoints: [ + { + method: 'GET', + name: 'findMany()', + path: "await strapi.documents('api::restaurant.restaurant').findMany()", + docHash: '#findmany', + response: { + status: 200, + statusText: 'OK', + time: 8, + body: [ + { + documentId: 'a1b2c3d4e5f6g7h8i9j0klm', + name: 'Biscotte Restaurant', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A cozy place for brunch lovers.' }], + }, + ], + locale: 'en', + }, + ], + }, + }, + { + method: 'GET', + name: 'findOne()', + path: "await strapi.documents('api::restaurant.restaurant').findOne({ documentId: 'a1b2c3d4e5f6g7h8i9j0klm' })", + docHash: '#findone', + response: { + status: 200, + statusText: 'OK', + time: 5, + body: { + documentId: 'a1b2c3d4e5f6g7h8i9j0klm', + name: 'Biscotte Restaurant', + description: [ + { + type: 'paragraph', + children: [{ type: 'text', text: 'A cozy place for brunch lovers.' }], + }, + ], + locale: 'en', + }, + }, + }, + { + method: 'POST', + name: 'create()', + path: "await strapi.documents('api::restaurant.restaurant').create({ data: { name: 'Restaurant B' } })", + docHash: '#create', + response: { + status: 200, + statusText: 'OK', + time: 15, + body: { + documentId: 'f6g7h8i9j0k1l2m3n4o5pqr', + name: 'Restaurant B', + createdAt: '2026-04-05T14:30:00.000Z', + locale: 'en', + }, + }, + }, + ], + }, +}; + +const METHOD_COLORS = { + GET: 'get', + POST: 'post', + PUT: 'put', + DELETE: 'delete', +}; + +/** + * Syntax-highlighted JSON renderer + */ +function JsonView({ data }) { + const json = JSON.stringify(data, null, 2); + const highlighted = json + .replace(/&/g, '&') + .replace(/"$1"') + .replace(/:\s*"([^"]*)"/g, ': "$1"') + .replace(/:\s*(\d+\.?\d*)/g, ': $1') + .replace(/:\s*(true|false|null)/g, ': $1'); + + return ( +
+  );
+}
+
+export default function ApiExplorer() {
+  const [activeTab, setActiveTab] = useState('rest');
+  const [activeEndpoint, setActiveEndpoint] = useState(0);
+  const [isLoading, setIsLoading] = useState(false);
+  const [showResponse, setShowResponse] = useState(true);
+  const [showRequest, setShowRequest] = useState(false);
+  const responseRef = useRef(null);
+
+  const apiGroup = API_DATA[activeTab];
+  const endpoint = apiGroup.endpoints[activeEndpoint];
+
+  const handleTabChange = useCallback((tab) => {
+    setActiveTab(tab);
+    setActiveEndpoint(0);
+    setShowResponse(true);
+    setShowRequest(false);
+  }, []);
+
+  const handleEndpointChange = useCallback((index) => {
+    setActiveEndpoint(index);
+    setShowResponse(false);
+    setShowRequest(false);
+  }, []);
+
+  const handleSend = useCallback(() => {
+    setIsLoading(true);
+    setShowResponse(false);
+    setShowRequest(false);
+    setTimeout(() => {
+      setIsLoading(false);
+      setShowResponse(true);
+    }, 300 + Math.random() * 400);
+  }, []);
+
+  useEffect(() => {
+    setShowResponse(true);
+  }, []);
+
+  const docLink = endpoint.docHash
+    ? `${apiGroup.docBase}${endpoint.docHash}`
+    : apiGroup.docBase;
+
+  return (
+    
+
API Explorer
+
+ {/* Tabs */} +
+ {Object.entries(API_DATA).map(([key, group]) => ( + + ))} +
+ +
+ {/* Endpoint sidebar */} +
+ {apiGroup.endpoints.map((ep, i) => ( + + ))} +
+ + {/* Request + Response */} +
+ {/* URL bar */} +
+ + {endpoint.method} + + {endpoint.path} + +
+ + {/* Request body (for POST/PUT) */} + {endpoint.requestBody && !showResponse && !isLoading && ( +
+
Request Body
+
+ {typeof endpoint.requestBody === 'string' + ?
{endpoint.requestBody}
+ : + } +
+
+ )} + + {/* Response */} + {showResponse && endpoint.response && ( +
+
+ + + {endpoint.response.status} {endpoint.response.statusText} + + {endpoint.response.time}ms +
+
+ {endpoint.response.body !== null + ? + :
No response body
+ } +
+
+ )} + + {isLoading && ( +
+
+
+
+
+ )} +
+
+
+ + {/* Per-endpoint doc link */} +
+ Read the {apiGroup.label} docs → + +
+ ); +} diff --git a/docusaurus/src/components/ApiExplorer/ApiExplorer.module.scss b/docusaurus/src/components/ApiExplorer/ApiExplorer.module.scss new file mode 100644 index 0000000000..156e97af0e --- /dev/null +++ b/docusaurus/src/components/ApiExplorer/ApiExplorer.module.scss @@ -0,0 +1,414 @@ +@use '../../scss/mixins' as *; + +/* ─── Explorer wrapper ─── */ +.explorer { + width: 100%; + max-width: 960px; + margin: 0 auto; +} + +.explorerLabel { + font-family: var(--strapi-font-family-technical); + font-size: 12px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--strapi-neutral-400); + margin-bottom: 16px; + display: flex; + align-items: center; + gap: 12px; + + &::after { + content: ''; + flex: 1; + height: 1px; + background: var(--strapi-neutral-200); + } +} + +/* ─── Dark card container ─── */ +.explorerCard { + background: #1a1a2e; + border-radius: 16px; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.08); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.24), 0 2px 8px rgba(0, 0, 0, 0.12); +} + +/* ─── API Tabs ─── */ +.tabs { + display: flex; + gap: 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + padding: 0 20px; +} + +.tab { + display: flex; + align-items: center; + gap: 8px; + padding: 14px 20px; + border: none; + background: transparent; + color: rgba(255, 255, 255, 0.4); + font-family: var(--strapi-font-family-technical); + font-size: 13px; + font-weight: 600; + cursor: pointer; + position: relative; + transition: color 0.15s ease; + white-space: nowrap; + + &:hover { + color: rgba(255, 255, 255, 0.7); + } + + &::after { + content: ''; + position: absolute; + bottom: -1px; + left: 0; + right: 0; + height: 2px; + background: transparent; + transition: background 0.2s ease; + } +} + +.tabActive { + color: #fff; + + &::after { + background: var(--strapi-primary-500); + } + + .tabDot { + background: #4ade80; + } +} + +.tabDot { + width: 6px; + height: 6px; + border-radius: 50%; + background: transparent; + transition: background 0.2s ease; +} + +/* ─── Body: sidebar + request pane ─── */ +.explorerBody { + display: flex; + min-height: 520px; +} + +/* ─── Endpoint sidebar ─── */ +.endpointList { + width: 200px; + flex-shrink: 0; + border-right: 1px solid rgba(255, 255, 255, 0.06); + padding: 12px 8px; + display: flex; + flex-direction: column; + gap: 2px; +} + +.endpointItem { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 12px; + border: none; + background: transparent; + color: rgba(255, 255, 255, 0.6); + font-family: var(--strapi-font-family-body); + font-size: 13px; + cursor: pointer; + border-radius: 8px; + transition: background 0.12s ease, color 0.12s ease; + text-align: left; + + &:hover { + background: rgba(255, 255, 255, 0.05); + color: rgba(255, 255, 255, 0.85); + } +} + +.endpointItemActive { + background: rgba(255, 255, 255, 0.08); + color: #fff; +} + +.endpointName { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* ─── Method badges ─── */ +.methodBadge { + font-family: var(--strapi-font-family-technical); + font-size: 10px; + font-weight: 700; + padding: 2px 6px; + border-radius: 4px; + text-transform: uppercase; + flex-shrink: 0; + letter-spacing: 0.02em; +} + +.methodget { background: rgba(74, 222, 128, 0.15); color: #4ade80; } +.methodpost { background: rgba(251, 191, 36, 0.15); color: #fbbf24; } +.methodput { background: rgba(96, 165, 250, 0.15); color: #60a5fa; } +.methoddelete { background: rgba(248, 113, 113, 0.15); color: #f87171; } + +/* ─── Request pane ─── */ +.requestPane { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; +} + +/* ─── URL bar ─── */ +.urlBar { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 16px; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + background: rgba(255, 255, 255, 0.02); +} + +.urlMethod { + font-family: var(--strapi-font-family-technical); + font-size: 12px; + font-weight: 700; + padding: 4px 10px; + border-radius: 6px; + flex-shrink: 0; +} + +.urlPath { + flex: 1; + font-family: var(--strapi-font-family-mono); + font-size: 13px; + color: rgba(255, 255, 255, 0.7); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.sendBtn { + flex-shrink: 0; + padding: 6px 16px; + border: none; + border-radius: 8px; + background: var(--strapi-primary-600); + color: #fff; + font-family: var(--strapi-font-family-technical); + font-size: 12px; + font-weight: 600; + cursor: pointer; + transition: background 0.15s ease, transform 0.1s ease; + white-space: nowrap; + + &:hover { + background: var(--strapi-primary-500); + } + + &:active { + transform: scale(0.97); + } + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } +} + +/* ─── Request body ─── */ +.requestBodySection { + display: flex; + flex-direction: column; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); +} + +.requestBodyHeader { + font-family: var(--strapi-font-family-technical); + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; + color: rgba(255, 255, 255, 0.35); + padding: 8px 16px 0; +} + +/* ─── Response area ─── */ +.response { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.responseHeader { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 16px; + border-bottom: 1px solid rgba(255, 255, 255, 0.04); +} + +.statusDot { + width: 8px; + height: 8px; + border-radius: 50%; +} + +.statusOk { background: #4ade80; } +.statusErr { background: #f87171; } + +.statusCode { + font-family: var(--strapi-font-family-technical); + font-size: 13px; + font-weight: 600; + color: #4ade80; +} + +.responseTime { + margin-left: auto; + font-family: var(--strapi-font-family-technical); + font-size: 12px; + color: rgba(255, 255, 255, 0.35); +} + +.responseBody { + flex: 1; + overflow: auto; + padding: 16px; + max-height: 480px; + + /* Thin scrollbar */ + scrollbar-width: thin; + scrollbar-color: rgba(255, 255, 255, 0.15) transparent; + &::-webkit-scrollbar { width: 4px; } + &::-webkit-scrollbar-track { background: transparent; } + &::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 4px; } +} + +/* ─── JSON syntax highlighting ─── */ +.jsonPre { + margin: 0; + font-family: var(--strapi-font-family-mono); + font-size: 13px; + line-height: 1.6; + color: rgba(255, 255, 255, 0.7); + background: transparent !important; + white-space: pre; + tab-size: 2; + + :global(.json-key) { color: #c4b5fd; } + :global(.json-string) { color: #fbbf24; } + :global(.json-number) { color: #4ade80; } + :global(.json-bool) { color: #60a5fa; } +} + +/* ─── Loading animation ─── */ +.loadingBar { + height: 2px; + background: rgba(255, 255, 255, 0.05); + overflow: hidden; +} + +.loadingBarInner { + height: 100%; + width: 40%; + background: var(--strapi-primary-500); + border-radius: 2px; + animation: loadSlide 0.8s ease-in-out infinite; +} + +@keyframes loadSlide { + 0% { transform: translateX(-100%); } + 100% { transform: translateX(350%); } +} + +/* ─── Doc link ─── */ +.explorerDocLink { + display: inline-flex; + align-items: center; + margin-top: 12px; + font-family: var(--strapi-font-family-technical); + font-size: 13px; + font-weight: 500; + color: var(--strapi-neutral-400); + text-decoration: none; + transition: color 0.15s ease; + + &:hover { + color: var(--strapi-primary-500); + text-decoration: none; + } +} + +/* ─── Responsive ─── */ +@media (max-width: 768px) { + .explorerBody { + flex-direction: column; + min-width: 0; + } + + /* Tabs scroll horizontally instead of overflowing the card on narrow screens. */ + .tabs { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + scrollbar-width: none; + + &::-webkit-scrollbar { + display: none; + } + } + + .tab { + flex-shrink: 0; + } + + .endpointList { + width: 100%; + /* min-width:0 lets overflow-x:auto actually contain the row inside the + flex column, instead of the row stretching the card wider than the + viewport. */ + min-width: 0; + border-right: none; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + flex-direction: row; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + padding: 8px; + gap: 4px; + } + + .endpointItem { + white-space: nowrap; + flex-shrink: 0; + } + + /* The request pane and its code blocks must not push the card wider; keep + them inside the column and let the code scroll within its own box. */ + .requestPane { + min-width: 0; + } + + .urlBar { + flex-wrap: wrap; + } + + /* Wrap the JSON instead of scrolling it horizontally on small screens, so the + response stays readable without sideways scrolling inside the card. */ + .jsonPre { + white-space: pre-wrap; + word-break: break-word; + overflow-wrap: anywhere; + } +} diff --git a/docusaurus/src/components/ApiReference/ApiHeader.jsx b/docusaurus/src/components/ApiReference/ApiHeader.jsx new file mode 100644 index 0000000000..8cb3f73fd4 --- /dev/null +++ b/docusaurus/src/components/ApiReference/ApiHeader.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import styles from './api-reference.module.scss'; + +/** + * API page header with gradient accent bar. + * + * + */ +export default function ApiHeader({ title, description, baseUrl = 'http://localhost:1337' }) { + return ( +
+

{title}

+ {description &&

{description}

} +
+ Base + {baseUrl} +
+
+ ); +} diff --git a/docusaurus/src/components/ApiReference/ApiReferencePage.jsx b/docusaurus/src/components/ApiReference/ApiReferencePage.jsx new file mode 100644 index 0000000000..c378e2cbbe --- /dev/null +++ b/docusaurus/src/components/ApiReference/ApiReferencePage.jsx @@ -0,0 +1,39 @@ +import React from 'react'; +import Layout from '@theme/Layout'; +import styles from './api-reference.module.scss'; +import ApiSidebar from './ApiSidebar'; +import ApiHeader from './ApiHeader'; + +/** + * Full API reference page layout. + * Replaces the standard Docusaurus doc page layout for API reference. + * + * + * + * + * + */ +export default function ApiReferencePage({ + title, + description, + baseUrl = 'http://localhost:1337', + sidebarSections = [], + children, +}) { + return ( + +
+ +
+ + {children} +
+
+
+ ); +} diff --git a/docusaurus/src/components/ApiReference/ApiSidebar.jsx b/docusaurus/src/components/ApiReference/ApiSidebar.jsx new file mode 100644 index 0000000000..b9fdc42946 --- /dev/null +++ b/docusaurus/src/components/ApiReference/ApiSidebar.jsx @@ -0,0 +1,64 @@ +import React from 'react'; +import styles from './api-reference.module.scss'; +import clsx from 'clsx'; +import { useLocation, useHistory } from '@docusaurus/router'; + +const METHOD_KEY = { + GET: 'get', POST: 'post', PUT: 'put', DELETE: 'del', DEL: 'del', PATCH: 'patch', +}; + +/** + * Custom API sidebar with method badges. + * + * + */ +export default function ApiSidebar({ sections = [] }) { + const location = useLocation(); + + const isActive = (href) => { + if (href.startsWith('#')) { + return location.hash === href; + } + return location.pathname === href || location.pathname === href + '/'; + }; + + return ( + + ); +} diff --git a/docusaurus/src/components/ApiReference/CodePanel.jsx b/docusaurus/src/components/ApiReference/CodePanel.jsx new file mode 100644 index 0000000000..62ef38200f --- /dev/null +++ b/docusaurus/src/components/ApiReference/CodePanel.jsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import CopyCodeButton from './CopyCodeButton'; +import styles from './api-reference.module.scss'; +import clsx from 'clsx'; + +/** + * CodePanel with language tabs and URL bar. + * + * Usage: + * + */ +export default function CodePanel({ kind = 'http', method = 'GET', path, pathHighlights = [], tabs = [] }) { + const [activeTab, setActiveTab] = useState(0); + const methodKey = method.toUpperCase() === 'DELETE' ? 'del' : method.toLowerCase(); + const displayMethod = method.toUpperCase() === 'DELETE' ? 'DEL' : method.toUpperCase(); + const isJs = kind === 'js'; + + // Highlight path params + const renderPath = (p) => { + if (!p) return null; + let result = p; + pathHighlights.forEach(h => { + result = result.replace(h, `${h}`); + }); + // Also highlight :param patterns + result = result.replace(/:(\w+)/g, `:$1`); + return ; + }; + + return ( +
+ {tabs.length > 1 && ( +
+ {tabs.map((tab, i) => ( + setActiveTab(i)} + > + {tab.label} + + ))} +
+ )} + {path && !isJs && ( +
+ + {displayMethod} + + {renderPath(path)} +
+ )} +
+ +
+          {tabs[activeTab]?.code || ''}
+        
+
+
+ ); +} diff --git a/docusaurus/src/components/ApiReference/CopyCodeButton.jsx b/docusaurus/src/components/ApiReference/CopyCodeButton.jsx new file mode 100644 index 0000000000..50571bdaf8 --- /dev/null +++ b/docusaurus/src/components/ApiReference/CopyCodeButton.jsx @@ -0,0 +1,44 @@ +import React, { useState, useCallback } from 'react'; +import styles from './api-reference.module.scss'; +import clsx from 'clsx'; + +/** + * Self-contained copy button for the API reference code/response panels. + * + * The Docusaurus @theme/CodeBlock/CopyButton only renders correctly inside a + * real (it depends on that component's CSS modules for sizing and + * icons). Used standalone it collapses to a 0x0 element. This button owns its + * own markup and styles, so it works anywhere. + */ +export default function CopyCodeButton({ code = '' }) { + const [copied, setCopied] = useState(false); + + const onCopy = useCallback(() => { + if (!code) return; + navigator.clipboard.writeText(code).then(() => { + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }); + }, [code]); + + return ( + + ); +} diff --git a/docusaurus/src/components/ApiReference/Endpoint.jsx b/docusaurus/src/components/ApiReference/Endpoint.jsx new file mode 100644 index 0000000000..36301ab44e --- /dev/null +++ b/docusaurus/src/components/ApiReference/Endpoint.jsx @@ -0,0 +1,124 @@ +import React from 'react'; +import useBrokenLinks from '@docusaurus/useBrokenLinks'; +import styles from './api-reference.module.scss'; +import MethodPill from './MethodPill'; +import ParamTable from './ParamTable'; +import CodePanel from './CodePanel'; +import ResponsePanel from './ResponsePanel'; + +/** + * Full 2-column endpoint block matching the V3 mockup. + * + * Usage (HTTP / REST): + * + * + * Usage (JS API — Document Service, etc.): pass kind="js". This hides the HTTP + * method pill and the URL bar, renders `path` as the JS method signature, and + * labels the result "Returns" instead of an HTTP status. A JS call has no HTTP + * verb and no HTTP status, so the http chrome is suppressed. + * + */ +export default function Endpoint({ + id, + kind = 'http', + method = 'GET', + path, + title, + description, + params = [], + paramTitle = 'Parameters', + codeTabs = [], + codePath, + codePathHighlights = [], + responses = [], + collapsibleResponse = false, + isLast = false, + children, +}) { + useBrokenLinks().collectAnchor(id); + const hasColumns = (params.length > 0 || children) && (codeTabs.length > 0 || responses.length > 0); + const isJs = kind === 'js'; + + return ( +
+ {/* Header: full-width, above the 2-column grid */} +
+
+ {isJs ? ( + {path} + ) : ( + <> + + + {path} + + + )} +
+ {description &&

{description}

} +
+ + {/* 2-column grid: params left, code right */} + {hasColumns ? ( +
+
+ {params.length > 0 && } + {children} +
+
+ {codeTabs.length > 0 && ( + + )} + {responses.length > 0 && } +
+
+ ) : ( + /* Fallback: no params, just code below the header */ + <> + {(codeTabs.length > 0 || responses.length > 0) && ( +
+ {codeTabs.length > 0 && ( + + )} + {responses.length > 0 && } +
+ )} + {children &&
{children}
} + + )} +
+ ); +} diff --git a/docusaurus/src/components/ApiReference/MethodPill.jsx b/docusaurus/src/components/ApiReference/MethodPill.jsx new file mode 100644 index 0000000000..b89cd7edfa --- /dev/null +++ b/docusaurus/src/components/ApiReference/MethodPill.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import styles from './api-reference.module.scss'; +import clsx from 'clsx'; + +const METHOD_MAP = { + GET: 'get', + POST: 'post', + PUT: 'put', + DELETE: 'del', + DEL: 'del', + PATCH: 'patch', +}; + +export default function MethodPill({ method = 'GET' }) { + const key = METHOD_MAP[method.toUpperCase()] || 'get'; + return ( + + {method.toUpperCase() === 'DELETE' ? 'DEL' : method.toUpperCase()} + + ); +} diff --git a/docusaurus/src/components/ApiReference/ParamTable.jsx b/docusaurus/src/components/ApiReference/ParamTable.jsx new file mode 100644 index 0000000000..624d9a4dd7 --- /dev/null +++ b/docusaurus/src/components/ApiReference/ParamTable.jsx @@ -0,0 +1,35 @@ +import React from 'react'; +import styles from './api-reference.module.scss'; +import clsx from 'clsx'; + +/** + * Structured parameter table for API endpoints. + * + * Usage: + * + */ +export default function ParamTable({ title = 'Parameters', params = [] }) { + if (!params.length) return null; + return ( +
+
{title}
+ {params.map((param, i) => ( +
+
+
{param.name}
+ {param.type &&
{param.type}
} +
+ + {param.required ? 'required' : 'optional'} + +
+
+ ))} +
+ ); +} diff --git a/docusaurus/src/components/ApiReference/ResponsePanel.jsx b/docusaurus/src/components/ApiReference/ResponsePanel.jsx new file mode 100644 index 0000000000..445f1c2901 --- /dev/null +++ b/docusaurus/src/components/ApiReference/ResponsePanel.jsx @@ -0,0 +1,100 @@ +import React, { useState } from 'react'; +import CopyCodeButton from './CopyCodeButton'; +import styles from './api-reference.module.scss'; +import clsx from 'clsx'; + +/** + * ResponsePanel with status tabs and animated dot. + * + * Usage: + * + */ +const COLLAPSE_LINE_THRESHOLD = 10; + +export default function ResponsePanel({ kind = 'http', responses = [], collapsible = false }) { + const [activeIdx, setActiveIdx] = useState(0); + const [expanded, setExpanded] = useState(false); + if (!responses.length) return null; + + const isJs = kind === 'js'; + const active = responses[activeIdx]; + const isOk = active.status < 400; + + // Opt-in: collapse long response bodies behind a "Show more" toggle. + const lineCount = active.body ? String(active.body).split('\n').length : 0; + const isCollapsible = collapsible && lineCount > COLLAPSE_LINE_THRESHOLD; + const collapsed = isCollapsible && !expanded; + + const getTabStyle = (status) => { + if (status < 300) return 'response-tab--2xx'; + if (status < 400) return 'response-tab--3xx'; + if (status < 500) return 'response-tab--4xx'; + return 'response-tab--5xx'; + }; + + return ( +
+ {!isJs && responses.length > 1 && ( +
+ {responses.map((r, i) => ( + setActiveIdx(i)} + > + {r.status} + + ))} +
+ )} + +
+ {isJs ? ( + + Returns + + ) : ( + <> + + + {active.status} {active.statusText} + + {active.time && {active.time}} + + )} +
+ +
+
+ +
+            {active.body}
+          
+ {collapsed && + {isCollapsible && ( + + )} +
+
+ ); +} diff --git a/docusaurus/src/components/ApiReference/api-reference.module.scss b/docusaurus/src/components/ApiReference/api-reference.module.scss new file mode 100644 index 0000000000..6fa52de42a --- /dev/null +++ b/docusaurus/src/components/ApiReference/api-reference.module.scss @@ -0,0 +1,793 @@ +/** Component: V3 API Reference — Stripe-style 2-column layout */ +@use '../../scss/_mixins.scss' as *; + +/* ═══ LAYOUT ═══ */ +.apiLayout { + display: flex; + min-height: calc(100vh - var(--ifm-navbar-height)); + margin-top: 0; +} + +.apiMain { + flex: 1; + min-width: 0; +} + +/* ═══ API SIDEBAR ═══ */ +.apiSidebar { + width: 240px; + min-width: 240px; + border-right: 1px solid var(--strapi-border); + height: calc(100vh - var(--ifm-navbar-height)); + position: sticky; + top: var(--ifm-navbar-height); + overflow-y: auto; + background: var(--strapi-surface-0); + padding: 8px 0; + scrollbar-width: thin; + scrollbar-color: var(--strapi-surface-3) transparent; + + &__section { + padding: 0 8px; + margin-bottom: 2px; + } + + &__sectionTitle { + font-family: var(--strapi-font-family-technical); + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--strapi-fg-5); + padding: 14px 10px 6px; + } + + &__divider { + height: 1px; + background: var(--strapi-border); + margin: 4px 12px; + } +} + +/* Sidebar items */ +.sItem { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 7px; + font-size: 12.5px; + color: var(--strapi-fg-3); + text-decoration: none; + transition: all 0.12s; + cursor: pointer; + + &:hover { + background: var(--strapi-surface-3); + color: var(--strapi-fg-1); + text-decoration: none; + } + + &--active { + background: rgba(73, 69, 255, 0.08); + color: var(--strapi-accent-light); + font-weight: 600; + } + + &__badge { + font-family: var(--strapi-font-family-technical); + font-size: 9px; + font-weight: 700; + padding: 2px 5px; + border-radius: 4px; + text-transform: uppercase; + width: 34px; + text-align: center; + flex-shrink: 0; + + &--get { + background: rgba(52, 211, 153, 0.1); + color: var(--strapi-green); + } + &--post { + background: rgba(73, 69, 255, 0.1); + color: var(--strapi-accent-light); + } + &--put { + background: rgba(251, 191, 36, 0.1); + color: var(--strapi-amber); + } + &--del { + background: rgba(248, 113, 113, 0.1); + color: var(--strapi-red); + } + &--patch { + background: rgba(192, 132, 252, 0.1); + color: var(--strapi-accent-2); + } + } +} + +/* ═══ API HEADER ═══ */ +.apiHeader { + padding: 40px 48px 32px; + border-bottom: 1px solid var(--strapi-border); + position: relative; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 48px; + width: 60px; + height: 3px; + border-radius: 2px; + background: linear-gradient(90deg, var(--strapi-accent), var(--strapi-accent-2)); + animation: apiLineExpand 0.6s var(--strapi-ease) both; + } + + &__title { + font-family: var(--strapi-font-family-display); + font-size: 34px; + font-weight: 800; + letter-spacing: -0.03em; + margin-bottom: 10px; + color: var(--strapi-fg-1); + } + + &__desc { + font-size: 16px; + line-height: 1.6; + color: var(--strapi-fg-3); + max-width: 560px; + } + + &__base { + margin-top: 20px; + display: inline-flex; + align-items: center; + gap: 10px; + padding: 8px 14px; + border-radius: var(--strapi-radius-md); + background: var(--strapi-surface-2); + border: 1px solid var(--strapi-border); + font-family: var(--strapi-font-family-mono); + font-size: 13px; + } + + &__baseLabel { + font-size: 10px; + font-weight: 600; + color: var(--strapi-fg-5); + text-transform: uppercase; + letter-spacing: 0.06em; + } + + &__baseUrl { + color: var(--strapi-fg-2); + } +} + +@keyframes apiLineExpand { + from { width: 0; opacity: 0; } + to { width: 60px; opacity: 1; } +} + +/* ═══ ENDPOINT — 2-column split ═══ */ +.endpoint { + border-bottom: 1px solid var(--strapi-border); + + /* Full-width header above the 2-column grid */ + &__header { + padding: 40px 44px 20px; + } + + /* 2-column grid: params left, code right */ + &__columns { + display: grid; + grid-template-columns: 1fr 1fr; + } + + &__desc { + padding: 24px 44px 40px; + border-right: 1px solid var(--strapi-border); + } + + &__methodRow { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 20px; + } + + &__path { + font-family: var(--strapi-font-family-mono); + font-size: 14px; + color: var(--strapi-fg-2); + } + + // JS API signature (Document Service etc.): shown instead of a method pill + + // URL path, because a JS method call has no HTTP verb. Renders the call + // signature (e.g. strapi.documents().findOne()) as the header anchor. + &__signature { + font-family: var(--strapi-font-family-mono); + font-size: 15px; + font-weight: 600; + color: var(--strapi-fg-1); + background: var(--strapi-surface-2); + border: 1px solid var(--strapi-border); + border-radius: var(--strapi-radius-md, 6px); + padding: 4px 10px; + } + + &__title { + font-family: var(--strapi-font-family-display); + font-size: 22px; + font-weight: 700; + letter-spacing: -0.02em; + margin-bottom: 12px; + color: var(--strapi-fg-1); + border: none; + + &::before, + &::after { + display: none; + } + } + + &__text { + font-size: 15px; + line-height: 1.7; + color: var(--strapi-fg-3); + margin-bottom: 0; + } + + &__code { + padding: 24px 32px 40px; + // No background tint: the contrast on the code/response column added visual + // noise without purpose. The column blends with the page in light and dark. + position: sticky; + top: var(--ifm-navbar-height); + align-self: start; + max-height: calc(100vh - var(--ifm-navbar-height)); + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--strapi-surface-3) transparent; + } + + /* Fallback: code-only layout when there are no params */ + &__codeOnly { + padding: 24px 44px 40px; + max-width: 720px; + } +} + +/* ═══ METHOD PILL ═══ */ +.methodPill { + font-family: var(--strapi-font-family-technical); + font-size: 11px; + font-weight: 700; + padding: 4px 10px; + border-radius: 6px; + text-transform: uppercase; + letter-spacing: 0.02em; + position: relative; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent); + animation: methodShimmer 3s ease-in-out infinite; + } + + &--get { + background: rgba(52, 211, 153, 0.1); + color: var(--strapi-green); + } + &--post { + background: rgba(73, 69, 255, 0.1); + color: var(--strapi-accent-light); + } + &--put { + background: rgba(251, 191, 36, 0.1); + color: var(--strapi-amber); + } + &--del { + background: rgba(248, 113, 113, 0.1); + color: var(--strapi-red); + } + &--patch { + background: rgba(192, 132, 252, 0.1); + color: var(--strapi-accent-2); + } +} + +@keyframes methodShimmer { + 0%, 70% { left: -100%; } + 100% { left: 100%; } +} + +/* ═══ PARAMS TABLE ═══ */ +.params { + &__header { + font-family: var(--strapi-font-family-technical); + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--strapi-fg-3); + padding-bottom: 10px; + border-bottom: 1px solid var(--strapi-border); + margin-bottom: 0; + } +} + +.paramRow { + display: grid; + grid-template-columns: 1.2fr auto 1.5fr; + gap: 12px; + padding: 12px 0; + border-bottom: 1px solid var(--strapi-border); + align-items: start; + + // No hover state: parameter rows are not interactive (clicking does nothing), + // so a hover highlight wrongly suggested they were clickable. + + &:last-child { + border-bottom: none; + } +} + +.param { + &__name { + font-family: var(--strapi-font-family-mono); + font-size: 13px; + font-weight: 500; + color: var(--strapi-fg-1); + } + + &__type { + font-family: var(--strapi-font-family-mono); + font-size: 11px; + color: var(--strapi-fg-4); + margin-top: 2px; + } + + &__badge { + font-family: var(--strapi-font-family-technical); + font-size: 9px; + font-weight: 700; + padding: 2px 6px; + border-radius: 4px; + text-transform: uppercase; + letter-spacing: 0.02em; + + &--req { + background: rgba(248, 113, 113, 0.1); + color: var(--strapi-red); + } + &--opt { + background: var(--strapi-surface-3); + color: var(--strapi-fg-3); + } + } + + &__desc { + font-size: 13px; + line-height: 1.5; + color: var(--strapi-fg-3); + + code { + font-family: var(--strapi-font-family-mono); + font-size: 12px; + padding: 1px 5px; + border-radius: 4px; + background: var(--strapi-surface-2); + color: var(--strapi-accent); + border: 1px solid var(--strapi-border); + } + } +} + +/* ═══ CODE PANEL ═══ */ +.codePanel { + border-radius: 12px; + border: 1px solid var(--strapi-border-strong); + // No background fill: the white/tinted box on the code & response blocks added + // visual noise. Keep only the border to delimit the block; it blends with the + // page in light and dark. + background: transparent; + overflow: hidden; + margin-bottom: 16px; + transition: border-color 0.3s; + + &:hover { + border-color: rgba(73, 69, 255, 0.12); + } + + &__tabs { + display: flex; + border-bottom: 1px solid var(--strapi-border); + padding: 0 4px; + background: var(--strapi-surface-2); + } + + &__tab { + font-family: var(--strapi-font-family-mono); + font-size: 11px; + font-weight: 500; + padding: 9px 12px; + color: var(--strapi-fg-4); + cursor: pointer; + border-bottom: 2px solid transparent; + transition: all 0.15s; + user-select: none; + + &:hover { + color: var(--strapi-fg-2); + } + + &--active { + color: var(--strapi-fg-1); + border-bottom-color: var(--strapi-accent); + } + } + + &__url { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 14px; + border-bottom: 1px solid var(--strapi-border); + font-family: var(--strapi-font-family-mono); + font-size: 12px; + } + + &__urlMethod { + font-weight: 700; + font-size: 10px; + padding: 2px 6px; + border-radius: 4px; + text-transform: uppercase; + + &--get { + background: rgba(52, 211, 153, 0.1); + color: var(--strapi-green); + } + &--post { + background: rgba(73, 69, 255, 0.1); + color: var(--strapi-accent-light); + } + &--put { + background: rgba(251, 191, 36, 0.1); + color: var(--strapi-amber); + } + &--del { + background: rgba(248, 113, 113, 0.1); + color: var(--strapi-red); + } + &--patch { + background: rgba(192, 132, 252, 0.1); + color: var(--strapi-accent-2); + } + } + + &__urlPath { + color: var(--strapi-fg-2); + } + + // Wraps the
 so the copy button can anchor to its top-right corner.
+  // Reveals the copy button on hover.
+  &__codeWrap {
+    position: relative;
+
+    &:hover .copyCodeBtn,
+    .copyCodeBtn:focus-visible {
+      opacity: 1;
+    }
+  }
+
+  &__pre {
+    padding: 14px;
+    margin: 0;
+    overflow-x: auto;
+    background: transparent;
+
+    code {
+      font-family: var(--strapi-font-family-mono);
+      font-size: 12.5px;
+      line-height: 1.65;
+      color: var(--strapi-fg-2);
+      // Prism/Infima give the inner  a solid (white) background; strip it
+      // so the code block blends with the now-transparent panel.
+      background: transparent !important;
+    }
+
+    // Collapsed state: clip to ~10 lines of code.
+    &--collapsed {
+      max-height: 220px;
+      overflow: hidden;
+    }
+  }
+
+  // Fade-out gradient over the bottom of a collapsed response.
+  &__fade {
+    position: absolute;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    height: 48px;
+    pointer-events: none;
+    background: linear-gradient(to bottom, transparent, var(--strapi-surface-0));
+  }
+
+  // "Show more / Show less" toggle for long responses.
+  &__showMore {
+    display: block;
+    width: 100%;
+    padding: 8px 14px;
+    border: none;
+    border-top: 1px solid var(--strapi-border);
+    background: var(--strapi-surface-2);
+    color: var(--strapi-fg-3);
+    font-family: var(--strapi-font-family-mono);
+    font-size: 11px;
+    font-weight: 600;
+    text-transform: uppercase;
+    letter-spacing: 0.04em;
+    cursor: pointer;
+    transition: color 0.15s, background 0.15s;
+
+    &:hover {
+      color: var(--ifm-link-color);
+      background: var(--strapi-surface-3);
+    }
+  }
+}
+
+.pathHighlight {
+  color: var(--strapi-accent-light);
+}
+
+/* ═══ COPY BUTTON (self-contained, used by CodePanel + ResponsePanel) ═══ */
+.copyCodeBtn {
+  position: absolute;
+  top: 8px;
+  right: 8px;
+  z-index: 2;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 30px;
+  height: 30px;
+  padding: 0;
+  border: 1px solid var(--strapi-border);
+  border-radius: 6px;
+  background: var(--strapi-surface-2);
+  color: var(--strapi-fg-2);
+  cursor: pointer;
+  opacity: 0;
+  transition: opacity 0.15s ease-in-out, color 0.15s, border-color 0.15s;
+
+  &:hover {
+    color: var(--strapi-fg-1);
+    border-color: var(--strapi-border-strong);
+  }
+
+  &--copied {
+    opacity: 1;
+    color: var(--strapi-green);
+    border-color: var(--strapi-green);
+  }
+
+  svg {
+    display: block;
+  }
+}
+
+/* ═══ RESPONSE PANEL ═══ */
+.responsePanel {
+  margin-top: 4px;
+}
+
+.responseTabs {
+  display: flex;
+  gap: 2px;
+  margin-bottom: 8px;
+}
+
+.responseTab {
+  font-family: var(--strapi-font-family-technical);
+  font-size: 10px;
+  font-weight: 600;
+  padding: 3px 8px;
+  border-radius: 5px;
+  cursor: pointer;
+  transition: all 0.15s;
+  text-transform: uppercase;
+  letter-spacing: 0.04em;
+  border: 1px solid transparent;
+  user-select: none;
+
+  &--2xx {
+    background: rgba(52, 211, 153, 0.1);
+    color: var(--strapi-green);
+  }
+  &--3xx {
+    background: rgba(96, 165, 250, 0.1);
+    color: #60a5fa;
+  }
+  &--4xx {
+    background: rgba(248, 113, 113, 0.1);
+    color: var(--strapi-red);
+  }
+  &--5xx {
+    background: rgba(251, 191, 36, 0.1);
+    color: var(--strapi-amber);
+  }
+
+  &--active {
+    &.responseTab--2xx { border-color: var(--strapi-green); }
+    &.responseTab--4xx { border-color: var(--strapi-red); }
+    &.responseTab--5xx { border-color: var(--strapi-amber); }
+  }
+}
+
+.responseHeader {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 8px;
+  font-family: var(--strapi-font-family-mono);
+  font-size: 11px;
+}
+
+.responseDot {
+  width: 6px;
+  height: 6px;
+  border-radius: 50%;
+  animation: apiPulse 2s ease-in-out infinite;
+
+  &--ok {
+    background: var(--strapi-green);
+    box-shadow: 0 0 8px var(--strapi-green);
+  }
+  &--err {
+    background: var(--strapi-red);
+    box-shadow: 0 0 8px var(--strapi-red);
+  }
+}
+
+.responseStatus {
+  font-weight: 600;
+
+  &--ok { color: var(--strapi-green); }
+  &--err { color: var(--strapi-red); }
+}
+
+.responseTime {
+  color: var(--strapi-fg-5);
+  margin-left: auto;
+}
+
+@keyframes apiPulse {
+  0%, 100% { opacity: 1; }
+  50% { opacity: 0.4; }
+}
+
+/* ═══ RESPONSIVE ═══ */
+@include medium-down {
+  .apiLayout {
+    flex-direction: column;
+  }
+
+  .apiSidebar {
+    width: 100%;
+    min-width: 100%;
+    height: auto;
+    position: static;
+    border-right: none;
+    border-bottom: 1px solid var(--strapi-border);
+    display: flex;
+    overflow-x: auto;
+    padding: 8px;
+    gap: 4px;
+
+    &__section {
+      display: flex;
+      gap: 4px;
+      padding: 0;
+      flex-shrink: 0;
+    }
+
+    &__sectionTitle {
+      display: none;
+    }
+
+    &__divider {
+      width: 1px;
+      height: auto;
+      margin: 0 4px;
+    }
+  }
+
+  .sItem {
+    white-space: nowrap;
+    font-size: 11px;
+    padding: 4px 8px;
+  }
+
+  .endpoint__header {
+    padding: 24px 20px 0;
+  }
+
+  .endpoint__columns {
+    grid-template-columns: 1fr;
+  }
+
+  .endpoint__desc {
+    border-right: none;
+    border-bottom: 1px solid var(--strapi-border);
+    padding: 16px 20px 24px;
+  }
+
+  .endpoint__code {
+    position: static;
+    max-height: none;
+    padding: 16px 20px 24px;
+  }
+
+  .endpoint__codeOnly {
+    padding: 16px 20px 24px;
+  }
+
+  .apiHeader {
+    padding: 24px 20px 20px;
+
+    &::before {
+      left: 20px;
+    }
+
+    &__title {
+      font-size: 24px;
+    }
+  }
+}
+
+/* ═══ LIGHT MODE specifics ═══ */
+/* .endpoint__code and .codePanel intentionally have no background fill (removed
+   for a cleaner, noise-free code/response column). The tabs keep a subtle
+   surface tint so the cURL/JS switcher stays legible. */
+
+.codePanel__tabs {
+  background: var(--strapi-surface-2);
+}
+
+/* ═══ DARK MODE ═══ */
+@include dark {
+  .codePanel__tabs {
+    background: var(--strapi-surface-2);
+  }
+}
+
+/* ═══ REDUCED MOTION ═══ */
+@media (prefers-reduced-motion: reduce) {
+  .methodPill::after {
+    animation: none;
+  }
+
+  .responseDot {
+    animation: none;
+  }
+
+  .apiHeader::before {
+    animation: none;
+    width: 60px;
+    opacity: 1;
+  }
+}
diff --git a/docusaurus/src/components/ApiReference/index.js b/docusaurus/src/components/ApiReference/index.js
new file mode 100644
index 0000000000..c0e7a8b4e6
--- /dev/null
+++ b/docusaurus/src/components/ApiReference/index.js
@@ -0,0 +1,8 @@
+export { default as ApiReferencePage } from './ApiReferencePage';
+export { default as ApiHeader } from './ApiHeader';
+export { default as ApiSidebar } from './ApiSidebar';
+export { default as Endpoint } from './Endpoint';
+export { default as MethodPill } from './MethodPill';
+export { default as ParamTable } from './ParamTable';
+export { default as CodePanel } from './CodePanel';
+export { default as ResponsePanel } from './ResponsePanel';
diff --git a/docusaurus/src/components/Card/card.module.scss b/docusaurus/src/components/Card/card.module.scss
index ef0ca9933a..c4e53c5a3b 100644
--- a/docusaurus/src/components/Card/card.module.scss
+++ b/docusaurus/src/components/Card/card.module.scss
@@ -6,13 +6,13 @@
   --strapi-card-border-color: var(--strapi-neutral-150);
   --strapi-card-border-color-dark: var(--strapi-neutral-150);
   --strapi-card-border-color-light: var(--strapi-neutral-150);
-  --strapi-card-border-radius: 4px;
+  --strapi-card-border-radius: var(--strapi-radius-lg);
   --strapi-card-background-dark: linear-gradient(180deg, var(--strapi-neutral-100) 0%, var(--strapi-neutral-0) 100%);
   --strapi-card-background-light: var(--strapi-neutral-0);
   --strapi-card-box-shadow: 0 0 0 transparent;
   --strapi-card-content-delimited: 395px;
   --strapi-card-img-border-width: 1px;
-  --strapi-card-img-border-radius: 4px;
+  --strapi-card-img-border-radius: var(--strapi-radius-md);
   --strapi-card-img-bg-scale: 1;
   --strapi-card-justify-content: center;
   --strapi-card-position: relative;
@@ -47,11 +47,9 @@
 .card {
   position: var(--strapi-card-position);
   overflow: var(--strapi-card-overflow);
-  // background: var(--strapi-card-background);
-  background-color: transparent;
+  background: transparent;
   border-radius: var(--strapi-card-border-radius);
   border: 1px solid var(--strapi-card-border-color-light);
-  // box-shadow: var(--strapi-card-box-shadow);
   display: flex;
   flex-direction: column;
   gap: var(--strapi-card-gap);
@@ -60,7 +58,6 @@
   text-align: var(--strapi-card-text-align);
   padding: var(--strapi-card-py) var(--strapi-card-px);
   transition: all 0.2s ease;
-  background: var(--strapi-card-background-light);
 
   &:focus, &:hover {
     --strapi-card-border-color: var(--strapi-card-hover-border-color);
@@ -68,7 +65,8 @@
     --strapi-card-img-bg-scale: var(--strapi-card-hover-img-bg-scale);
     cursor: pointer;
     transform: translateY(-2px);
-    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
+    border-color: var(--strapi-card-hover-border-color);
+    box-shadow: 0px 1px 4px rgba(33, 33, 52, 0.1);
   }
 
   &-category-icon-container {
@@ -90,7 +88,7 @@
     font-weight: var(--strapi-card-title-font-weight);
     line-height: var(--strapi-card-title-line-height);
     margin: 0;
-    font-family: "SF Pro Text", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; 
+    font-family: var(--strapi-font-family-body) !important; 
     font-size: 28px;
     font-style: normal;
     font-weight: 600;
@@ -114,7 +112,7 @@
     --ifm-link-decoration: underline;
 
     color:#A5A5BA;
-    font-family: "SF Pro Text", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; 
+    font-family: var(--strapi-font-family-body) !important; 
     font-size: 16px;
     font-style: normal;
     font-weight: 400;
@@ -222,7 +220,7 @@
   --strapi-card-container-icon-background-color-cloud: var(--strapi-neutral-0);
 
   .card {
-    background: var(--strapi-card-background-dark);
+    background: transparent;
 
     &-category-icon-container {
       /* Couleur par défaut pour tous les conteneurs d'icônes */
diff --git a/docusaurus/src/components/CollapsibleTOC/CollapsibleTOC.jsx b/docusaurus/src/components/CollapsibleTOC/CollapsibleTOC.jsx
new file mode 100644
index 0000000000..fd6066a71f
--- /dev/null
+++ b/docusaurus/src/components/CollapsibleTOC/CollapsibleTOC.jsx
@@ -0,0 +1,53 @@
+import React, { useState, useCallback, useEffect } from 'react';
+import styles from './CollapsibleTOC.module.scss';
+
+const STORAGE_KEY = 'strapi-toc-collapsed';
+
+function getInitialCollapsed() {
+  try {
+    return localStorage.getItem(STORAGE_KEY) === 'true';
+  } catch {
+    return false;
+  }
+}
+
+export default function CollapsibleTOC({ children }) {
+  const [collapsed, setCollapsed] = useState(getInitialCollapsed);
+
+  // Drop the anti-FOUC attribute once mounted so the head-script CSS stops
+  // forcing the collapsed look — from here React's `collapsed` state drives the
+  // TOC (so re-expanding is not blocked). The head script sets it before paint
+  // to avoid a collapsed TOC flashing open on navigation.
+  useEffect(() => {
+    try { delete document.documentElement.dataset.tocCollapsed; } catch {}
+  }, []);
+
+  const toggle = useCallback(() => {
+    setCollapsed(prev => {
+      const next = !prev;
+      try { localStorage.setItem(STORAGE_KEY, String(next)); } catch {}
+      return next;
+    });
+  }, []);
+
+  return (
+    
+
+ {!collapsed && On this page} + +
+ {!collapsed && ( +
+ {children} +
+ )} +
+ ); +} diff --git a/docusaurus/src/components/CollapsibleTOC/CollapsibleTOC.module.scss b/docusaurus/src/components/CollapsibleTOC/CollapsibleTOC.module.scss new file mode 100644 index 0000000000..aa0efaed90 --- /dev/null +++ b/docusaurus/src/components/CollapsibleTOC/CollapsibleTOC.module.scss @@ -0,0 +1,91 @@ +/** V3: Collapsible Table of Contents — Sanity-inspired */ + +.wrapper { + position: sticky; + // Keep a small gap below the navbar when scrolled (and at the top of the + // page), aligned with the other floating controls. Without this the sticky + // TOC pins flush against the navbar on scroll. + top: calc(var(--ifm-navbar-height, 56px) + 18px); + width: 100%; + max-height: calc(100vh - var(--ifm-navbar-height, 56px) - 18px); + overflow-y: auto; + border-left: none; + padding: 0 8px 28px 20px; + + /* Thin scrollbar when TOC content overflows */ + scrollbar-width: thin; + scrollbar-color: var(--strapi-neutral-200) transparent; + &::-webkit-scrollbar { width: 3px; } + &::-webkit-scrollbar-track { background: transparent; } + &::-webkit-scrollbar-thumb { background-color: var(--strapi-neutral-200); border-radius: 3px; } + + // Hide on mobile/tablet — Docusaurus shows a "On this page" dropdown instead + @media (max-width: 996px) { + display: none; + } +} + +.collapsed { + border-left: none; + padding: 0; + display: flex; + align-items: flex-start; + justify-content: center; +} + +/** Header: label + toggle button */ +.header { + display: flex; + align-items: center; + justify-content: space-between; + padding-bottom: 8px; + min-height: 44px; +} + +.collapsed .header { + padding-bottom: 0; + min-height: auto; + padding-top: 4px; +} + +.label { + font-family: var(--strapi-font-family-technical, 'JetBrains Mono', monospace); + font-size: 12px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--strapi-neutral-400); + white-space: nowrap; +} + +.toggle { + width: 28px; + height: 28px; + border-radius: 6px; + border: 1px solid var(--strapi-neutral-200); + background: transparent; + cursor: pointer; + display: grid; + place-items: center; + color: var(--strapi-neutral-400); + font-size: 14px; + line-height: 1; + transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; + flex-shrink: 0; + padding: 0; + + &:hover { + background: var(--strapi-neutral-100); + color: var(--strapi-neutral-800); + border-color: var(--strapi-neutral-300); + } +} + +.content { + /* Override inner Docusaurus TOC sticky — our wrapper handles it */ + :global(.theme-doc-toc-desktop) { + position: static; + max-height: none; + overflow-y: visible; + } +} diff --git a/docusaurus/src/components/CustomDocCard.js b/docusaurus/src/components/CustomDocCard.js index 3a30253f18..aa291f37e7 100644 --- a/docusaurus/src/components/CustomDocCard.js +++ b/docusaurus/src/components/CustomDocCard.js @@ -4,6 +4,12 @@ import Link from '@docusaurus/Link'; export default function CustomDocCard(props) { const { title, description, link, icon, small = false } = props; + + // Markdown mode is handled purely in CSS (view-modes.scss turns + // .custom-doc-card into a bullet list). The component keeps the SAME markup + // in every mode so the DOM doesn't change between SSR and hydration — which + // is what caused a brief flash from cards to a list on generated-index pages. + const linkClasses = classNames({ card: true, cardContainer: true, diff --git a/docusaurus/src/components/CustomDocCardsWrapper.js b/docusaurus/src/components/CustomDocCardsWrapper.js index 29b5baf059..1ab4573a65 100644 --- a/docusaurus/src/components/CustomDocCardsWrapper.js +++ b/docusaurus/src/components/CustomDocCardsWrapper.js @@ -1,6 +1,9 @@ import React from 'react'; export default function CustomDocCardsWrapper({ children }) { + // Same markup in every mode (no SSR/hydration DOM swap → no flash). Markdown + // mode is styled entirely in CSS (view-modes.scss flattens this wrapper and + // turns the cards into a bullet list). return (
{children} diff --git a/docusaurus/src/components/ExpandableContent.js b/docusaurus/src/components/ExpandableContent.js index 7c1dcea558..c76a9a57e9 100644 --- a/docusaurus/src/components/ExpandableContent.js +++ b/docusaurus/src/components/ExpandableContent.js @@ -7,24 +7,28 @@ export default function ExpandableContent({ maxHeight = "200px" }) { const [isExpanded, setIsExpanded] = useState(false); + const [interacted, setInteracted] = useState(false); const buttonRef = useRef(null); const toggleExpanded = () => { + // Mark as interacted so the max-height transition is enabled only from the + // first user toggle on (avoids the open-then-collapse flash on page reload). + setInteracted(true); setIsExpanded(!isExpanded); - + // Si on ferme le contenu, scroll vers le bouton après un petit délai if (isExpanded) { setTimeout(() => { - buttonRef.current?.scrollIntoView({ - behavior: 'smooth', - block: 'center' + buttonRef.current?.scrollIntoView({ + behavior: 'smooth', + block: 'center' }); }, 100); } }; return ( -
+
{ + const sync = () => setForceAll(document.documentElement.dataset.viewMode === 'markdown'); + sync(); + const observer = new MutationObserver(sync); + observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-view-mode'] }); + return () => observer.disconnect(); + }, []); + const childArray = React.Children.toArray(children); - const visibleChildren = isExpanded ? childArray : childArray.slice(0, initialVisible); + const showAll = isExpanded || forceAll; + const visibleChildren = showAll ? childArray : childArray.slice(0, initialVisible); const hasMoreItems = childArray.length > initialVisible; const toggleExpanded = () => { @@ -22,8 +35,8 @@ export default function ExpandableDocCardsWrapper({
{visibleChildren}
- - {hasMoreItems && ( + + {hasMoreItems && !forceAll && (
); diff --git a/docusaurus/src/components/HomepageAIButton/homepageaibutton.module.scss b/docusaurus/src/components/HomepageAIButton/homepageaibutton.module.scss index 9927afe07b..736a1c7b1c 100644 --- a/docusaurus/src/components/HomepageAIButton/homepageaibutton.module.scss +++ b/docusaurus/src/components/HomepageAIButton/homepageaibutton.module.scss @@ -1,87 +1,142 @@ +/** Component: Homepage AI Command Bar — V3 matching mockup-v2 exactly */ @use '@site/src/scss/_mixins.scss' as mixins; -:root { - --button-hover-border: rgba(255,255,255,.2); - --button-hover-transition-timing: 0.3s; -} - .homepage-ai-button-container { display: flex; align-items: center; justify-content: center; text-align: center; - margin-top: 10px; - margin-bottom: 72px; z-index: 100; + position: relative; } .homepage-ai-button { position: relative; - background-color: var(--strapi-neutral-0); - border-radius: 4px; - border: 1px solid #666687; + background: var(--strapi-surface-1); + border-radius: 16px; + border: 1px solid var(--strapi-border-strong); display: flex; align-items: center; - justify-content: center; - gap: 10px; - border: solid 1px #DCDCE4; - cursor: pointer; - padding: 26px 34px 26px 26px; - color: var(--strapi-neutral-500, #8E8EA9); - font-feature-settings: 'liga' off, 'clig' off; - font-family: "SF Pro Text", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; - font-size: 18px; - font-style: normal; - font-weight: 600; - line-height: 20px; - letter-spacing: -0.36px; + gap: 12px; + cursor: text; + padding: 0 24px; + width: 100%; + max-width: 580px; + height: 56px; + color: var(--strapi-fg-5); + font-family: var(--strapi-font-family-body); + font-size: 15px; + font-weight: 400; overflow: hidden; + transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1); +} - > svg { - fill: #c0c0cf; - transition: all 0.3s ease-in-out; - } - transition: all 0.3s ease-in-out; +/** Gradient border glow on hover */ +.homepage-ai-button::before { + content: ''; + position: absolute; + inset: -1px; + border-radius: 17px; + background: linear-gradient(135deg, var(--strapi-accent, #4945FF), transparent 40%, transparent 60%, var(--strapi-accent-light, #7B79FF)); + opacity: 0; + transition: opacity 0.3s; + z-index: -1; +} - p { - margin-bottom: 0; - color: var(--strapi-neutral-500); - } +.homepage-ai-button:hover::before { + opacity: 1; } .homepage-ai-button:hover { - cursor: pointer; - background-color: #9736E8; - color: white; - box-shadow: 0 0px 400px 30px #ac73e6, 0 0px 0px 12px #9736e833; - border-color: rgba(255, 255, 255, 0.20) !important; - p { - color: white; - } - > svg { - fill: white; + border-color: transparent; + box-shadow: 0 0 40px var(--strapi-accent-glow), 0 8px 32px rgba(0, 0, 0, 0.1); +} + +/** 4-point star sparkle icon */ +.sparkle { + font-size: 22px; + background: linear-gradient(135deg, var(--strapi-accent-light, #7B79FF), #c084fc); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + flex-shrink: 0; +} + +.homepage-ai-button:hover .sparkle { + animation: sparkleWobble 3s ease-in-out infinite; +} + +@keyframes sparkleWobble { + 0% { transform: rotate(0deg); } + 25% { transform: rotate(15deg); } + 75% { transform: rotate(-15deg); } + 100% { transform: rotate(0deg); } +} + +.placeholder { + flex: 1; + text-align: left; + color: var(--strapi-fg-5); +} + +/** Keyboard shortcut pills */ +.keys { + display: flex; + gap: 4px; + + kbd { + font-family: var(--strapi-font-family-mono, 'JetBrains Mono', monospace); + font-size: 12px; + padding: 4px 8px; + border-radius: 6px; + background: var(--strapi-surface-2); + color: var(--strapi-fg-5); + border: 1px solid var(--strapi-border); + line-height: 1; + min-width: 28px; + text-align: center; } } +/** Shimmer sweep on hover */ .homepage-ai-button::after { content: ""; position: absolute; - z-index: 1; - background-color: rgba(255, 255, 255, 0.50); - height: 200px; - width: 200px; + inset: 0; + background: linear-gradient(90deg, transparent, rgba(73, 69, 255, 0.06), transparent); + background-size: 200% 100%; opacity: 0; - transition: all 0.3s ease-in-out; - border-radius: 50%; - filter: blur(80px); + transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1); } .homepage-ai-button:hover::after { opacity: 1; + animation: shimmer 2s ease-in-out infinite; +} + +@keyframes shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } } +/** Dark mode — more visible text, darker surface */ @include mixins.dark { .homepage-ai-button { - border-color: #32324D; + background: var(--strapi-surface-2); + border-color: var(--strapi-border-strong); + } + + .placeholder { + color: var(--strapi-fg-5); + } + + .keys kbd { + background: var(--strapi-surface-3); + border-color: var(--strapi-border-strong); + color: var(--strapi-fg-4); + } + + .homepage-ai-button:hover { + box-shadow: 0 0 60px var(--strapi-accent-glow), 0 8px 32px rgba(0, 0, 0, 0.3); } -} \ No newline at end of file +} diff --git a/docusaurus/src/components/KapaThemeInjector/KapaThemeInjector.jsx b/docusaurus/src/components/KapaThemeInjector/KapaThemeInjector.jsx new file mode 100644 index 0000000000..69d5c87ed6 --- /dev/null +++ b/docusaurus/src/components/KapaThemeInjector/KapaThemeInjector.jsx @@ -0,0 +1,543 @@ +/** + * KapaThemeInjector — Injects theme-aware styles into Kapa's Shadow DOM. + * + * Kapa renders its modal inside a Shadow DOM (#kapa-widget-container), + * which prevents external CSS from reaching its elements. This component + * observes the page theme (data-theme on ) and injects matching + * styles directly into the shadow root. + */ +import { useEffect } from 'react'; + +const STYLE_ID = 'strapi-kapa-theme'; + +/** Shared styles applied in both modes */ +const SHARED_STYLES = ` + .mantine-Paper-root { + border-radius: 16px !important; + overflow: hidden; + font-family: var(--strapi-font-family-body, 'Inter', sans-serif); + } + .mantine-Modal-header { + padding: 20px 24px !important; + } + .mantine-Modal-header .mantine-Title-root { + font-family: var(--strapi-font-family-display, 'Inter Tight', sans-serif); + font-weight: 700; + letter-spacing: -0.02em; + } + .mantine-CloseButton-root { + border-radius: 10px !important; + transition: all 0.2s !important; + } + .mantine-Button-root { + border-radius: 10px !important; + font-family: var(--strapi-font-family-body, 'Inter', sans-serif) !important; + font-size: 13px !important; + font-weight: 500 !important; + transition: all 0.2s !important; + } + .mantine-Input-input, + .mantine-Textarea-input { + font-family: var(--strapi-font-family-body, 'Inter', sans-serif) !important; + font-size: 14px !important; + transition: border-color 0.2s !important; + } + .mantine-Input-input:focus, + .mantine-Textarea-input:focus { + border-color: #4945FF !important; + box-shadow: none !important; + outline: none !important; + } + .mantine-ActionIcon-root { + background: #4945FF !important; + border: none !important; + border-radius: 10px !important; + transition: all 0.2s !important; + } + .mantine-ActionIcon-root:hover { + background: #7B79FF !important; + } + .mantine-ActionIcon-root svg, + .mantine-ActionIcon-root .mantine-ActionIcon-icon { + color: #FFFFFF !important; + } + .mantine-Overlay-root { + backdrop-filter: blur(4px) !important; + } + .mantine-Popover-dropdown { + border-radius: 10px !important; + } + /* Response links — smooth transition on hover */ + .mantine-Modal-body a:not(.mantine-Paper-root) { + transition: color 0.15s ease !important; + } + /* Code blocks — add padding-right so copy button doesn't overlap text */ + div:has(> .mantine-ActionIcon-root) > div { + padding-right: 40px !important; + } +`; + +const LIGHT_STYLES = ` + .mantine-Paper-root { + background: #FFFFFF !important; + box-shadow: 0 24px 64px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.06) !important; + } + .mantine-Modal-header { + background: #FFFFFF !important; + border-bottom: 1px solid rgba(0, 0, 0, 0.08) !important; + } + .mantine-Modal-header .mantine-Title-root { + color: #09090B !important; + } + .mantine-CloseButton-root { + background: transparent !important; + border: 1px solid rgba(0, 0, 0, 0.08) !important; + color: #09090B !important; + } + .mantine-CloseButton-root:hover { + background: #F4F4F5 !important; + border-color: rgba(0, 0, 0, 0.12) !important; + } + .mantine-Modal-body { + background: #FFFFFF !important; + } + .mantine-Modal-body .mantine-Text-root { + color: #27272A !important; + } + /* Suggestion buttons (default variant, no icon) */ + .mantine-Button-root[data-variant="default"]:not([data-with-left-section]) { + background: #FFFFFF !important; + border: 1px solid rgba(0, 0, 0, 0.08) !important; + color: #27272A !important; + } + .mantine-Button-root[data-variant="default"]:not([data-with-left-section]):hover { + background: #F4F4F5 !important; + border-color: rgba(0, 0, 0, 0.12) !important; + } + .mantine-Button-root[data-variant="default"]:not([data-with-left-section]) .mantine-Button-label { + color: #27272A !important; + } + .mantine-Input-input, + .mantine-Textarea-input { + background: #FFFFFF !important; + border-color: rgba(0, 0, 0, 0.08) !important; + color: #09090B !important; + } + .mantine-Input-input::placeholder, + .mantine-Textarea-input::placeholder { + color: #A1A1AA !important; + } + .mantine-Anchor-root { + color: #A1A1AA !important; + } + /* Disclaimer banner — remove tinted background */ + .scrollable-container div:has(> .mantine-Group-root > .mantine-Text-root) { + background: transparent !important; + border: none !important; + } + /* Links hover — dark violet in light mode */ + .mantine-Modal-body a:not(.mantine-Paper-root):hover { + color: #4945FF !important; + } + .mantine-Popover-dropdown { + background: #FFFFFF !important; + border: 1px solid rgba(0, 0, 0, 0.08) !important; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08) !important; + } +`; + +const DARK_STYLES = ` + /* Override Mantine root CSS variables — Kapa forces data-mantine-color-scheme="light", + so we must redefine these for dark mode to propagate through var() references */ + #kapa-widget-root { + --mantine-color-gray-light: rgba(255, 255, 255, 0.06) !important; + --mantine-color-gray-light-hover: rgba(255, 255, 255, 0.1) !important; + --mantine-color-gray-light-color: #A1A1AA !important; + } + .mantine-Paper-root { + background: #111113 !important; + box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.08) !important; + } + .mantine-Modal-header { + background: #111113 !important; + border-bottom: 1px solid rgba(255, 255, 255, 0.06) !important; + } + .mantine-Modal-header .mantine-Title-root { + color: #FAFAFA !important; + } + .mantine-CloseButton-root { + background: transparent !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + color: #FAFAFA !important; + } + .mantine-CloseButton-root:hover { + background: #1F1F23 !important; + } + .mantine-CloseButton-root svg { + color: #FAFAFA !important; + } + .mantine-Modal-body { + background: #111113 !important; + color: #D4D4D8 !important; + } + .mantine-Modal-body .mantine-Text-root { + color: #D4D4D8 !important; + } + /* Response content — headings, text, tables, links */ + .mantine-Modal-body h1, + .mantine-Modal-body h2, + .mantine-Modal-body h3, + .mantine-Modal-body h4 { + color: #FAFAFA !important; + } + .mantine-Modal-body p, + .mantine-Modal-body li, + .mantine-Modal-body td, + .mantine-Modal-body span { + color: #D4D4D8 !important; + } + .mantine-Modal-body th { + color: #FAFAFA !important; + background: rgba(255, 255, 255, 0.04) !important; + } + .mantine-Modal-body table { + border-color: rgba(255, 255, 255, 0.08) !important; + } + .mantine-Modal-body td, + .mantine-Modal-body th { + border-color: rgba(255, 255, 255, 0.08) !important; + } + .mantine-Modal-body a { + color: #7B79FF !important; + } + /* Links hover — brighter violet in dark mode */ + .mantine-Modal-body a:not(.mantine-Paper-root):hover { + color: #A5A3FF !important; + } + .mantine-Modal-body strong { + color: #FAFAFA !important; + } + /* Source cards (anchor elements styled as Paper) */ + a.mantine-Paper-root { + background: #18181B !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + color: #D4D4D8 !important; + } + a.mantine-Paper-root:hover { + background: #1F1F23 !important; + border-color: rgba(255, 255, 255, 0.1) !important; + } + a.mantine-Paper-root .mantine-Text-root { + color: #A1A1AA !important; + } + /* Action buttons (New chat, Copy, Good/Bad answer) */ + .mantine-Modal-body .mantine-UnstyledButton-root { + color: #D4D4D8 !important; + } + .mantine-Modal-body .mantine-UnstyledButton-root:hover { + background: rgba(255, 255, 255, 0.05) !important; + } + /* SVGs in modal body inherit light color */ + .mantine-Modal-body svg { + color: #A1A1AA !important; + } + /* Disclaimer banner — remove the light bg, keep it transparent */ + .scrollable-container div:has(> .mantine-Group-root > .mantine-Text-root) { + background: transparent !important; + border: none !important; + } + /* Use MCP button in header — dark mode */ + .mantine-Modal-header .mantine-Group-root:has(> .mantine-Text-root) { + background: #18181B !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + color: #D4D4D8 !important; + } + .mantine-Modal-header .mantine-Group-root:has(> .mantine-Text-root):hover { + background: #1F1F23 !important; + border-color: rgba(255, 255, 255, 0.1) !important; + } + .mantine-Modal-header .mantine-Group-root:has(> .mantine-Text-root) .mantine-Text-root { + color: #D4D4D8 !important; + } + .mantine-Modal-header .mantine-Group-root:has(> .mantine-Text-root) svg { + color: #D4D4D8 !important; + } + /* Suggestion buttons (default variant, no icon) */ + .mantine-Button-root[data-variant="default"]:not([data-with-left-section]) { + --button-bg: #18181B !important; + --button-hover: #1F1F23 !important; + --button-color: #D4D4D8 !important; + --button-bd: 1px solid rgba(255, 255, 255, 0.06) !important; + background: #18181B !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + color: #D4D4D8 !important; + } + .mantine-Button-root[data-variant="default"]:not([data-with-left-section]):hover { + background: #1F1F23 !important; + border-color: rgba(255, 255, 255, 0.1) !important; + } + .mantine-Button-root[data-variant="default"]:not([data-with-left-section]) .mantine-Button-label { + color: #D4D4D8 !important; + } + /* Action buttons — New chat, Copy, Good/Bad answer (light variant) */ + .mantine-Button-root[data-variant="light"] { + --button-bg: rgba(255, 255, 255, 0.04) !important; + --button-hover: rgba(255, 255, 255, 0.1) !important; + --button-color: #71717A !important; + --button-bd: 1px solid transparent !important; + background: rgba(255, 255, 255, 0.04) !important; + border: 1px solid transparent !important; + color: #71717A !important; + } + .mantine-Button-root[data-variant="light"]:hover { + background: rgba(255, 255, 255, 0.1) !important; + border-color: transparent !important; + color: #D4D4D8 !important; + } + .mantine-Button-root[data-variant="light"] .mantine-Button-label { + color: inherit !important; + } + .mantine-Button-root[data-variant="light"] svg { + color: inherit !important; + } + /* Input wrapper (inner Paper-root) — match modal background */ + .mantine-Paper-root:has(.mantine-Textarea-input) { + background: transparent !important; + border: 1px solid rgba(255, 255, 255, 0.08) !important; + } + .mantine-Input-input, + .mantine-Textarea-input { + background: transparent !important; + border-color: rgba(255, 255, 255, 0.06) !important; + color: #FAFAFA !important; + } + .mantine-Input-input::placeholder, + .mantine-Textarea-input::placeholder { + color: #71717A !important; + } + .mantine-Anchor-root { + color: #71717A !important; + } + .mantine-Popover-dropdown { + background: #18181B !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3) !important; + color: #FAFAFA !important; + } + .mantine-Popover-dropdown * { + color: #D4D4D8 !important; + } + .mantine-Popover-dropdown h1, + .mantine-Popover-dropdown h2, + .mantine-Popover-dropdown h3, + .mantine-Popover-dropdown h4, + .mantine-Popover-dropdown strong { + color: #FAFAFA !important; + } + .mantine-Popover-dropdown a { + color: #7B79FF !important; + } + .mantine-Popover-dropdown a:hover { + color: #A5A3FF !important; + } + .mantine-Popover-dropdown svg { + color: #D4D4D8 !important; + } + /* "Use MCP" popover — client logos (Cursor, VS Code, Claude Code) are + monochrome currentColor SVGs. The generic gray above rendered them as a + dull, barely-visible gray on the dark dropdown; show them in near-white so + they read clearly. (.mantine-b5sdit is the per-row icon wrapper.) */ + .mantine-Popover-dropdown .mantine-b5sdit svg { + color: #FAFAFA !important; + } + .mantine-Popover-dropdown .mantine-Paper-root { + background: #1F1F23 !important; + box-shadow: none !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + } + .mantine-Popover-dropdown .mantine-Paper-root:hover { + background: #27272A !important; + border-color: rgba(255, 255, 255, 0.1) !important; + } + /* Deep Thinking button — dark-mode base state (default variant + left section) */ + .mantine-Button-root[data-variant="default"][data-with-left-section] { + background: #18181B !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + color: #D4D4D8 !important; + } + .mantine-Button-root[data-variant="default"][data-with-left-section] .mantine-Button-label { + color: #D4D4D8 !important; + } + .mantine-Button-root[data-variant="default"][data-with-left-section]:hover { + background: #1F1F23 !important; + border-color: rgba(255, 255, 255, 0.1) !important; + } + /* Deep Thinking active/expanded state — violet accent */ + .mantine-Button-root[data-variant="default"][data-with-left-section][aria-expanded="true"] { + background: rgba(73, 69, 255, 0.12) !important; + border-color: rgba(73, 69, 255, 0.4) !important; + color: #A5B4FC !important; + } + .mantine-Button-root[data-variant="default"][data-with-left-section][aria-expanded="true"] .mantine-Button-label { + color: #A5B4FC !important; + } + .mantine-Button-root[data-variant="default"][data-with-left-section][aria-expanded="true"] svg { + color: #A5B4FC !important; + } + .mantine-Alert-root { + background: transparent !important; + border: 1px solid rgba(255, 255, 255, 0.06) !important; + } + .mantine-Modal-body code, + .mantine-Modal-header code { + background: #09090B !important; + color: #E4E4E7 !important; + } + .mantine-Code-root { + background: rgba(255, 255, 255, 0.06) !important; + color: #E4E4E7 !important; + } + .mantine-Modal-body pre, + .mantine-Modal-header pre { + border: 1px solid rgba(255, 255, 255, 0.06) !important; + } +`; + +function injectStyles(theme) { + const container = document.getElementById('kapa-widget-container'); + const shadow = container?.shadowRoot; + if (!shadow) return; + + let styleEl = shadow.getElementById(STYLE_ID); + if (!styleEl) { + styleEl = document.createElement('style'); + styleEl.id = STYLE_ID; + shadow.appendChild(styleEl); + } + + const themeStyles = theme === 'dark' ? DARK_STYLES : LIGHT_STYLES; + styleEl.textContent = SHARED_STYLES + themeStyles; +} + +const DEEP_THINKING_LABEL_DISABLED = 'Enable deep thinking'; +const DEEP_THINKING_LABEL_ENABLED = 'Deep thinking enabled'; + +/** + * Overrides the Deep Thinking button label based on its toggle state. + * + * Kapa uses data-variant="outline" when enabled, "default" when disabled. + * React re-renders the label text on every hover/state change, replacing + * any DOM text we set. To counteract this we observe both: + * – button attributes (data-variant) to detect toggle state changes + * – label childList to catch React text-node replacements + * + * Returns a cleanup function, or null if the button is not found yet. + */ +function setupDeepThinkingLabel(shadow) { + if (!shadow) return null; + + const btn = shadow.querySelector( + '.mantine-Button-root[data-with-left-section][aria-haspopup="dialog"]' + ); + if (!btn) return null; + + const labelEl = btn.querySelector('.mantine-Button-label'); + if (!labelEl) return null; + + let updating = false; // guard against infinite recursion + + const update = () => { + if (updating) return; + updating = true; + const isEnabled = btn.getAttribute('data-variant') === 'outline'; + const desired = isEnabled + ? DEEP_THINKING_LABEL_ENABLED + : DEEP_THINKING_LABEL_DISABLED; + if (labelEl.textContent !== desired) { + labelEl.textContent = desired; + } + updating = false; + }; + + // Set initial label + update(); + + // Watch button attributes for state changes (variant, aria-expanded) + const btnObs = new MutationObserver(update); + btnObs.observe(btn, { + attributes: true, + attributeFilter: ['data-variant', 'aria-expanded'], + }); + + // Watch label childList to catch React re-renders that replace our text + const labelObs = new MutationObserver(update); + labelObs.observe(labelEl, { childList: true, subtree: true }); + + return { + disconnect() { + btnObs.disconnect(); + labelObs.disconnect(); + }, + }; +} + +export default function KapaThemeInjector() { + useEffect(() => { + if (typeof window === 'undefined') return; + + const getTheme = () => document.documentElement.dataset.theme || 'light'; + let deepThinkingObserver = null; + let trackedBtn = null; // the DOM node we're currently observing + + function ensureDeepThinkingLabel(shadow) { + if (!shadow) return; + const btn = shadow.querySelector( + '.mantine-Button-root[data-with-left-section][aria-haspopup="dialog"]' + ); + // Re-attach if the button is new (Kapa re-rendered its tree) + if (btn && btn !== trackedBtn) { + deepThinkingObserver?.disconnect(); + deepThinkingObserver = setupDeepThinkingLabel(shadow); + trackedBtn = btn; + } + } + + // Inject immediately if container already exists + injectStyles(getTheme()); + + const container = document.getElementById('kapa-widget-container'); + if (container?.shadowRoot) { + ensureDeepThinkingLabel(container.shadowRoot); + } + + // Observe theme changes on + const themeObserver = new MutationObserver(() => { + injectStyles(getTheme()); + // Kapa may re-render on theme change — re-attach label observer + const c = document.getElementById('kapa-widget-container'); + if (c?.shadowRoot) ensureDeepThinkingLabel(c.shadowRoot); + }); + themeObserver.observe(document.documentElement, { + attributes: true, + attributeFilter: ['data-theme'], + }); + + // Observe when Kapa container appears or re-renders in the DOM + const bodyObserver = new MutationObserver(() => { + const c = document.getElementById('kapa-widget-container'); + if (c?.shadowRoot) { + injectStyles(getTheme()); + ensureDeepThinkingLabel(c.shadowRoot); + } + }); + bodyObserver.observe(document.body, { childList: true, subtree: true }); + + return () => { + themeObserver.disconnect(); + bodyObserver.disconnect(); + deepThinkingObserver?.disconnect(); + }; + }, []); + + return null; +} diff --git a/docusaurus/src/components/MarkdownAlternateLink.js b/docusaurus/src/components/MarkdownAlternateLink.js new file mode 100644 index 0000000000..101d06c798 --- /dev/null +++ b/docusaurus/src/components/MarkdownAlternateLink.js @@ -0,0 +1,27 @@ +import React from 'react'; +import Head from '@docusaurus/Head'; +import { useLocation } from '@docusaurus/router'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +/** + * Emits in the + * page . A standard machine-readable signal pointing agents/crawlers to + * the clean Markdown twin of the page (generated at build time, see + * generate-llms.js writePerPageMarkdown). Rendered once per doc (on the H1). + */ +export default function MarkdownAlternateLink() { + const { pathname } = useLocation(); + const { siteConfig } = useDocusaurusContext(); + + const clean = (pathname || '').replace(/\/$/, ''); + if (!clean || clean === '') return null; // homepage: HTML only + + const origin = (siteConfig.url || '').replace(/\/$/, ''); + const href = `${origin}${clean}.md`; + + return ( + + + + ); +} diff --git a/docusaurus/src/components/MermaidWithFallback.js b/docusaurus/src/components/MermaidWithFallback.js index 18591edd1b..c14c6704f3 100644 --- a/docusaurus/src/components/MermaidWithFallback.js +++ b/docusaurus/src/components/MermaidWithFallback.js @@ -235,30 +235,11 @@ export default function DocusaurusMermaidFileFallback({ } }, [isLoading, chartContent, shouldRender, renderFailed, checkIfVisible]); - // Initialize zoom on the fallback image - useEffect(() => { - if (renderFailed && imgRef.current) { - import('medium-zoom').then((module) => { - const mediumZoom = module.default; - try { - const zoom = mediumZoom(imgRef.current, { - margin: 24, - background: 'rgba(0, 0, 0, 0.7)', - scrollOffset: 0, - }); - - return () => { - zoom.detach(); - }; - } catch (error) { - console.error('Failed to apply zoom:', error); - } - }).catch(error => { - console.error('Failed to import medium-zoom:', error); - }); - } - }, [renderFailed]); - + // Note: the Mermaid fallback image is intentionally NOT zoomable. It used to + // attach medium-zoom here AND opt into the site-wide zoom (via the + // medium-zoom-image class + data-zoomable), which double-bound the zoom and + // broke the layout. The fallback is now a plain, non-zoomable image. + // Show loading state if (isLoading) { return ( @@ -274,13 +255,11 @@ export default function DocusaurusMermaidFileFallback({ if (renderFailed) { return (
- {alt
Please note that the diagram couldn't be rendered, probably due to a Mermaid.js issue. A static image is displayed instead. diff --git a/docusaurus/src/components/NavbarBreadcrumbs/NavbarBreadcrumbs.jsx b/docusaurus/src/components/NavbarBreadcrumbs/NavbarBreadcrumbs.jsx new file mode 100644 index 0000000000..7031238d7e --- /dev/null +++ b/docusaurus/src/components/NavbarBreadcrumbs/NavbarBreadcrumbs.jsx @@ -0,0 +1,152 @@ +import React, { useRef, useEffect, useCallback } from 'react'; +import { useHistory } from '@docusaurus/router'; +import styles from './NavbarBreadcrumbs.module.scss'; + +const PRODUCTS = { + cms: { switchTo: 'cloud', switchHref: '/cloud/intro' }, + cloud: { switchTo: 'cms', switchHref: '/cms/intro' }, +}; + +const SEGMENT_REWRITES = { + 'cms/api': '/cms/api/content-api', +}; + +const ROOT_LINKS = { cms: '/cms/intro', cloud: '/cloud/intro' }; + +function buildCrumbs(pathname) { + const segments = pathname.replace(/^\//, '').replace(/\/$/, '').split('/'); + if (segments.length === 0) return []; + + return segments.map((segment, index) => { + const cumPath = segments.slice(0, index + 1).join('/'); + let href; + if (index === 0 && ROOT_LINKS[segment]) { + href = ROOT_LINKS[segment]; + } else if (SEGMENT_REWRITES[cumPath]) { + href = SEGMENT_REWRITES[cumPath]; + } else { + href = '/' + cumPath; + } + return { label: segment, href, isLast: index === segments.length - 1, isRoot: index === 0 }; + }); +} + +/** + * Renders breadcrumbs into the container ref imperatively. + * This bypasses React's render cycle which Docusaurus blocks for the navbar. + */ +function renderBreadcrumbs(container, pathname) { + if (!container) return; + + const isDocPage = pathname.startsWith('/cms/') || pathname.startsWith('/cloud/'); + container.style.display = ''; + + if (!isDocPage) { + // Homepage: show product links + let html = `
`; + html += ``; + container.innerHTML = html; + return; + } + + const rootSegment = pathname.split('/')[1]; // 'cms' or 'cloud' + const product = PRODUCTS[rootSegment]; + const crumbs = buildCrumbs(pathname); + + // Build HTML + let html = `
`; + html += ``; + container.innerHTML = html; +} + +/** + * Mockup-v3 style breadcrumbs that render inside the navbar. + * Shows a monospace path-style trail: cms / getting-started / quick-start + * The first segment (cms/cloud) shows a subtle switch link on hover. + * + * Uses imperative DOM updates because Docusaurus memoizes the navbar tree + * and prevents React re-renders on client-side navigation. + */ +export default function NavbarBreadcrumbs() { + const containerRef = useRef(null); + const lastPathRef = useRef(''); + const routerHistory = useHistory(); + + const update = useCallback(() => { + const current = window.location.pathname; + if (current !== lastPathRef.current) { + lastPathRef.current = current; + renderBreadcrumbs(containerRef.current, current); + } + }, []); + + // The crumbs are rendered as plain (imperative HTML), which would + // trigger a full page reload and reset the view mode (notably losing AI mode, + // which isn't persisted). Intercept same-origin clicks and navigate via the + // SPA router instead, so the React state — and the current view mode — is + // preserved across breadcrumb navigation. + const onClick = useCallback((e) => { + const a = e.target.closest && e.target.closest('a'); + if (!a) return; + const href = a.getAttribute('href'); + if (!href || !href.startsWith('/')) return; // external/product-switch handled normally + if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return; + e.preventDefault(); + routerHistory.push(href); + }, [routerHistory]); + + useEffect(() => { + // Initial render + lastPathRef.current = window.location.pathname; + renderBreadcrumbs(containerRef.current, window.location.pathname); + const container = containerRef.current; + if (container) container.addEventListener('click', onClick); + + // Listen for all navigation types + // 1. popstate (back/forward) + window.addEventListener('popstate', update); + + // 2. Patch pushState/replaceState for SPA navigations + const origPush = history.pushState; + const origReplace = history.replaceState; + history.pushState = function (...args) { + origPush.apply(this, args); + // Defer to next microtask so URL is updated + Promise.resolve().then(update); + }; + history.replaceState = function (...args) { + origReplace.apply(this, args); + Promise.resolve().then(update); + }; + + return () => { + window.removeEventListener('popstate', update); + history.pushState = origPush; + history.replaceState = origReplace; + if (container) container.removeEventListener('click', onClick); + }; + }, [update, onClick]); + + return
; +} diff --git a/docusaurus/src/components/NavbarBreadcrumbs/NavbarBreadcrumbs.module.scss b/docusaurus/src/components/NavbarBreadcrumbs/NavbarBreadcrumbs.module.scss new file mode 100644 index 0000000000..6f5a084062 --- /dev/null +++ b/docusaurus/src/components/NavbarBreadcrumbs/NavbarBreadcrumbs.module.scss @@ -0,0 +1,127 @@ +@use '../../scss/mixins' as *; + +.navbarBreadcrumbs { + display: flex; + align-items: center; + gap: 20px; + margin-left: 20px; +} + +.separator { + width: 1px; + height: 20px; + background: var(--strapi-neutral-300); + flex-shrink: 0; +} + +.crumbs { + display: flex; + align-items: center; + gap: 6px; + font-family: var(--strapi-font-family-technical, 'JetBrains Mono', monospace); + font-size: 13px; + color: var(--strapi-neutral-600); +} + +.slash { + color: var(--strapi-neutral-400); + user-select: none; +} + +.homeDash { + color: var(--strapi-neutral-400); + user-select: none; + margin: 0 2px; +} + +.crumbLink { + color: var(--strapi-neutral-600); + text-decoration: none; + transition: color 0.15s ease; + + &:hover { + color: var(--strapi-primary-600); + text-decoration: none; + } +} + +.current { + color: var(--strapi-primary-600); + font-weight: 500; +} + +/* ── Root crumb with inline product switch ── */ +.rootCrumb { + position: relative; + display: inline-flex; + align-items: center; + gap: 0; + + &:hover .switchLink { + opacity: 1; + max-width: 80px; + margin-left: 8px; + } +} + +.switchLink { + display: inline-flex; + align-items: center; + font-family: var(--strapi-font-family-technical, 'JetBrains Mono', monospace); + font-size: 12px; + color: var(--strapi-neutral-400); + text-decoration: none; + white-space: nowrap; + overflow: hidden; + max-width: 0; + opacity: 0; + margin-left: 0; + transition: opacity 0.2s ease, max-width 0.25s ease, margin-left 0.25s ease; + + &:hover { + color: var(--strapi-primary-600); + text-decoration: none; + } +} + +/* ── Dark mode ── */ +@include dark { + .separator { + background: var(--strapi-neutral-400); + } + + .slash { + color: var(--strapi-neutral-500); + } + + .crumbLink { + color: var(--strapi-neutral-500); + + &:hover { + color: var(--strapi-primary-600); + } + } + + .current { + color: var(--strapi-primary-600); + } + + .switchLink { + color: var(--strapi-neutral-500); + + &:hover { + color: var(--strapi-primary-600); + } + } + + .homeDash { + color: var(--strapi-neutral-500); + } +} + +// Hide on mobile — too cluttered +@include medium-down { + .navbarBreadcrumbs { + display: none; + } +} diff --git a/docusaurus/src/components/NavbarSearchAI/NavbarSearchAI.jsx b/docusaurus/src/components/NavbarSearchAI/NavbarSearchAI.jsx new file mode 100644 index 0000000000..2b2f03f722 --- /dev/null +++ b/docusaurus/src/components/NavbarSearchAI/NavbarSearchAI.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import SearchBar from '@theme/SearchBar'; +import Icon from '../Icon'; +import styles from './NavbarSearchAI.module.scss'; + +export default function NavbarSearchAI() { + return ( +
+
+ +
+
+ +
+ ); +} diff --git a/docusaurus/src/components/NavbarSearchAI/NavbarSearchAI.module.scss b/docusaurus/src/components/NavbarSearchAI/NavbarSearchAI.module.scss new file mode 100644 index 0000000000..c0adcf8d9e --- /dev/null +++ b/docusaurus/src/components/NavbarSearchAI/NavbarSearchAI.module.scss @@ -0,0 +1,194 @@ +@use '../../scss/mixins' as *; + +.wrapper { + display: flex; + align-items: center; + border: 1px solid var(--strapi-neutral-200); + border-radius: 10px; + background: var(--strapi-neutral-0); + height: 36px; + min-width: 310px; + overflow: hidden; + transition: border-color 0.15s ease, box-shadow 0.15s ease; + + &:hover { + border-color: var(--strapi-neutral-300); + } + + &:focus-within { + border-color: var(--strapi-primary-500); + box-shadow: 0 0 0 3px rgba(73, 69, 255, 0.1); + } +} + +/** Search slot: override MeiliSearch defaults */ +.searchSlot { + display: flex; + align-items: center; + flex: 1 1 50%; + height: 100%; + overflow: hidden; + border-radius: 9px 0 0 9px; + transition: background 0.15s ease; + + &:hover { + background: var(--strapi-neutral-100); + + :global(.docsearch-btn-placeholder) { + color: var(--strapi-neutral-600); + } + + :global(.docsearch-btn-placeholder)::before { + color: var(--strapi-primary-500); + } + } + + :global(.navbar__search) { + width: 100%; + min-width: 0; + padding: 0; + } + + :global(.docsearch-btn) { + all: unset; + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + height: 36px; + width: 100%; + min-width: 0; + box-sizing: border-box; + cursor: pointer; + padding: 0 10px; + font-family: var(--strapi-font-family-body); + font-size: 13px; + color: var(--strapi-neutral-500); + } + + :global(.docsearch-btn-icon-container) { + display: none; + } + + :global(.docsearch-btn-placeholder) { + font-family: var(--strapi-font-family-body); + font-size: 13px; + font-weight: 500; + color: var(--strapi-neutral-400); + transition: color 0.15s ease; + + &::before { + content: '\E30C'; + font-family: "Phosphor"; + color: var(--strapi-neutral-400); + margin-right: 8px; + font-size: 15px; + position: relative; + top: 2px; + transition: color 0.15s ease; + } + } + + :global(.docsearch-btn-keys) { + display: none; + } + + :global(.docsearch-btn-key) { + font-family: var(--strapi-font-family-technical); + font-size: 10px; + font-weight: 500; + color: var(--strapi-neutral-400); + background: var(--strapi-neutral-100); + border: none; + border-radius: 4px; + padding: 1px 4px; + box-shadow: none; + line-height: 1.4; + width: auto; + min-width: 0; + } +} + +.divider { + width: 1px; + height: 20px; + background: var(--strapi-neutral-200); + flex-shrink: 0; +} + +.askAI { + display: flex; + align-items: center; + justify-content: center; + gap: 7px; + flex: 1 1 50%; + height: 100%; + padding: 0 12px; + border: none; + background: transparent; + cursor: pointer; + white-space: nowrap; + color: var(--strapi-neutral-400); + font-family: var(--strapi-font-family-body); + font-size: 13px; + font-weight: 500; + border-radius: 0 9px 9px 0; + transition: color 0.15s ease, background 0.15s ease; + + i { + font-size: 15px; + color: var(--strapi-neutral-400); + position: relative; + top: 1px; + transition: color 0.15s ease; + } + + &:hover { + background: var(--strapi-neutral-100); + color: var(--strapi-neutral-600); + + i { + color: var(--strapi-primary-500); + } + } +} + +/** Dark mode */ +@include dark { + .wrapper { + background: var(--strapi-neutral-100); + border-color: var(--strapi-neutral-300); + + &:hover { + border-color: var(--strapi-neutral-400); + } + } + + .searchSlot:hover { + background: rgba(255, 255, 255, 0.06); + + :global(.docsearch-btn-placeholder) { + color: rgba(255, 255, 255, 0.8); + } + } + + .divider { + background: var(--strapi-neutral-300); + } + + .askAI:hover { + background: rgba(255, 255, 255, 0.06); + color: rgba(255, 255, 255, 0.8); + + i { + color: var(--strapi-primary-500); + } + } +} + +/** Hide on mobile — use mobile sidebar search instead */ +@include medium-down { + .wrapper { + display: none; + } +} diff --git a/docusaurus/src/components/NextSteps/NextSteps.jsx b/docusaurus/src/components/NextSteps/NextSteps.jsx new file mode 100644 index 0000000000..d4ed1f807d --- /dev/null +++ b/docusaurus/src/components/NextSteps/NextSteps.jsx @@ -0,0 +1,62 @@ +import React from 'react'; +import styles from './next-steps.module.scss'; + +/** + * NextSteps — a beautiful numbered step list for "What's next?" sections. + * + * Usage in MDX: + * ```mdx + * + * + * + * + * ``` + */ +function Step({ title, description, link, index }) { + const content = ( +
+
+ {index} +
+
+
{title}
+ {description &&
{description}
} +
+ {link &&
} +
+ ); + + if (link) { + return
{content}; + } + return content; +} + +export default function NextSteps({ title = "What's next?", children }) { + // Inject index into Step children + const steps = React.Children.toArray(children).filter(Boolean); + + return ( +
+ {title &&

{title}

} +
+ {steps.map((child, i) => { + if (React.isValidElement(child) && child.type === Step) { + return React.cloneElement(child, { index: i + 1, key: i }); + } + return child; + })} +
+
+ ); +} + +NextSteps.Step = Step; diff --git a/docusaurus/src/components/NextSteps/next-steps.module.scss b/docusaurus/src/components/NextSteps/next-steps.module.scss new file mode 100644 index 0000000000..a796c47e7d --- /dev/null +++ b/docusaurus/src/components/NextSteps/next-steps.module.scss @@ -0,0 +1,127 @@ +/** NextSteps — "What's next?" numbered step list + * Design matching the v3 quick-start guide screenshot: + * - Numbered circles with accent background + * - Clean separators between steps + * - Generous vertical spacing + */ +@use '@site/src/scss/_mixins.scss' as *; + +.wrapper { + margin: 48px 0 32px; + padding: 0; +} + +.title { + font-family: var(--strapi-font-family-display, 'Outfit', sans-serif); + font-size: 24px; + font-weight: 700; + letter-spacing: -0.02em; + color: var(--strapi-fg-1, var(--ifm-font-color-base)); + margin: 0 0 32px; + border: none; + padding: 0; +} + +.steps { + display: flex; + flex-direction: column; + gap: 0; +} + +.stepLink { + text-decoration: none !important; + color: inherit; + + &:hover { + text-decoration: none !important; + color: inherit; + } + + &:hover .step { + background: var(--strapi-surface-2, #F4F4F5); + } + + &:hover .stepArrow { + opacity: 1; + transform: translateX(0); + color: var(--strapi-accent, #4945FF); + } + + &:hover .stepTitle { + color: var(--strapi-accent, #4945FF); + } +} + +.step { + display: flex; + align-items: center; + gap: 20px; + padding: 28px 24px; + border-bottom: 1px solid var(--strapi-border, rgba(0, 0, 0, 0.06)); + transition: background 0.2s; + border-radius: 12px; + margin: 0 -24px; + width: calc(100% + 48px); + + &:last-child { + border-bottom: none; + } +} + +.stepNumber { + width: 40px; + height: 40px; + border-radius: 10px; + background: rgba(73, 69, 255, 0.08); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + + span { + font-family: var(--strapi-font-family-display, 'Outfit', sans-serif); + font-size: 15px; + font-weight: 600; + color: var(--strapi-accent, #4945FF); + } +} + +.stepContent { + flex: 1; + min-width: 0; +} + +.stepTitle { + font-family: var(--strapi-font-family-display, 'Outfit', sans-serif); + font-size: 16px; + font-weight: 600; + color: var(--strapi-fg-1, var(--ifm-font-color-base)); + margin-bottom: 4px; + transition: color 0.2s; +} + +.stepDesc { + font-size: 14px; + line-height: 1.5; + color: var(--strapi-fg-4, var(--ifm-font-color-secondary)); +} + +.stepArrow { + font-size: 18px; + color: var(--strapi-fg-5, #A1A1AA); + opacity: 0; + transform: translateX(-4px); + transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); + flex-shrink: 0; +} + +/* Dark mode */ +@include dark { + .stepNumber { + background: rgba(73, 69, 255, 0.15); + } + + .stepLink:hover .step { + background: var(--strapi-surface-2, #18181B); + } +} diff --git a/docusaurus/src/components/PageFeedback/FeedbackForm.jsx b/docusaurus/src/components/PageFeedback/FeedbackForm.jsx new file mode 100644 index 0000000000..79a0eea00c --- /dev/null +++ b/docusaurus/src/components/PageFeedback/FeedbackForm.jsx @@ -0,0 +1,82 @@ +import React, { useState } from 'react'; + +const MIN_COMMENT_LENGTH = 20; +const MAX_COMMENT_LENGTH = 2000; + +export default function FeedbackForm({ + onSubmit, + onCancel, + isSubmitting, + required, +}) { + const [comment, setComment] = useState(''); + + const trimmed = comment.trim(); + const isTooLong = trimmed.length > MAX_COMMENT_LENGTH; + const canSubmit = required + ? trimmed.length >= MIN_COMMENT_LENGTH && !isTooLong && !isSubmitting + : !isTooLong && !isSubmitting; + + function handleSubmit(e) { + e.preventDefault(); + if (!canSubmit) return; + const hp = e.target.elements._hp?.value || ''; + onSubmit(trimmed || null, hp); + } + + return ( +
+ +