Several updates to the API have been made to support working with Bases. This is a brand new feature that is still in development. Attempting to use any of these endpoints while the feature is in development will throw an error. A release announcement will be published here when the feature is available to all users.Brand new endpoints related to working with Bases:
Fetch bases (GET /v2/bases) — lists all the bases in your workspace, including each base’s GitHub connection.
Fetch a base (GET /v2/bases/{baseId}) — returns a single base, with its text item count, its folders and the projects connected to it.
Create bases (POST /v2/bases) — creates one or more bases. Supports linking new bases to a GitHub repository, which also kicks off an initial scan.
Update a base (PATCH /v2/bases/{baseId}) — edit an individual base. Currently supports name, developer ID and connecting to a GitHub repository.
Create text items from a base (POST /v2/textItems/fromBase) — copies text items from a base into a project connected to that base, optionally placing them in a new or existing block.
Publish to base (POST /v2/projects/{projectId}/publish) — publishes a project’s Modified and New text items to its base, either all of them or the ones you name. Text items in Conflict are only acted on when you choose which version to keep.
Update text items from base (POST /v2/projects/{projectId}/updateFromBase) — updates Outdated or Conflict text items in a project to their base’s version.
The following existing endpoints now include support for Bases:
Fetch text items (GET /v2/textItems) - Optional bases filter to retrieve Base Text Items. Project Text Items now include nullable baseId and baseTextItemId fields.
Export text items (GET /v2/textItems/export) - Optional bases filter to retrieve Base Text Items. If the same text item appears in a fetched project and base, the project’s value overrides the base’s.
Update text items (PUT /v2/textItems) - Takes an optional projectId parameter on each text item to update, to disambiguate between the same base text item appearing in multiple projects.
Delete text items (DELETE /v2/textItems) - Takes an optional projectId parameter to disambiguate between text items that are connected to the same library component or base text item.
Fetch projects (GET /v2/projects) - Added baseId to each project in the response.
Create project (POST /v2/projects) - Added optional baseId field to support creating a project from a base.
Maintenance release to resolve security vulnerabilities in DOMPurify. Release Notes. Legacy customers using the React SDK should upgrade to the latest version. If you cannot upgrade ditto-react, you may also pin the DOMPurify version to ^3.4.17 to resolve the security vulnerabilities without upgrading the Ditto SDK directly.
Delete Text Items (DELETE /v2/textItems) now optionally accepts a projectId to disambiguate Developer IDs that match multiple project text items. A Developer ID could match multiple project text items if it is the ID of a library component or base text item. Provide a projectId to specify which individual text item to delete, while leaving all other instances unchanged. The projectId should sufficiently disambiguate as long as there are not multiple instances of the same library component in that project. In that case, you must delete the target instance(s) through Ditto app. Prior to this change, deletion of library component instances was not supported at all through this endpoint.
delete_text_items now optionally accepts a projectId to disambiguate Developer Ids that match multiple project text items. Follows the same patterns as the API endpoint.
For workspaces that have opted into library component versioning, adds endpoints for saving component changes without publishing them, publishing or discarding those changes, and bringing instances up to date. In workspaces that haven’t opted in, these endpoints return a 404.
Fetch unpublished component changes (GET /v2/components/staged): returns the components that have unpublished changes, with those changes applied. Takes the same filter and richText parameters as Fetch components.
Save unpublished component changes (PATCH /v2/components/staged): saves changes to text, plurals, tags, notes, or characterLimit without making them available to instances.
Publish component changes (POST /v2/components/staged/publish): publishes the unpublished changes, allowing component instances to adopt those changes.
Discard unpublished component changes (DELETE /v2/components/staged): discards the unpublished changes, leaving the published component and its instances unchanged.
Upgrade component instances (PATCH /v2/components/upgrade): brings text items that are instances of a component up to date with its latest published version. Instances with local edits return a 409 unless discardLocalEdits is set.
In these workspaces, existing endpoints also include versioning details:
Fetch components (GET /v2/components): each component includes hasUnpublishedChanges.
Update components (PATCH /v2/components): can’t update text, plurals, tags, notes, or characterLimit on a component with unpublished changes, since publishing those changes would overwrite the updates.
Fetch text items (GET /v2/textItems): each text item includes component, with the component’s id and the instance’s state: current, outdated, modified, or conflict. It’s null for text items that aren’t instances.
Link Figma nodes (POST /v2/textItems/linkFigmaNodes) now supports linking Figma text nodes to many text items in one request. Request body now takes links, a mapping of text item developer IDs to Figma node IDs. Up to 500 distinct node IDs are allowed per request across all links. Reports whether linking was successful for each node in request.
The previous request body (textItemId with figma.nodeIds) is no longer accepted. Send one links entry to link
nodes to a single text item.
Omitting branchId always targets linking nodes in the main Figma file. To link nodes in a branch, pass its ID explicitly in the top-level branchId field.
Add the update_project tool, which supports updating an individual project’s name, Developer ID, and/or connected base. More details on bases and connecting projects to bases coming soon!Add the link_figma_nodes_to_text_items tool for linking Figma text nodes to many text items in one call. It takes a mapping of text item developer IDs to Figma node IDs, up to 500 node IDs per call, and returns a count per outcome plus the nodes that did not link.
The link_figma_nodes_to_text_item tool has been removed. Use link_figma_nodes_to_text_items with a single entry in
links to link nodes to one text item.
Omitting branchId always targets linking nodes in the main Figma file. To link nodes in a branch, pass its ID explicitly in the top-level branchId field.
v5.12.0 released. Bumps @dittowords/text-extract to 0.4.1. The scan command now reports files.skipped_too_large in the extract summary. This count covers files larger than 1 MB, which are not scanned.
Adds a new endpoint: Update Project (PATCH /v2/projects/{projectId}) with support for changing the name or developerId of a project, as well as connecting to or disconnecting from a base (new feature coming soon!).
When a request doesn’t match an endpoint’s request schema, the 400 response now has a readable message that names each invalid field and why it’s invalid. The invalid fields are also listed in details.errors, each with its location in the request (body, query, or params), its path, and a message.Previously, these responses returned the raw output of our validation library as an array.Affected endpoints: all /v2 endpoints. Legacy endpoints are unchanged.
Adds two new optional parameters for JSON exports:
excludeVariantMetadata?: boolean. By default, all three JSON exports include the following fields at the bottom of each variant file: __variant-name and __variant-description. You can now set this query param to true to omit these two fields. Applies to the following formats: json_icu, json_i18next, json_vue_i18n. Ignored for base text (non-variant) exports or any other formats.
includeVariableSummary?: boolean. If true, will add a __variables_used field to the bottom of the exported file, which will contain an alphabetical list (array) of the names of all the variables that are present in the export. If omitted or set to false, this field will not be added to the file. Applies to the following formats: json_i18next, json_vue_i18n. Ignored for any other formats.
Text items and components with empty text are now included in every export format, instead of being left out. This applies to empty base text, empty variant text, and empty plural forms; the behavior change primarily affects empty variants. Items that don’t have the requested variant at all are still left out of that variant’s export.Because these keys used to be missing, most localization libraries fell back to either the base text or to the key itself. Now that they’re included with an empty value, your app will render them as empty.
This is a behavior change for plaintext exports that contain empty text. If a variant’s text is empty by mistake, your
app will now show it as empty instead of falling back to the base text. Fill in the variant’s text, or remove the
variant from that text item or component to continue rendering base text.
Format-specific details:
json_vue_i18n: An empty plural form is written as the literal {''}, and a plural form that contains only whitespace is written as a literal that keeps it, such as {' '}. vue-i18n can’t compile a plural message with an empty choice, so plural messages with an empty form previously caused an error when they were rendered.
json_icu and arb: Plural messages are now included when their first form is empty. Previously, the whole message was left out, even if its other forms had text. FormatJS (react-intl) treats an empty message as missing by default; set fallbackOnEmptyString: false to render it as empty.
android: Empty strings and plural forms are written as self-closing elements, such as <string name="welcome"/>. This also fixes malformed XML in exports that contained an empty plural form.
Consistent html and html_paragraphs rich text output
Standardizes the html rich text outputs across all four related endpoints. richText="html_paragraphs" wraps all text in <p> tags, while richText="html" does not wrap its content in outer tags, and uses <br /> for line breaks. All other html generation is identical between the two formats.Affected endpoints:
Prior to this change, the html parameter returned the unwrapped text from the Fetch endpoints, and the paragraph-wrapped text from the Export endpoints. Now, all four endpoints return the same output format for each richText option.
This is a behavior change for the Export endpoints. To continue receiving identical output, you must switch from
html to html_paragraphs.
The Create and Update endpoints are unaffected by this change. They still maintain a single html rich text option, which can convert either paragraph format into Ditto rich text.Example:For a text item with two paragraphs:
Welcome back!
Your order has shipped.
richText=html returns:
<strong>Welcome back!</strong><br />Your order has shipped.
richText=html_paragraphs returns:
<p><strong>Welcome back!</strong></p><p>Your order has shipped.</p>
Variant exports now use the variant’s own notes as each string’s description in arb, and as the comment above each string in ios-strings. If a variant has no notes, its base notes are used instead. Base exports are unchanged.Previously, both formats always used the base notes, even in variant exports.Affected endpoints:
Updates the CLI to support the new html_paragraphs rich text parameter.Prior to the API changes, the CLI used unwrapped html for the plain JSON export and the JSON export with i18next and vue-i18n frameworks. All other formats (including json_icu) returned the html_paragraphs style.The API changes mentioned above affect all CLI versions immediately. If you were using one of the other formats with rich text, and want to continue exporting with the legacy format, you will need to upgrade to this CLI version and change your config file from richText: html to richText: html_paragraphs.Additionally, this version includes the following bug fixes:
Generates plurals correctly for format: json, framework: vue-i18n, as returned from the Export endpoints.
Respects the integrated filter for components fetches. Previously, it was only applied to text items.
Add newDeveloperId to Update a style guide (PATCH /v2/styleguides) for renaming a style guide’s developer ID. It can be set alongside other field changes in the same request, and must be unique among the workspace’s style guides.
Add newDeveloperId to the update_styleguide tool for renaming a style guide’s developer ID. It can be combined with other field changes in the same call.
json_i18next Now returns the unsuffixed key alongside all plural keys. This brings it in line with what the CLI exports for json and json + i18next.
json_vue_i18n Resolves a minor bug in how plurals were generated if you had a zero and other form defined but not a one form. This format still drops two, few, and many forms, which are not supported by Vue without a custom rule definition. This change is not yet reflected in the CLI.
Add the translate_text_items tool for translating project text items into a variant’s locale, applying any style guide scoped to that locale.Add the translate_library_components tool for translating library components into a variant’s locale, applying any style guide scoped to that locale.
scan now requires a clean checkout of your repository’s default branch. Scanning from a tree with uncommitted changes, from a non-default branch, or from a detached HEAD stops with a message explaining what to change, before anything is uploaded.Scan records the commit and branch it read, and the code links Ditto builds point at them. A scan taken from anywhere else describes lines your default branch never had, so a later scan reports those links as changed or removed when nothing actually changed.The default branch comes from origin/HEAD, falling back to a local main or master. Because that reference is set when you clone and doesn’t update on its own, a mismatch is confirmed against your remote first, so a branch renamed after you cloned won’t block you. Scanning outside a Git repository is unaffected.
Add Publish component (POST /v2/components/publish) endpoint for publishing an existing text item to the component library.Add Link components (PATCH /v2/components/link) endpoint for linking text items to a library component by developer ID.Add Unlink components endpoint, which unlinks every text item that currently shares a given developer ID with its sibling instances. Accepts an optional projectId to scope the unlink to a single project.
Add the publish_library_component for publishing an existing text item to the component library.Add the link_text_items_to_component for linking text items to a library component by developer ID.Add the unlink_text_items_from_component tool, which unlinks every text item that currently shares a given developer ID with its sibling instances. Accepts an optional projectId to scope the unlink to a single project.
Add Link Figma nodes (POST /v2/textItems/linkFigmaNodes) endpoint for linking already-synced Figma text nodes to an existing text item, up to 50 node IDs per request.
Add the link_figma_nodes_to_text_item tool for linking already-synced Figma text nodes to an existing text item. Replaced by link_figma_nodes_to_text_items.Add figma to the search_ditto_textfields parameter, returning the Figma text node IDs linked to each text item.
Add ARB as an export format for Export text items (GET /v2/textItems/export) and Export components (GET /v2/components/export) — provide ?format=arb. See ARB JSON for the content shape.
Add framework: arb and framework: icu for json-format outputs, generating ARB and ICU JSON respectively. See Frameworks.Add androidLocales, which maps Ditto variant IDs to Android locale-qualified resource directories (values-<locale>/) — the Android counterpart to iosLocales. Unlike iosLocales, there’s no need to map base, since Android already has a default resource directory (values/) that the platform falls back to automatically.Add androidLocalesOutDir and iosLocalesOutDir, which let Android and iOS locale-organized output be written to separate root directories — useful since they typically need to live in different parts of a codebase.
scan now records which part of your repository it looked at, alongside the Git context added in 5.8.0. Scanning a repository root is recorded as covering the whole repository; scanning a single directory is recorded as covering only that directory.This lets Ditto tell the difference between a string removed from your code and a string that simply was not part of the scan, so re-scanning one directory implies nothing about the rest of the repository.
scan now records the Git repository, commit, and branch of the code it scans. Ditto uses these to recognize a codebase it has already seen, so a later scan of the same repository can be matched against an earlier one instead of importing every string again.This is read from your local Git checkout. Scan makes no additional network requests, does not send Git credentials, and records nothing about your remote beyond its host and path. Scanning outside a Git repository still works — the CLI notes that the scan can be imported but not re-synced, and continues.
Add richText parameter to Create components (POST /v2/components) and Patch components (PATCH /v2/components).When richText param is set to html, all text values in the update request — including plural and variant text — will be parsed as an HTML string and saved as rich text.
Improve how scan decodes the text it extracts. Escape sequences, XML entities, and inline markup are now handled per file format, so candidates arrive in Ditto as the text a user sees instead of as raw source.
Add the list_statuses tool, which lists the statuses text items and library components can be set to, in workflow order.The MCP server now supports logging in with your Ditto account via OAuth, in addition to a static API token. See Installation for setup instructions per client.
Add Delete components (DELETE /v2/components) endpoint for deleting library components by developer ID.Add Fetch statuses (GET /v2/statuses) endpoint for listing the statuses available in a workspace, in workflow order.
Add richText parameter to Update text items (PATCH /v2/textItems) and Create text items (POST /v2/textItems).When richText param is set to html, all text values in the update request — including plural and variant text — will be parsed as an HTML string and saved as rich text.For example, the following request would store formatted string “Inspiration for your next trip” as the Korean variant:
{ "richText": "html", "variantId": "korean", "updates": [ { "developerId": "homepage.section.inspiration", "text": "<strong>Inspiration</strong> for your next trip" } ]}
Supported formatting: <strong>/<b>, <em>/<i>, <u>, <s>, and <br> for line breaks.
<sup> and <sub> are only supported for workspaces with superscript and subscript enabled.
We drop unsupported markup such as links, lists, or headings but keep its text.
{{variable_name}} placeholders still resolve, and keep any formatting applied around them.
Without the parameter, text is saved as plaintext and any markup is stored literally, unchanged from previous behavior.
Renaming a variable with newName rewrites every {{variable_name}} placeholder referencing it — across text items, library components, variants, and plurals — so existing text keeps resolving.
A variable can’t be deleted while any text item or library component still references it.
Add the login and logout commands. login signs you in through your browser, so the CLI no longer needs an API key.
npx @dittowords/cli login
The session is saved to $HOME/.config/ditto and renews itself as you keep using the CLI. Commands act as you — your Ditto account and its permissions — instead of as whoever generated an API key.
logout forgets the session on this machine and revokes it with Ditto.
API keys still work. DITTO_TOKEN takes precedence over a saved session, so CI and other headless environments are unaffected. See credential precedence.
Add the suggest_edit tool, which checks text against your workspace’s style guide rules and returns suggested edits — the same rule-based suggestions shown in the Ditto app. Check an existing text item by developer ID, or freeform text that isn’t saved as a text item yet.
Improve how scan handles codebases that are larger than a workspace’s plan’s scan limit.Add the --list-directories flag. scan <path> --list-directories prints the number of candidate strings found in each directory and exits without uploading anything, so you can choose a scope before running a real scan.
npx @dittowords/cli scan . --list-directories
Counts are rolled up: each directory includes the strings found in its subdirectories.
Directories are printed in tree order, indented by depth, with the whole scan total at the top.
When a scan exceeds your plan’s limit, the error now suggests narrower paths to scan instead of just reporting the limit.
The message lists the largest subdirectories that each fit within your remaining limit, with their string counts and a ready-to-run command for each.
The limit is checked before candidates are uploaded, so an oversized scan fails right away instead of after the upload finishes.
Document the agent setup package as the default way to integrate Ditto with Claude Code. See Agent setup package.Standardize the API token environment variable to DITTO_TOKEN across the CLI, Ditto Specs, and MCP setup docs (previously DITTO_API_KEY and DITTO_API_TOKEN).
Add list_variants and list_variables tools, and expose variants and variables on the text item and library component tools — reference a variable with a {{variable_name}} placeholder, or set variant-specific text via a variant’s developer ID.
Add Fetch activity (GET /v2/activity) endpoint for retrieving a paginated list of change events in your workspace, optionally filtered by project, text item, library component, or entity type.
id (default) sorts the response alphabetically by developer ID (matching previous behavior)
project_order groups items by project, returned alphabetically by project developer ID, then sorts within projects based on the custom sort order set up in the web app.
Add the scan command. scan <path> analyzes a local directory for user-facing text and sends the candidates to Ditto, where you can review them and turn them into a content system tailored to your product. See the Scan documentation.
This release includes packages that require Node.js 20 or higher.
Add assignee, along with new variant fields variants[n].status, variants[n].assignee, variants[n].notes, and variants[n].characterLimit to the Create components resource.
assignee must be a valid email matching a user in your workspace
variant status must be a valid status in your workspace
Each text item and component in the response now includes a characterLimit field: a positive integer when a limit is set, or null when no limit is configured.
For variant responses, characterLimit reflects the variant’s own character limit rather than the base value.
Update Text Item and Component endpoints to support variant assignee, notes and character limit.
Fetch text items (GET /v2/textItems) and Fetch components (GET /v2/components) now return variant assignee and notes in variant response objects, not the base properties.
Requests that include an assignee filter and a variantId return only items whose base and variant assignees both match the filter. This applies to Fetch text items (GET /v2/textItems), Export text items (GET /v2/textItems/export), Fetch components (GET /v2/components), and Export components (GET /v2/components/export).
Requests that include assignee, notes and/or character limit along with a variantId in the payload of Update text items (PATCH /v2/textItems) or Update components (PATCH /v2/components) will update that variant’s properties, not the base values.
Add component name to the response of Fetch components (GET /v2/components) endpoint. Each component in the response will now include a name field matching the component name. The same component name will be returned across base text, variants and plural forms.
Add Update components (PATCH /v2/components) endpoint.
Supports updating text, tags, status, and assignee on components identified by developer ID. Includes optional variant targeting with variantId and forceVariantCreation parameters.Add PATCH /v2/textItems as the preferred method for updating text items. PUT /v2/textItems continues to work but is now deprecated.
Add CLI support for filtering by tags. Add a tags configuration to your config file to scope text items and components by one or more tags, with support for AND/OR operators.
tags: values: - "tag-1" - "tag-2" operator: "AND"
The tags filter can be specified at the top level of your config or within individual outputs (output-level overrides top-level). When operator is "AND", only items with all specified tags are returned. When operator is "OR" (or omitted), items with any of the specified tags are returned.See full release notes here.
Add the get_workspace_tags tool, which lists the tags currently in use across the workspace — useful before adding tags to a style guide rule, since only existing tags are allowed. Add the first tools for creating, updating, and deleting style guide rules from your editor.
Add assignee and tags filters to Fetch components (GET /v2/components),
Export components (GET /v2/components/export),
and Export text items (GET /v2/textItems/export).
The assignee filter accepts an email address or null to match unassigned items. The tags filter accepts an array of tag values with an optional operator field (AND or OR, defaulting to OR).
Add CLI support for filtering by integration status. Add integrated: true to your config file to fetch only text items and components that have been marked as integrated into development.See full release notes here.
The Ditto MCP server can now run remotely over Streamable HTTP, instead of only as a local stdio server. See Installation for how to connect Claude Code, Cursor, VS Code, Windsurf, Codex, and other MCP clients.
Add plurals field to Update text items (PUT /v2/textItems) API endpoint.
The plurals field supports upsert and remove operations for managing plural forms (zero, one, two, few, many, other) on text items.
Existing plural forms not mentioned in either operation are preserved. Supports variant plurals via the variantId parameter.
Add assignee and tags filters to Fetch text items (GET /v2/textItems).
The assignee filter accepts an email address or null to match unassigned text items. The tags filter accepts an array of tag values with an optional operator field (AND or OR, defaulting to OR).Fetch text items (GET /v2/textItems)
and Fetch components (GET /v2/components)
now include the assignee field in the response payload, returned as the assignee’s email address or null if unassigned.
Add assignee field to Update text items (PUT /v2/textItems) API endpoint.
The assignee field accepts an optional email string of a user in the workspace to assign to the text item. Setting assignee to null will remove the current assignee.
Add the search_ditto_text tool, which searches your workspace for existing text items and library components by content — so agents can find and reuse strings instead of generating new ones.
Ditto’s MCP server is here! It connects AI coding agents to your team’s content in Ditto, starting with the get_styleguide_rules tool for fetching workspace and project-level style guide rules. See the MCP overview to get started.
Fetch text items (GET /v2/textItems),
Fetch components (GET /v2/components),
Export text items (GET /v2/textItems/export),
and Export components (GET /v2/components/export)
now return a 400 error response when statuses that don’t exist in your workspace are provided in the status filter.
Fetch text items (GET /v2/textItems)
and Fetch components (GET /v2/components)
now return separate records for each plural form. Plural forms follow the standard i18n plural forms outlined here.
Each record in the response includes a pluralForm value, and for each pluralForm on a text item or component, a separate record is returned with
that pluralForm and its respective value. If a record has a pluralForm, it will be appended to the end of the developer ID.Example response:
Default JSON file formats now include plurals, where the standard
unicode plural rule (zero, one, two, few, many, other) is appended to the end of the developer ID key.Example output:
Add Export text items (GET /v2/textItems/export)
and Export components (GET /v2/components/export)
endpoints for fetching text items and components in .json ICU, .json i18next, .json Vue i18n, .strings, .stringsdict, or .xml formats.
Add CLI support for Android .xml, iOS .strings and .stringsdict, and ICU .json formats. In conjunction with iOS format additions,
add iOS Locale directory generation for configured variant -> locale mappings in config. If iOS locales are configured, CLI will also auto-generate
a Ditto.swift file for reading locale values.See full release notes here.
Relax requirement in Update text items (PUT /v2/textItems) API endpoint that requires text to be included in the request.
Add tags field which is an optional string[] that if set in the request will replace the existing tags with the specified tags on the textItem.
Clarified expected behavior with variant and status filtering for Fetch text items (GET /v2/textItems) API endpoint.
Variants that match the variant filter should only be returned if they match the status filter and their base text also matches the status filter.Added query param in Fetch components (GET /v2/components) API endpoint status filter that allows for filtering components by status.
Variants that match the variant filter should only be returned if they match the status filter and their base text also matches the status filter.
Added Fetch text items (GET /v2/textItems) API endpoint status filter that allows for fetching textItems by status.Relax requirement in Update text items (PUT /v2/textItems) API endpoints that requires all textItems to be in the same project.
Now updates can include textItems that span multiple projects and all will be updated.
Updates the Github Action to work with CLI v5.x, compatible with both new and legacy Ditto. After upgrading, the Github Action will fetch from new Ditto projects/components by default.Legacy users will need to add pull-from-legacy: "true" to their workflow file to continue fetching legacy text.If you wish to use this action for both new and legacy Ditto, simply create separate steps with different inputs. See the README for more details and examples.Release notes:
A small update to support the -m and --meta flags in commands. This is used internally for analytics and should not affect customer workflows.See full release notes here.
First official stable release that provides support for fetching project text and components from the new Ditto experience, including all features from the v5 Beta release (through 5.0.0-beta.8).This version maintains full support for fetching from legacy projects and components. Simply include the --legacy flag along with any command from v4.x. Users with both new and legacy projects may pull data from both places into the same codebase by maintaining two separate config files and output directories, and including the path to the right config file in your pull command.See full release notes here.
Added support for fetching components in addition to project text via the CLI. Include components in your config file to fetch components from the specified folders. Include projects in your config file to fetch text from the specified projects.Breaking change: If projects or components are omitted from the config file, will not fetch text from that area. Previously, if projects was omitted, it would fetch text from all projects.See full release notes here.
Added support for fetching and outputting rich text (HTML) content for Ditto text, by adding richText: html to the config file.At this time, this version is still in Beta, accessible via @dittowords/cli@beta.See full release notes here.
Beta release of CLI for Ditto 2.0. This version supports fetching text from new, non-legacy Ditto projects. It requires a new format for the config file and supports returning json files formatted for i18next. This version is still in beta, and can be accessed via @dittowords/cli@beta. Supports all legacy features via --legacy flag.Release notes:
The fetch component text (GET /v1/components) API endpoint now supports the includeTimeData query parameter.When includeTimeData is set to true, the response will include the createdAt and updatedAt fields for each component. This feature is only available when the structured format is used.
Pluralization is now supported for all JSON formats when importing components via the Ditto web app or the Fetch component text API endpoint.Example import data:
{ "fruit": "You have fruit in your cart.", "fruit_one": "You have one fruit in your cart.", "fruit_other": "You have some fruit in your cart."}
v4.5.0 released to add support for a new option which disables the generation of index.js and index.d.ts files when working with JSON formats.See the release notes here.
The /components/fileendpoint
now supports a folderId query parameter. You can supply the Developer ID of one of
your component folders, and all the components will be imported to that folder.
Ditto text items with rich text can now be rendered natively by passing the richText property on either Ditto or DittoText.This expands rich text support from v1.5.0 which introduced support for rich text on components.Example:
This release includes features designed to tighten integration for a variety of environments, including iOS, TypeScript, and more.See the release notes here.
We’ve released new versions of our example applications, which have been updated to include the latest in recommended practices for integrating Ditto into development.See the full list here.
The behavior of variables when exporting to mobile formats (.strings, .stringsdict, and .xml) has changed.Variables will now maintain a consistent ordering across base text, variant text, and plural forms; they’re assigned an index according to the order of usage (starting with base text, and then variants), and that index is maintained through variant exports.For example, consider the following text:
// Base Text{{username}}, your role is {{role}}.// Variant TextTú papel es {{role}}, {{username}}.Previously, exports for the base text and variant text would cause format specifier indices to be reversed for the variables:/* base-example.strings */"text" = "%1$@, your role is %2$@.";/* spanish-example.strings */"text" = "Tú papel es %1$@, %2$@.";To facilitate ease of integration into development, exports for variant text will now ensure that the format specifier indices match those in the base text:/* base-example.strings */"text" = "%1$@, your role is %2$@.";/* spanish-example.strings */"text" = "Tú papel es %2$@, %1$@.";
Added the import-components command which enables component imports via a file through the CLI. For information about the command please refer to the documentation in the README.
We clarified a small point of confusion with the documentation around the request payload expected for the endpoint.The JSON payload should include a top-level data property:
{ "data": { "[API ID]": { "text": "[TEXT OF TEXT ITEM (CAN INCLUDE VARIABLES)]", "notes": "[NOTES OF TEXT ITEM]", // optional "tags": [ ... ], // optional: array of strings "plurals": [ // optional: array of plural objects { "text": "[TEXT OF PLURAL FORM]", "form": "[one|two|zero|few|many|other]" } ] } }}
We’ve added a __type property to variable output in our structured export format; this enables simple discrimination between different types of variables:
We’ve published v3.0.0 of the CLI, which focuses around a number breaking changes intended to better align default CLI behavior with Ditto best practices.Read the release notes here.
We’ve released a new version of our API that includes some breaking changes. The old API endpoints are deprecated, and existing users should migrate to the new endpoints at their earliest convenience.
Added the status filter as a configuration variable. To filter the fetched text by its status, you can now use the status parameter in your config.yml.
Added information to the README about two supported environment variables:
DITTO_CONFIG_FILE: used to specify an alternate file location for the CLI to read authentication information from. The default path is $HOME/.config/ditto.
DITTO_TEXT_DIR: used to specify an alternate folder location for the CLI to write its output files to. The default path is ./ditto.
Added new endpoint: Fetch components by component folder
Added sub-headings to divide the endpoints by the entity they’re associated with, and implemented minor miscellaneous cleanup across the endpoint documentation
Text items with plural values will have those plural values included in flat exports as individual key/value pairs; pluralized keys are structured like [TEXT ID]_[PLURAL FORM]. See the flat format documentation for more details.
Fixed a bug where the status field failed to properly filter returned data when specified in conjunction with the android or ios-strings formats.
We exported two hooks that can be used for accessing synced data: useDittoSingleText and useDittoComponent. These hooks are experimental and will likely undergo API changes in the future.
Added support for including variables in payloads sent to the PUT /components endpoint.
Fixed an issue with Android & iOS export formats not escaping special characters: \n, \t, @, ?, ', and " characters are now properly escaped.
Added missing xliff namespace to exported Android .xml files.
= Fixed a bug with Android .xml exports that occurred with text items with API IDs that include the - character. Now, all - characters are replaced with \_ characters in the name property of <string> and <plural> tags, and a ditto_api_id property has been added to string and plural tags to serve as a reference to the original API ID.
Fixed a bug when using the project add / project remove commands and selecting the component library caused incorrect modifications to be made to the CLI’s configuration file.
Added early support for exporting text data to Android and iOS Strings formats. All endpoints that support a format query parameter can now accept values of android or ios-strings.
Added GET /variables endpoint that returns the variables in the workspace of the requesting user.
Added the ability to filter by text item status by passing a status query parameter in API requests. Supported by the following endpoints:
Update some user-facing CLI messages to accurately reflect our new subdomain: app.dittowords.com (instead of the old beta.dittowords.com). See the release here.
Our React SDK now supports variable interpolation by passing in values through the variables prop.
Our React SDK now supports displaying plural forms through the count prop.
For more information about using variable interpolations and pluralization through our React SDK, check out our SDK documentation.
We’ve added a new supported property to ditto/config.yml to allow explicitly specifying that the component library should be fetched and included in the CLI’s output:
components: trueThis is now the preferred alternative to the old way of specifying the component library:
Our goal with this change is to make the CLI easier to use and understand by aligning it with the way things work in the Ditto web app, where the component library is fundamentally different from the projects in a workspace.See the release here.
GET /components can now be used to fetch the components in a workspace
Supports format and variant parameters (the same as the /projects and /project/:id endpoints)
GET /projects/ditto_component_library has been deprecated; the endpoint is still available, but references to it have been removed from the documentation.
PUT /components can now be used to update the text of components in a workspace
Currently only supports updating variant text via the variant query parameter (an error will be thrown if not specified)
Currently only available to teams on Team or Enterprise plans
Output files are now written to disk in several different ways according to how the CLI is configured; most notably, if the variants option is set and a format of structured or flat is specified, output files will be written on a per-project per-variant basis
Data for structured and flat formats is saved without arbitrary top-level nesting
Files are only written for variants that contain values for the configured projects (no more empty files)
For a more in-depth description (with examples) of these changes and others in the release, see the full release notes here.
ditto-react now only works with CLI version 2.x.x — leaning into new CLI improvements allowed us to drastically reduce many areas of complex logical overhead
We made some stabilization improvements to the way that missing/invalid frameId, blockId, textId, or componentId values are handled
We implemented significant refactoring in several areas of the project
For a more in-depth description of these changes, see the full release notes here
We fixed a bug with the API (and in-app exports) that included hidden text in flat and structured JSON exports. Now, hidden text will correctly not be included in these export formats!
When the pull command is executed, all .json and .js files are now removed from the ditto folder prior to new data being written
= Support added for new options in ditto/config.yml:
variants: true or false
If set to true, data will be fetched for both base and variant text and stored in separate JSON files
format: flat or structured - If specified, data will be fetched and stored in the specified format
= Refactored README
GET /variants will now return names and API IDs for variants in the workspace associated with the requesting user.
GET /projects and GET /projects/:id now accept an optional query parameter of variant; when provided, the data exported will be specific to the variant with an API ID that matches the parameter’s value. For default and structured formats, the variants key will not be included when the variant parameter is provided.
GET /projects and GET /projects/:id now accepts an optional query parameter of format, which can be either flat or structured. If no format is provided, the full JSON of the project will be returned with blocks and frames.Example: /projects/<PROJECT_ID>?format=flat
GET /projects/:id will now return component variants. This applies both for when fetching projects or when fetching the component library (i.e. id = ditto_component_library)
GET /projects/:id will now match the project JSON export from the web-app to include component information (is_comp and component_api_id) in the text object
We’ve updated both our CLI and API to handle multiple projects.Heads up! This results in some breaking changes to the CLI in order for it to list projects, and will change the format of the text.json fetched by the CLI. Please upgrade your Ditto CLI via either npm or yarn.
GET /project-names is the new name of the previous GET /projects endpoint. Just as before, this will return the names and IDs of projects in your Ditto workspace with Developer Mode turned on
GET /projects/:id will now return the structured JSON in a format compatible with multiple projects
GET /projects is a new endpoint that will return the content of multiple projects (specified via the query parameter projectIds) as a single JSON object
We’ve updated the CLI to handle syncing multiple projects in a single directory! This means several things:
/ditto/config.yml now supports multiple projects. ditto-cli pull will pull all projects in the current directory’s /ditto/config.yml
We’ve added two new commands to add and remove projects from /ditto/config.yml
ditto-cli project add
ditto-cli project remove
The regular ditto-cli project command will now function as ditto-cli project add
GET /projects endpoint for fetching Ditto projects from workspace
GET /projects/:id endpoint for fetching content in Ditto project as structured JSON
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Ditto","description":"Developer documentation for Ditto, the source of truth for product text. Scan a codebase to import its strings, then connect coding agents through the Ditto MCP server, link Figma files, and pull localized string files with the CLI.","colors":{"primary":"#E2B103","light":"#F0D164","dark":"#1D1700"},"logo":{"light":"https://mintcdn.com/ditto/A9jN5zv6WG_Dk9hK/logo/ditto_logo.svg?fit=max\u0026auto=format\u0026n=A9jN5zv6WG_Dk9hK\u0026q=85\u0026s=4e38ddaa8955775a191cbe1616e02312","dark":"https://mintcdn.com/ditto/A9jN5zv6WG_Dk9hK/logo/ditto_logo.svg?fit=max\u0026auto=format\u0026n=A9jN5zv6WG_Dk9hK\u0026q=85\u0026s=4e38ddaa8955775a191cbe1616e02312"},"favicon":"https://mintcdn.com/ditto/WgRtoF9rLXWv6hNh/favicon.jpeg?fit=max\u0026auto=format\u0026n=WgRtoF9rLXWv6hNh\u0026q=85\u0026s=011fcbfc2411f0c04ab811e7b701750c","background":{"color":{"dark":"#11141B"}},"navbar":{"links":[{"href":"mailto:support@dittowords.com","label":"Support"}],"primary":{"type":"button","label":"Open App","href":"https://app.dittowords.com"}},"footer":{"socials":{"twitter":"https://twitter.com/dittowords","github":"https://github.com/dittowords","linkedin":"https://www.linkedin.com/company/ditto-app"}},"seo":{"organization":{"id":"https://www.dittowords.com/#organization","name":"Ditto","url":"https://www.dittowords.com","logo":"https://developer.dittowords.com/logo/ditto_logo.svg","sameAs":["https://twitter.com/dittowords","https://github.com/dittowords","https://www.linkedin.com/company/ditto-app"]},"indexing":"navigable"},"contextual":{"options":["copy","view","claude","chatgpt","mcp","cursor","vscode"],"display":"header"},"markdown":{"instructions":["These are Ditto's developer docs. Ditto is a single source of truth for product copy across design, review, localization, and code.","The first step on any codebase is a scan: https://developer.dittowords.com/get-started/scan-your-repo.md. That page also covers reviewing the style guide Ditto drafts from the scan. After it, the follow-on guides are Connect Figma files and Set up localization (under /guides/) and Connect the Ditto MCP (the Setup page of the MCP reference).","Two different MCP servers: the Ditto MCP server at https://api.dittowords.com/v2/mcp gives an agent a workspace's text and style guide rules; the documentation MCP server at https://developer.dittowords.com/mcp searches these docs.","Prefer logging in with a Ditto account (npx -y @dittowords/cli@latest login; OAuth in MCP clients) over API keys. API keys are for CI and headless clients only.","Commands are complete as written and use npx -y @dittowords/cli@latest; nothing needs a global install."]},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"Help Guides","icon":"book-open-cover","href":"https://help.dittowords.com/en/"},{"anchor":"What's New","icon":"newspaper","href":"https://www.dittowords.com/whats-new"},{"anchor":"Figma Plugin","icon":"figma","href":"https://www.figma.com/community/plugin/798826066406007173/ditto-manage-copy-from-design-to-production"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"ditto","hasAudioNarration":false,"actualSubdomain":"ditto","customDomains":["developer.dittowords.com"],"gitSource":{"type":"github","owner":"dittowords","repo":"ditto-app","deployBranch":"master","contentDirectory":"docs-public","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae4b3adf49f5b7aedfe29b7","collectionId":"b679a977-0d82-462d-aed1-9ee4962c5f7c","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae4b3adf49f5b7aedfe29b7"},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"REMOVE_BRANDING":{"status":"DISABLED"},"CONTEXTUAL_FEEDBACK":{"status":"DISABLED"},"CODE_SNIPPET_FEEDBACK":{"status":"DISABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6ae4b3adf49f5b7aedfe29b7","clientVersion":"0.0.4043","searchFilterCounts":[{"language":"default","tag":"Documentation","count":97},{"language":"default","tag":"API Reference","count":68},{"language":"default","tag":"Endpoints","count":66},{"language":"default","tag":"Legacy","count":18},{"language":"default","tag":"Components","count":16},{"language":"default","tag":"Projects","count":8},{"language":"default","tag":"Text Items","count":8},{"language":"default","tag":"CLI Reference","count":7},{"language":"default","tag":"Component Folders","count":6},{"language":"default","tag":"Style guides","count":6}]},"assistantConfig":{},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"feedback-support/changelog","slug":"/feedback-support/changelog","pageMetadata":{"title":"Developer changelog","sidebarTitle":"Changelog","description":"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.","href":"/feedback-support/changelog"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,blockquote:`blockquote`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`october-30-2026`,children:`October 30, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api`,children:`API`}),`\n`,_jsx(_components.p,{children:`Several updates to the API have been made to support working with Bases. This is a brand new feature that is still in development. Attempting to use any of these endpoints while the feature is in development will throw an error. A release announcement will be published here when the feature is available to all users.`}),`\n`,_jsx(_components.p,{children:`Brand new endpoints related to working with Bases:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/bases/get-bases`,children:`Fetch bases`}),` (`,_jsx(_components.code,{children:`GET /v2/bases`}),`) — lists all the bases in your workspace, including each base’s GitHub connection.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/bases/get-base`,children:`Fetch a base`}),` (`,_jsx(_components.code,{children:`GET /v2/bases/{baseId}`}),`) — returns a single base, with its text item count, its folders and the projects connected to it.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/bases/create-bases`,children:`Create bases`}),` (`,_jsx(_components.code,{children:`POST /v2/bases`}),`) — creates one or more bases. Supports linking new bases to a GitHub repository, which also kicks off an initial scan.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/bases/patch-bases`,children:`Update a base`}),` (`,_jsx(_components.code,{children:`PATCH /v2/bases/{baseId}`}),`) — edit an individual base. Currently supports name, developer ID and connecting to a GitHub repository.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/create-text-items-from-base`,children:`Create text items from a base`}),` (`,_jsx(_components.code,{children:`POST /v2/textItems/fromBase`}),`) — copies text items from a base into a project connected to that base, optionally placing them in a new or existing block.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/projects/publish-project`,children:`Publish to base`}),` (`,_jsx(_components.code,{children:`POST /v2/projects/{projectId}/publish`}),`) — publishes a project’s Modified and New text items to its base, either all of them or the ones you name. Text items in Conflict are only acted on when you choose which version to keep.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/projects/update-text-items-from-base`,children:`Update text items from base`}),` (`,_jsx(_components.code,{children:`POST /v2/projects/{projectId}/updateFromBase`}),`) — updates Outdated or Conflict text items in a project to their base’s version.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`The following existing endpoints now include support for Bases:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) - Optional `,_jsx(_components.code,{children:`bases`}),` filter to retrieve Base Text Items. Project Text Items now include nullable `,_jsx(_components.code,{children:`baseId`}),` and `,_jsx(_components.code,{children:`baseTextItemId`}),` fields.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`) - Optional `,_jsx(_components.code,{children:`bases`}),` filter to retrieve Base Text Items. If the same text item appears in a fetched project and base, the project’s value overrides the base’s.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`) - Takes an optional `,_jsx(_components.code,{children:`projectId`}),` parameter on each text item to update, to disambiguate between the same base text item appearing in multiple projects.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/delete-text-items`,children:`Delete text items`}),` (`,_jsx(_components.code,{children:`DELETE /v2/textItems`}),`) - Takes an optional `,_jsx(_components.code,{children:`projectId`}),` parameter to disambiguate between text items that are connected to the same library component or base text item.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/projects/get-projects`,children:`Fetch projects`}),` (`,_jsx(_components.code,{children:`GET /v2/projects`}),`) - Added `,_jsx(_components.code,{children:`baseId`}),` to each project in the response.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/projects/create-projects`,children:`Create project`}),` (`,_jsx(_components.code,{children:`POST /v2/projects`}),`) - Added optional `,_jsx(_components.code,{children:`baseId`}),` field to support creating a project from a base.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-29-2026`,children:`October 29, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-1-6-4`,children:`Ditto React — 1.6.4`}),`\n`,_jsxs(_components.p,{children:[`Maintenance release to resolve security vulnerabilities in DOMPurify. `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.6.4`,children:`Release Notes`}),`. Legacy customers using the React SDK should upgrade to the latest version. If you cannot upgrade `,_jsx(_components.code,{children:`ditto-react`}),`, you may also pin the DOMPurify version to `,_jsx(_components.code,{children:`^3.4.17`}),` to resolve the security vulnerabilities without upgrading the Ditto SDK directly.`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-21-2026`,children:`October 21, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-2`,children:`API`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/delete-text-items`,children:`Delete Text Items`}),` (`,_jsx(_components.code,{children:`DELETE /v2/textItems`}),`) now optionally accepts a `,_jsx(_components.code,{children:`projectId`}),` to disambiguate Developer IDs that match multiple project text items. A Developer ID could match multiple project text items if it is the ID of a library component or base text item. Provide a `,_jsx(_components.code,{children:`projectId`}),` to specify which individual text item to delete, while leaving all other instances unchanged. The `,_jsx(_components.code,{children:`projectId`}),` should sufficiently disambiguate as long as there are not multiple instances of the same library component in that project. In that case, you must delete the target instance(s) through Ditto app. Prior to this change, deletion of library component instances was not supported at all through this endpoint.`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/mcp-reference/tools#delete_text_items`,children:_jsx(_components.code,{children:`delete_text_items`})}),` now optionally accepts a `,_jsx(_components.code,{children:`projectId`}),` to disambiguate Developer Ids that match multiple project text items. Follows the same patterns as the API endpoint.`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-20-2026`,children:`October 20, 2026`}),`\n`,_jsx(Heading,{level:`4`,id:`library-component-versioning`,children:`Library component versioning`}),`\n`,_jsxs(_components.p,{children:[`For workspaces that have opted into library component versioning, adds endpoints for saving component changes without publishing them, publishing or discarding those changes, and bringing instances up to date. In workspaces that haven’t opted in, these endpoints return a `,_jsx(_components.code,{children:`404`}),`.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-unpublished-component-changes`,children:`Fetch unpublished component changes`}),` (`,_jsx(_components.code,{children:`GET /v2/components/staged`}),`): returns the components that have unpublished changes, with those changes applied. Takes the same `,_jsx(_components.code,{children:`filter`}),` and `,_jsx(_components.code,{children:`richText`}),` parameters as Fetch components.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/save-unpublished-component-changes`,children:`Save unpublished component changes`}),` (`,_jsx(_components.code,{children:`PATCH /v2/components/staged`}),`): saves changes to `,_jsx(_components.code,{children:`text`}),`, `,_jsx(_components.code,{children:`plurals`}),`, `,_jsx(_components.code,{children:`tags`}),`, `,_jsx(_components.code,{children:`notes`}),`, or `,_jsx(_components.code,{children:`characterLimit`}),` without making them available to instances.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/publish-component-changes`,children:`Publish component changes`}),` (`,_jsx(_components.code,{children:`POST /v2/components/staged/publish`}),`): publishes the unpublished changes, allowing component instances to adopt those changes.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/discard-unpublished-component-changes`,children:`Discard unpublished component changes`}),` (`,_jsx(_components.code,{children:`DELETE /v2/components/staged`}),`): discards the unpublished changes, leaving the published component and its instances unchanged.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/upgrade-component-instances`,children:`Upgrade component instances`}),` (`,_jsx(_components.code,{children:`PATCH /v2/components/upgrade`}),`): brings text items that are instances of a component up to date with its latest published version. Instances with local edits return a `,_jsx(_components.code,{children:`409`}),` unless `,_jsx(_components.code,{children:`discardLocalEdits`}),` is set.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`In these workspaces, existing endpoints also include versioning details:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`): each component includes `,_jsx(_components.code,{children:`hasUnpublishedChanges`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/patch-components`,children:`Update components`}),` (`,_jsx(_components.code,{children:`PATCH /v2/components`}),`): can’t update `,_jsx(_components.code,{children:`text`}),`, `,_jsx(_components.code,{children:`plurals`}),`, `,_jsx(_components.code,{children:`tags`}),`, `,_jsx(_components.code,{children:`notes`}),`, or `,_jsx(_components.code,{children:`characterLimit`}),` on a component with unpublished changes, since publishing those changes would overwrite the updates.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`): each text item includes `,_jsx(_components.code,{children:`component`}),`, with the component’s `,_jsx(_components.code,{children:`id`}),` and the instance’s `,_jsx(_components.code,{children:`state`}),`: `,_jsx(_components.code,{children:`current`}),`, `,_jsx(_components.code,{children:`outdated`}),`, `,_jsx(_components.code,{children:`modified`}),`, or `,_jsx(_components.code,{children:`conflict`}),`. It’s `,_jsx(_components.code,{children:`null`}),` for text items that aren’t instances.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-19-2026`,children:`October 19, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-3`,children:`API`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/link-figma-nodes`,children:`Link Figma nodes`}),` (`,_jsx(_components.code,{children:`POST /v2/textItems/linkFigmaNodes`}),`) now supports linking Figma text nodes to many text items in one request. Request body now takes `,_jsx(_components.code,{children:`links`}),`, a mapping of text item developer IDs to Figma node IDs. Up to 500 distinct node IDs are allowed per request across all links. Reports whether linking was successful for each node in request.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`The previous request body (`,_jsx(_components.code,{children:`textItemId`}),` with `,_jsx(_components.code,{children:`figma.nodeIds`}),`) is no longer accepted. Send one `,_jsx(_components.code,{children:`links`}),` entry to link\nnodes to a single text item.`]})}),`\n`,_jsxs(_components.p,{children:[`Omitting `,_jsx(_components.code,{children:`branchId`}),` always targets linking nodes in the main Figma file. To link nodes in a branch, pass its ID explicitly in the top-level `,_jsx(_components.code,{children:`branchId`}),` field.`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-2`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#update_project`,children:_jsx(_components.code,{children:`update_project`})}),` tool, which supports updating an individual project’s name, Developer ID, and/or connected base. More details on bases and connecting projects to bases coming soon!`]}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#link_figma_nodes_to_text_items`,children:_jsx(_components.code,{children:`link_figma_nodes_to_text_items`})}),` tool for linking Figma text nodes to many text items in one call. It takes a mapping of text item developer IDs to Figma node IDs, up to 500 node IDs per call, and returns a count per outcome plus the nodes that did not link.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`link_figma_nodes_to_text_item`}),` tool has been removed. Use `,_jsx(_components.code,{children:`link_figma_nodes_to_text_items`}),` with a single entry in\n`,_jsx(_components.code,{children:`links`}),` to link nodes to one text item.`]})}),`\n`,_jsxs(_components.p,{children:[`Omitting `,_jsx(_components.code,{children:`branchId`}),` always targets linking nodes in the main Figma file. To link nodes in a branch, pass its ID explicitly in the top-level `,_jsx(_components.code,{children:`branchId`}),` field.`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-12-0`,children:`Ditto CLI - 5.12.0`}),`\n`,_jsxs(_components.p,{children:[`v5.12.0 released. Bumps `,_jsx(_components.code,{children:`@dittowords/text-extract`}),` to 0.4.1. The `,_jsx(_components.code,{children:`scan`}),` command now reports `,_jsx(_components.code,{children:`files.skipped_too_large`}),` in the extract summary. This count covers files larger than 1 MB, which are not scanned.`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-16-2026`,children:`October 16, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-4`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Adds a new endpoint: `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/projects/patch-projects`,children:`Update Project`}),` (`,_jsx(_components.code,{children:`PATCH /v2/projects/{projectId}`}),`) with support for changing the `,_jsx(_components.code,{children:`name`}),` or `,_jsx(_components.code,{children:`developerId`}),` of a project, as well as connecting to or disconnecting from a `,_jsx(_components.code,{children:`base`}),` (new feature coming soon!).`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-15-2026`,children:`October 15, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-5`,children:`API`}),`\n`,_jsx(Heading,{level:`4`,id:`filter-text-items-by-component`,children:`Filter text items by component`}),`\n`,_jsxs(_components.p,{children:[`Adds a `,_jsx(_components.code,{children:`components`}),` filter to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) that returns only the text items that are instances of the given library components.`]}),`\n`,_jsx(Heading,{level:`4`,id:`readable-validation-errors`,children:`Readable validation errors`}),`\n`,_jsxs(_components.p,{children:[`When a request doesn’t match an endpoint’s request schema, the `,_jsx(_components.code,{children:`400`}),` response now has a readable `,_jsx(_components.code,{children:`message`}),` that names each invalid field and why it’s invalid. The invalid fields are also listed in `,_jsx(_components.code,{children:`details.errors`}),`, each with its `,_jsx(_components.code,{children:`location`}),` in the request (`,_jsx(_components.code,{children:`body`}),`, `,_jsx(_components.code,{children:`query`}),`, or `,_jsx(_components.code,{children:`params`}),`), its `,_jsx(_components.code,{children:`path`}),`, and a `,_jsx(_components.code,{children:`message`}),`.`]}),`\n`,_jsx(_components.p,{children:`Previously, these responses returned the raw output of our validation library as an array.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Affected endpoints:`}),` all `,_jsx(_components.code,{children:`/v2`}),` endpoints. Legacy endpoints are unchanged.`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-12-2026`,children:`October 12, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-6`,children:`API`}),`\n`,_jsx(_components.p,{children:`Released several bugfixes and standardization measures across the Text Item and Component fetch and export endpoints.`}),`\n`,_jsx(Heading,{level:`4`,id:`new-json-metadata-parameters`,children:`New JSON metadata parameters`}),`\n`,_jsx(_components.p,{children:`Adds two new optional parameters for JSON exports:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`excludeVariantMetadata?: boolean`}),`. By default, all three JSON exports include the following fields at the bottom of each variant file: `,_jsx(_components.code,{children:`__variant-name`}),` and `,_jsx(_components.code,{children:`__variant-description`}),`. You can now set this query param to `,_jsx(_components.code,{children:`true`}),` to omit these two fields. Applies to the following formats: `,_jsx(_components.code,{children:`json_icu`}),`, `,_jsx(_components.code,{children:`json_i18next`}),`, `,_jsx(_components.code,{children:`json_vue_i18n`}),`. Ignored for base text (non-variant) exports or any other formats.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`includeVariableSummary?: boolean`}),`. If `,_jsx(_components.code,{children:`true`}),`, will add a `,_jsx(_components.code,{children:`__variables_used`}),` field to the bottom of the exported file, which will contain an alphabetical list (array) of the names of all the variables that are present in the export. If omitted or set to false, this field will not be added to the file. Applies to the following formats: `,_jsx(_components.code,{children:`json_i18next`}),`, `,_jsx(_components.code,{children:`json_vue_i18n`}),`. Ignored for any other formats.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Affected endpoints:`})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)`]}),`\n`]}),`\n`,_jsx(Heading,{level:`4`,id:`empty-text-is-now-included-in-exports`,children:`Empty text is now included in exports`}),`\n`,_jsx(_components.p,{children:`Text items and components with empty text are now included in every export format, instead of being left out. This applies to empty base text, empty variant text, and empty plural forms; the behavior change primarily affects empty variants. Items that don’t have the requested variant at all are still left out of that variant’s export.`}),`\n`,_jsx(_components.p,{children:`Because these keys used to be missing, most localization libraries fell back to either the base text or to the key itself. Now that they’re included with an empty value, your app will render them as empty.`}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`This is a behavior change for plaintext exports that contain empty text. If a variant’s text is empty by mistake, your\napp will now show it as empty instead of falling back to the base text. Fill in the variant’s text, or remove the\nvariant from that text item or component to continue rendering base text.`})}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Format-specific details:`})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`json_vue_i18n`}),`: An empty plural form is written as the literal `,_jsx(_components.code,{children:`{''}`}),`, and a plural form that contains only whitespace is written as a literal that keeps it, such as `,_jsx(_components.code,{children:`{' '}`}),`. vue-i18n can’t compile a plural message with an empty choice, so plural messages with an empty form previously caused an error when they were rendered.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`json_icu`}),` and `,_jsx(_components.code,{children:`arb`}),`: Plural messages are now included when their first form is empty. Previously, the whole message was left out, even if its other forms had text. FormatJS (`,_jsx(_components.code,{children:`react-intl`}),`) treats an empty message as missing by default; set `,_jsx(_components.code,{children:`fallbackOnEmptyString: false`}),` to render it as empty.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`android`}),`: Empty strings and plural forms are written as self-closing elements, such as `,_jsx(_components.code,{children:`\u003cstring name=\"welcome\"/>`}),`. This also fixes malformed XML in exports that contained an empty plural form.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Affected endpoints:`})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)`]}),`\n`]}),`\n`,_jsxs(Heading,{level:`4`,id:`consistent-html-and-html_paragraphs-rich-text-output`,children:[`Consistent `,_jsx(_components.code,{children:`html`}),` and `,_jsx(_components.code,{children:`html_paragraphs`}),` rich text output`]}),`\n`,_jsxs(_components.p,{children:[`Standardizes the html rich text outputs across all four related endpoints. `,_jsx(_components.code,{children:`richText=\"html_paragraphs\"`}),` wraps all text in `,_jsx(_components.code,{children:`\u003cp>`}),` tags, while `,_jsx(_components.code,{children:`richText=\"html\"`}),` does not wrap its content in outer tags, and uses `,_jsx(_components.code,{children:`\u003cbr />`}),` for line breaks. All other html generation is identical between the two formats.`]}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Affected endpoints:`})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Prior to this change, the `,_jsx(_components.code,{children:`html`}),` parameter returned the unwrapped text from the Fetch endpoints, and the paragraph-wrapped text from the Export endpoints. Now, all four endpoints return the same output format for each richText option.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`This is a behavior change for the Export endpoints. To continue receiving identical output, you must switch from\n`,_jsx(_components.code,{children:`html`}),` to `,_jsx(_components.code,{children:`html_paragraphs`}),`.`]})}),`\n`,_jsxs(_components.p,{children:[`The Create and Update endpoints are unaffected by this change. They still maintain a single `,_jsx(_components.code,{children:`html`}),` rich text option, which can convert either paragraph format into Ditto rich text.`]}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Example:`})}),`\n`,_jsx(_components.p,{children:`For a text item with two paragraphs:`}),`\n`,_jsxs(_components.blockquote,{children:[`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Welcome back!`}),_jsx(`br`,{}),`\nYour order has shipped.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`richText=html`}),` returns:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`html`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`html`,children:_jsxs(_components.code,{language:`html`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`\u003c`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`strong`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`Welcome back!`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`\u003c/`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`strong`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>\u003c`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`br`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:` />`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`Your order has shipped.`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`richText=html_paragraphs`}),` returns:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`html`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`html`,children:_jsxs(_components.code,{language:`html`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`\u003c`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`p`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>\u003c`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`strong`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`Welcome back!`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`\u003c/`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`strong`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>\u003c/`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`p`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`\u003c`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`p`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`Your order has shipped.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`\u003c/`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`p`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`>`})]}),`\n`]})})}),`\n`,_jsxs(Heading,{level:`4`,id:`variant-notes-in-arb-and-ios-strings-exports`,children:[`Variant notes in `,_jsx(_components.code,{children:`arb`}),` and `,_jsx(_components.code,{children:`ios-strings`}),` exports`]}),`\n`,_jsxs(_components.p,{children:[`Variant exports now use the variant’s own notes as each string’s `,_jsx(_components.code,{children:`description`}),` in `,_jsx(_components.code,{children:`arb`}),`, and as the comment above each string in `,_jsx(_components.code,{children:`ios-strings`}),`. If a variant has no notes, its base notes are used instead. Base exports are unchanged.`]}),`\n`,_jsx(_components.p,{children:`Previously, both formats always used the base notes, even in variant exports.`}),`\n`,_jsx(_components.p,{children:_jsx(_components.strong,{children:`Affected endpoints:`})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-11-0`,children:`Ditto CLI - 5.11.0`}),`\n`,_jsxs(_components.p,{children:[`Updates the CLI to support the new `,_jsx(_components.code,{children:`html_paragraphs`}),` rich text parameter.`]}),`\n`,_jsxs(_components.p,{children:[`Prior to the API changes, the CLI used unwrapped `,_jsx(_components.code,{children:`html`}),` for the plain JSON export and the JSON export with `,_jsx(_components.code,{children:`i18next`}),` and `,_jsx(_components.code,{children:`vue-i18n`}),` frameworks. All other formats (including `,_jsx(_components.code,{children:`json_icu`}),`) returned the `,_jsx(_components.code,{children:`html_paragraphs`}),` style.`]}),`\n`,_jsxs(_components.p,{children:[`The API changes mentioned above affect all CLI versions immediately. If you were using one of the other formats with rich text, and want to continue exporting with the legacy format, you will need to upgrade to this CLI version and change your config file from `,_jsx(_components.code,{children:`richText: html`}),` to `,_jsx(_components.code,{children:`richText: html_paragraphs`}),`.`]}),`\n`,_jsx(_components.p,{children:`Additionally, this version includes the following bug fixes:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Generates plurals correctly for `,_jsx(_components.code,{children:`format: json, framework: vue-i18n`}),`, as returned from the Export endpoints.`]}),`\n`,_jsxs(_components.li,{children:[`Respects the `,_jsx(_components.code,{children:`integrated`}),` filter for `,_jsx(_components.code,{children:`components`}),` fetches. Previously, it was only applied to text items.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-7-2026`,children:`October 7, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-7`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`newDeveloperId`}),` to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/styleguides/patch-styleguides`,children:`Update a style guide`}),` (`,_jsx(_components.code,{children:`PATCH /v2/styleguides`}),`) for renaming a style guide’s developer ID. It can be set alongside other field changes in the same request, and must be unique among the workspace’s style guides.`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-3`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`newDeveloperId`}),` to the `,_jsx(_components.a,{href:`/mcp-reference/tools#update_styleguide`,children:_jsx(_components.code,{children:`update_styleguide`})}),` tool for renaming a style guide’s developer ID. It can be combined with other field changes in the same call.`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-5-2026`,children:`October 5, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-8`,children:`API`}),`\n`,_jsx(_components.p,{children:`Improvements to plural exports for json formats.`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`json_i18next`}),` Now returns the unsuffixed key alongside all plural keys. This brings it in line with what the CLI exports for `,_jsx(_components.code,{children:`json`}),` and `,_jsx(_components.code,{children:`json + i18next`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`json_vue_i18n`}),` Resolves a minor bug in how plurals were generated if you had a `,_jsx(_components.code,{children:`zero`}),` and `,_jsx(_components.code,{children:`other`}),` form defined but not a `,_jsx(_components.code,{children:`one`}),` form. This format still drops `,_jsx(_components.code,{children:`two`}),`, `,_jsx(_components.code,{children:`few`}),`, and `,_jsx(_components.code,{children:`many`}),` forms, which are not supported by Vue without a custom rule definition. This change is not yet reflected in the CLI.`]}),`\n`]}),`\n`,_jsx(_components.p,{children:`This affects the following endpoints:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-1-2026`,children:`October 1, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-4`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#translate_text_items`,children:_jsx(_components.code,{children:`translate_text_items`})}),` tool for translating project text items into a variant’s locale, applying any style guide scoped to that locale.`]}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#translate_library_components`,children:_jsx(_components.code,{children:`translate_library_components`})}),` tool for translating library components into a variant’s locale, applying any style guide scoped to that locale.`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-17-2026`,children:`September 17, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-10-0`,children:`Ditto CLI - 5.10.0`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/cli-reference/commands#scan`,children:_jsx(_components.code,{children:`scan`})}),` now requires a clean checkout of your repository’s default branch. Scanning from a tree with uncommitted changes, from a non-default branch, or from a detached `,_jsx(_components.code,{children:`HEAD`}),` stops with a message explaining what to change, before anything is uploaded.`]}),`\n`,_jsx(_components.p,{children:`Scan records the commit and branch it read, and the code links Ditto builds point at them. A scan taken from anywhere else describes lines your default branch never had, so a later scan reports those links as changed or removed when nothing actually changed.`}),`\n`,_jsxs(_components.p,{children:[`The default branch comes from `,_jsx(_components.code,{children:`origin/HEAD`}),`, falling back to a local `,_jsx(_components.code,{children:`main`}),` or `,_jsx(_components.code,{children:`master`}),`. Because that reference is set when you clone and doesn’t update on its own, a mismatch is confirmed against your remote first, so a branch renamed after you cloned won’t block you. Scanning outside a Git repository is unaffected.`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-3-2026`,children:`September 3, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-9`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/publish-component`,children:`Publish component`}),` (`,_jsx(_components.code,{children:`POST /v2/components/publish`}),`) endpoint for publishing an existing text item to the component library.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/link-components`,children:`Link components`}),` (`,_jsx(_components.code,{children:`PATCH /v2/components/link`}),`) endpoint for linking text items to a library component by developer ID.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/unlink-components`,children:`Unlink components`}),` endpoint, which unlinks every text item that currently shares a given developer ID with its sibling instances. Accepts an optional `,_jsx(_components.code,{children:`projectId`}),` to scope the unlink to a single project.`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-5`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#publish_library_component`,children:_jsx(_components.code,{children:`publish_library_component`})}),` for publishing an existing text item to the component library.`]}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#link_text_items_to_component`,children:_jsx(_components.code,{children:`link_text_items_to_component`})}),` for linking text items to a library component by developer ID.`]}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#unlink_text_items_from_component`,children:_jsx(_components.code,{children:`unlink_text_items_from_component`})}),` tool, which unlinks every text item that currently shares a given developer ID with its sibling instances. Accepts an optional `,_jsx(_components.code,{children:`projectId`}),` to scope the unlink to a single project.`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-2-2026`,children:`September 2, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-10`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/link-figma-nodes`,children:`Link Figma nodes`}),` (`,_jsx(_components.code,{children:`POST /v2/textItems/linkFigmaNodes`}),`) endpoint for linking already-synced Figma text nodes to an existing text item, up to 50 node IDs per request.`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-6`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.code,{children:`link_figma_nodes_to_text_item`}),` tool for linking already-synced Figma text nodes to an existing text item. Replaced by `,_jsx(_components.a,{href:`/mcp-reference/tools#link_figma_nodes_to_text_items`,children:_jsx(_components.code,{children:`link_figma_nodes_to_text_items`})}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`figma`}),` to the `,_jsx(_components.a,{href:`/mcp-reference/tools#search_ditto_text`,children:_jsx(_components.code,{children:`search_ditto_text`})}),` `,_jsx(_components.code,{children:`fields`}),` parameter, returning the Figma text node IDs linked to each text item.`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-27-2026`,children:`August 27, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-11`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://github.com/google/app-resource-bundle/wiki/ApplicationResourceBundleSpecification`,children:`ARB`}),` as an export format for `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`) and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`) — provide `,_jsx(_components.code,{children:`?format=arb`}),`. See `,_jsx(_components.a,{href:`/string-formats/json#arb-json`,children:`ARB JSON`}),` for the content shape.`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-9-0`,children:`Ditto CLI - 5.9.0`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`framework: arb`}),` and `,_jsx(_components.code,{children:`framework: icu`}),` for `,_jsx(_components.code,{children:`json`}),`-format outputs, generating `,_jsx(_components.a,{href:`/string-formats/json#arb-json`,children:`ARB`}),` and `,_jsx(_components.a,{href:`/string-formats/json#icu-json`,children:`ICU`}),` JSON respectively. See `,_jsx(_components.a,{href:`/cli-reference/files#framework-specific-files`,children:`Frameworks`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/cli-reference/configuration#androidlocales`,children:_jsx(_components.code,{children:`androidLocales`})}),`, which maps Ditto variant IDs to Android locale-qualified resource directories (`,_jsx(_components.code,{children:`values-\u003clocale>/`}),`) — the Android counterpart to `,_jsx(_components.code,{children:`iosLocales`}),`. Unlike `,_jsx(_components.code,{children:`iosLocales`}),`, there’s no need to map `,_jsx(_components.code,{children:`base`}),`, since Android already has a default resource directory (`,_jsx(_components.code,{children:`values/`}),`) that the platform falls back to automatically.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/cli-reference/configuration#androidlocalesoutdir`,children:_jsx(_components.code,{children:`androidLocalesOutDir`})}),` and `,_jsx(_components.a,{href:`/cli-reference/configuration#ioslocalesoutdir`,children:_jsx(_components.code,{children:`iosLocalesOutDir`})}),`, which let Android and iOS locale-organized output be written to separate root directories — useful since they typically need to live in different parts of a codebase.`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-24-2026`,children:`August 24, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-8-1`,children:`Ditto CLI - 5.8.1`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/cli-reference/commands#scan`,children:_jsx(_components.code,{children:`scan`})}),` now records which part of your repository it looked at, alongside the Git context added in 5.8.0. Scanning a repository root is recorded as covering the whole repository; scanning a single directory is recorded as covering only that directory.`]}),`\n`,_jsx(_components.p,{children:`This lets Ditto tell the difference between a string removed from your code and a string that simply was not part of the scan, so re-scanning one directory implies nothing about the rest of the repository.`}),`\n`,_jsx(Heading,{level:`2`,id:`august-20-2026`,children:`August 20, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-8-0`,children:`Ditto CLI - 5.8.0`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/cli-reference/commands#scan`,children:_jsx(_components.code,{children:`scan`})}),` now records the Git repository, commit, and branch of the code it scans. Ditto uses these to recognize a codebase it has already seen, so a later scan of the same repository can be matched against an earlier one instead of importing every string again.`]}),`\n`,_jsx(_components.p,{children:`This is read from your local Git checkout. Scan makes no additional network requests, does not send Git credentials, and records nothing about your remote beyond its host and path. Scanning outside a Git repository still works — the CLI notes that the scan can be imported but not re-synced, and continues.`}),`\n`,_jsx(Heading,{level:`2`,id:`august-18-2026`,children:`August 18, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-7-2`,children:`Ditto CLI - 5.7.2`}),`\n`,_jsxs(_components.p,{children:[`Move `,_jsx(_components.a,{href:`/cli-reference/commands#scan`,children:_jsx(_components.code,{children:`scan`})}),` text extraction into the shared `,_jsx(_components.code,{children:`@dittowords/text-extract`}),` library. Extraction behavior is unchanged.`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-17-2026`,children:`August 17, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-12`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`richText`}),` parameter to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/create-components`,children:`Create components`}),` (`,_jsx(_components.code,{children:`POST /v2/components`}),`) and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/patch-components`,children:`Patch components`}),` (`,_jsx(_components.code,{children:`PATCH /v2/components`}),`).`]}),`\n`,_jsxs(_components.p,{children:[`When `,_jsx(_components.code,{children:`richText`}),` param is set to `,_jsx(_components.code,{children:`html`}),`, all text values in the update request — including plural and variant text — will be parsed as an HTML string and saved as rich text.`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-13-2026`,children:`August 13, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-7-1`,children:`Ditto CLI - 5.7.1`}),`\n`,_jsxs(_components.p,{children:[`Improve how `,_jsx(_components.a,{href:`/cli-reference/commands#scan`,children:_jsx(_components.code,{children:`scan`})}),` decodes the text it extracts. Escape sequences, XML entities, and inline markup are now handled per file format, so candidates arrive in Ditto as the text a user sees instead of as raw source.`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-7`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#list_statuses`,children:_jsx(_components.code,{children:`list_statuses`})}),` tool, which lists the statuses text items and library components can be set to, in workflow order.`]}),`\n`,_jsxs(_components.p,{children:[`The MCP server now supports logging in with your Ditto account via OAuth, in addition to a static API token. See `,_jsx(_components.a,{href:`/guides/connect-the-mcp`,children:`Installation`}),` for setup instructions per client.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-13`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/delete-components`,children:`Delete components`}),` (`,_jsx(_components.code,{children:`DELETE /v2/components`}),`) endpoint for deleting library components by developer ID.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/statuses/get-statuses`,children:`Fetch statuses`}),` (`,_jsx(_components.code,{children:`GET /v2/statuses`}),`) endpoint for listing the statuses available in a workspace, in workflow order.`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-11-2026`,children:`August 11, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-14`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`richText`}),` parameter to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/patch-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PATCH /v2/textItems`}),`) and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/create-text-items`,children:`Create text items`}),` (`,_jsx(_components.code,{children:`POST /v2/textItems`}),`).`]}),`\n`,_jsxs(_components.p,{children:[`When `,_jsx(_components.code,{children:`richText`}),` param is set to `,_jsx(_components.code,{children:`html`}),`, all `,_jsx(_components.code,{children:`text`}),` values in the update request — including plural and variant text — will be parsed as an HTML string and saved as rich text.`]}),`\n`,_jsxs(_components.p,{children:[`For example, the following request would store formatted string “`,_jsx(_components.strong,{children:`Inspiration`}),` for your next trip” as the Korean variant:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`7`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`7`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"richText\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"html\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"variantId\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"korean\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"updates\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"developerId\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"homepage.section.inspiration\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"\u003cstrong>Inspiration\u003c/strong> for your next trip\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Supported formatting: `,_jsx(_components.code,{children:`\u003cstrong>`}),`/`,_jsx(_components.code,{children:`\u003cb>`}),`, `,_jsx(_components.code,{children:`\u003cem>`}),`/`,_jsx(_components.code,{children:`\u003ci>`}),`, `,_jsx(_components.code,{children:`\u003cu>`}),`, `,_jsx(_components.code,{children:`\u003cs>`}),`, and `,_jsx(_components.code,{children:`\u003cbr>`}),` for line breaks.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`\u003csup>`}),` and `,_jsx(_components.code,{children:`\u003csub>`}),` are only supported for workspaces with superscript and subscript enabled.`]}),`\n`,_jsx(_components.li,{children:`We drop unsupported markup such as links, lists, or headings but keep its text.`}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`{{variable_name}}`}),` placeholders still resolve, and keep any formatting applied around them.`]}),`\n`,_jsx(_components.li,{children:`Without the parameter, text is saved as plaintext and any markup is stored literally, unchanged from previous behavior.`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-10-2026`,children:`August 10, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-8`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#create_variables`,children:_jsx(_components.code,{children:`create_variables`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#update_variables`,children:_jsx(_components.code,{children:`update_variables`})}),`, and `,_jsx(_components.a,{href:`/mcp-reference/tools#delete_variables`,children:_jsx(_components.code,{children:`delete_variables`})}),` tools for managing variables from your editor.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-15`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variables/create-variables`,children:`Create variables`}),` (`,_jsx(_components.code,{children:`POST /v2/variables`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variables/patch-variables`,children:`Update variables`}),` (`,_jsx(_components.code,{children:`PATCH /v2/variables`}),`), and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variables/delete-variables`,children:`Delete variables`}),` (`,_jsx(_components.code,{children:`DELETE /v2/variables`}),`) endpoints.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Renaming a variable with `,_jsx(_components.code,{children:`newName`}),` rewrites every `,_jsx(_components.code,{children:`{{variable_name}}`}),` placeholder referencing it — across text items, library components, variants, and plurals — so existing text keeps resolving.`]}),`\n`,_jsx(_components.li,{children:`A variable can’t be deleted while any text item or library component still references it.`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-6-2026`,children:`August 6, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-9`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#create_variants`,children:_jsx(_components.code,{children:`create_variants`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#update_variants`,children:_jsx(_components.code,{children:`update_variants`})}),`, and `,_jsx(_components.a,{href:`/mcp-reference/tools#delete_variants`,children:_jsx(_components.code,{children:`delete_variants`})}),` tools for managing variants from your editor.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-16`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variants/create-variants`,children:`Create variants`}),` (`,_jsx(_components.code,{children:`POST /v2/variants`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variants/patch-variants`,children:`Update variants`}),` (`,_jsx(_components.code,{children:`PATCH /v2/variants`}),`), and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variants/delete-variants`,children:`Delete variants`}),` (`,_jsx(_components.code,{children:`DELETE /v2/variants`}),`) endpoints.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`At most one variant per workspace can hold a given locale code.`}),`\n`,_jsx(_components.li,{children:`A variant can’t be deleted while any text item or library component still has text for it.`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-5-2026`,children:`August 5, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-7-0`,children:`Ditto CLI - 5.7.0`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/cli-reference/commands#login`,children:_jsx(_components.code,{children:`login`})}),` and `,_jsx(_components.a,{href:`/cli-reference/commands#logout`,children:_jsx(_components.code,{children:`logout`})}),` commands. `,_jsx(_components.code,{children:`login`}),` signs you in through your browser, so the CLI no longer needs an API key.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` @dittowords/cli`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` login`})]}),`\n`]})})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The session is saved to `,_jsx(_components.code,{children:`$HOME/.config/ditto`}),` and renews itself as you keep using the CLI. Commands act as you — your Ditto account and its permissions — instead of as whoever generated an API key.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`logout`}),` forgets the session on this machine and revokes it with Ditto.`]}),`\n`,_jsxs(_components.li,{children:[`API keys still work. `,_jsx(_components.code,{children:`DITTO_TOKEN`}),` takes precedence over a saved session, so CI and other headless environments are unaffected. See `,_jsx(_components.a,{href:`/cli-reference/authentication#credential-precedence`,children:`credential precedence`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-3-2026`,children:`August 3, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-10`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#create_styleguide`,children:_jsx(_components.code,{children:`create_styleguide`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#list_styleguides`,children:_jsx(_components.code,{children:`list_styleguides`})}),`, and `,_jsx(_components.a,{href:`/mcp-reference/tools#update_styleguide`,children:_jsx(_components.code,{children:`update_styleguide`})}),` tools for managing style guides themselves — sections, the default-enabled setting, and metadata — as opposed to the rules inside them. Add `,_jsx(_components.a,{href:`/mcp-reference/tools#create_styleguide_rules`,children:_jsx(_components.code,{children:`create_styleguide_rules`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#update_styleguide_rules`,children:_jsx(_components.code,{children:`update_styleguide_rules`})}),`, and `,_jsx(_components.a,{href:`/mcp-reference/tools#delete_styleguide_rules`,children:_jsx(_components.code,{children:`delete_styleguide_rules`})}),` tools for managing the rules inside a style guide section.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#list_component_folders`,children:_jsx(_components.code,{children:`list_component_folders`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#create_component_folders`,children:_jsx(_components.code,{children:`create_component_folders`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#update_component_folders`,children:_jsx(_components.code,{children:`update_component_folders`})}),`, and `,_jsx(_components.a,{href:`/mcp-reference/tools#delete_component_folders`,children:_jsx(_components.code,{children:`delete_component_folders`})}),` tools for managing component library folders from your editor.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-17`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/styleguides/create-styleguides`,children:`Create a style guide`}),` (`,_jsx(_components.code,{children:`POST /v2/styleguides`}),`) and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/styleguides/patch-styleguides`,children:`Update a style guide`}),` (`,_jsx(_components.code,{children:`PATCH /v2/styleguides`}),`) endpoints, along with `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/styleguides/create-styleguide-rules`,children:`Create style guide rules`}),` (`,_jsx(_components.code,{children:`POST /v2/styleguides/rules`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/styleguides/patch-styleguide-rules`,children:`Update style guide rules`}),` (`,_jsx(_components.code,{children:`PATCH /v2/styleguides/rules`}),`), and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/styleguides/delete-styleguide-rules`,children:`Delete style guide rules`}),` (`,_jsx(_components.code,{children:`DELETE /v2/styleguides/rules`}),`) endpoints for managing the rules inside a section.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/component-folders/get-component-folders`,children:`Fetch component folders`}),` (`,_jsx(_components.code,{children:`GET /v2/componentFolders`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/component-folders/create-component-folders`,children:`Create component folders`}),` (`,_jsx(_components.code,{children:`POST /v2/componentFolders`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/component-folders/patch-component-folders`,children:`Update component folders`}),` (`,_jsx(_components.code,{children:`PATCH /v2/componentFolders`}),`), and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/component-folders/delete-component-folders`,children:`Delete component folders`}),` (`,_jsx(_components.code,{children:`DELETE /v2/componentFolders`}),`) endpoints.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-31-2026`,children:`July 31, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-11`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#suggest_edit`,children:_jsx(_components.code,{children:`suggest_edit`})}),` tool, which checks text against your workspace’s style guide rules and returns suggested edits — the same rule-based suggestions shown in the Ditto app. Check an existing text item by developer ID, or freeform text that isn’t saved as a text item yet.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-29-2026`,children:`July 29, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-12`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#list_project_blocks`,children:_jsx(_components.code,{children:`list_project_blocks`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#create_project_blocks`,children:_jsx(_components.code,{children:`create_project_blocks`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#update_project_blocks`,children:_jsx(_components.code,{children:`update_project_blocks`})}),`, and `,_jsx(_components.a,{href:`/mcp-reference/tools#delete_project_blocks`,children:_jsx(_components.code,{children:`delete_project_blocks`})}),` tools for managing the blocks that group text items within a project.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-18`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/project-blocks/get-project-blocks`,children:`Fetch project blocks`}),` (`,_jsx(_components.code,{children:`GET /v2/projectBlocks`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/project-blocks/create-project-blocks`,children:`Create project blocks`}),` (`,_jsx(_components.code,{children:`POST /v2/projectBlocks`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/project-blocks/patch-project-blocks`,children:`Update project blocks`}),` (`,_jsx(_components.code,{children:`PATCH /v2/projectBlocks`}),`), and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/project-blocks/delete-project-blocks`,children:`Delete project blocks`}),` (`,_jsx(_components.code,{children:`DELETE /v2/projectBlocks`}),`) endpoints.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-27-2026`,children:`July 27, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-6-3`,children:`Ditto CLI - 5.6.3`}),`\n`,_jsxs(_components.p,{children:[`Improve how `,_jsx(_components.a,{href:`/cli-reference/commands#scan`,children:_jsx(_components.code,{children:`scan`})}),` handles codebases that are larger than a workspace’s plan’s scan limit.`]}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.code,{children:`--list-directories`}),` flag. `,_jsx(_components.code,{children:`scan \u003cpath> --list-directories`}),` prints the number of candidate strings found in each directory and exits without uploading anything, so you can choose a scope before running a real scan.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npx`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` @dittowords/cli`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` scan`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` .`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --list-directories`})]}),`\n`]})})}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Counts are rolled up: each directory includes the strings found in its subdirectories.`}),`\n`,_jsx(_components.li,{children:`Directories are printed in tree order, indented by depth, with the whole scan total at the top.`}),`\n`]}),`\n`,_jsx(_components.p,{children:`When a scan exceeds your plan’s limit, the error now suggests narrower paths to scan instead of just reporting the limit.`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`The message lists the largest subdirectories that each fit within your remaining limit, with their string counts and a ready-to-run command for each.`}),`\n`,_jsx(_components.li,{children:`The limit is checked before candidates are uploaded, so an oversized scan fails right away instead of after the upload finishes.`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-13`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#create_ditto_project`,children:_jsx(_components.code,{children:`create_ditto_project`})}),` and `,_jsx(_components.a,{href:`/mcp-reference/tools#list_project_folders`,children:_jsx(_components.code,{children:`list_project_folders`})}),` tools for creating projects and looking up project folders from your editor.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-19`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/projects/create-projects`,children:`Create a project`}),` (`,_jsx(_components.code,{children:`POST /v2/projects`}),`) endpoint. Optionally provide a folder’s developer ID to create the project inside that folder.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-24-2026`,children:`July 24, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-14`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#create_library_components`,children:_jsx(_components.code,{children:`create_library_components`})}),` and `,_jsx(_components.a,{href:`/mcp-reference/tools#update_library_components`,children:_jsx(_components.code,{children:`update_library_components`})}),` tools for managing library components from your editor, and the `,_jsx(_components.a,{href:`/mcp-reference/tools#list_component_folders`,children:_jsx(_components.code,{children:`list_component_folders`})}),` tool for looking up their folders.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-22-2026`,children:`July 22, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`documentation`,children:`Documentation`}),`\n`,_jsxs(_components.p,{children:[`Document the `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-agent-setup`,children:`agent setup package`}),` as the default way to integrate Ditto with Claude Code. See `,_jsx(_components.a,{href:`/guides/connect-the-mcp`,children:`Agent setup package`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Standardize the API token environment variable to `,_jsx(_components.code,{children:`DITTO_TOKEN`}),` across the CLI, Ditto Specs, and MCP setup docs (previously `,_jsx(_components.code,{children:`DITTO_API_KEY`}),` and `,_jsx(_components.code,{children:`DITTO_API_TOKEN`}),`).`]}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-15`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#list_variants`,children:_jsx(_components.code,{children:`list_variants`})}),` and `,_jsx(_components.a,{href:`/mcp-reference/tools#list_variables`,children:_jsx(_components.code,{children:`list_variables`})}),` tools, and expose variants and variables on the text item and library component tools — reference a variable with a `,_jsx(_components.code,{children:`{{variable_name}}`}),` placeholder, or set variant-specific text via a variant’s developer ID.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-10-2026`,children:`July 10, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-16`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`/mcp-reference/tools#create_text_items`,children:_jsx(_components.code,{children:`create_text_items`})}),`, `,_jsx(_components.a,{href:`/mcp-reference/tools#update_text_items`,children:_jsx(_components.code,{children:`update_text_items`})}),`, and `,_jsx(_components.a,{href:`/mcp-reference/tools#delete_text_items`,children:_jsx(_components.code,{children:`delete_text_items`})}),` tools for managing text items in bulk from your editor, and the `,_jsx(_components.a,{href:`/mcp-reference/tools#list_projects`,children:_jsx(_components.code,{children:`list_projects`})}),` tool for looking up a project’s developer ID.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-9-2026`,children:`July 9, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-20`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/activity/get-activity`,children:`Fetch activity`}),` (`,_jsx(_components.code,{children:`GET /v2/activity`}),`) endpoint for retrieving a paginated list of change events in your workspace, optionally filtered by project, text item, library component, or entity type.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-1-2026`,children:`July 1, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-21`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`blockName`}),` field to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) response.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Each text item now includes a `,_jsx(_components.code,{children:`blockName`}),` field: the name of the block the text item belongs to, or `,_jsx(_components.code,{children:`null`}),` if it is not in a block.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-25-2026`,children:`June 25, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-22`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`sort`}),` parameter to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`).`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`id`}),` (default) sorts the response alphabetically by developer ID (matching previous behavior)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`project_order`}),` groups items by project, returned alphabetically by project developer ID, then sorts within projects based on the custom sort order set up in the web app.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-16-2026`,children:`June 16, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-6-0`,children:`Ditto CLI - 5.6.0`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.code,{children:`scan`}),` command. `,_jsx(_components.code,{children:`scan \u003cpath>`}),` analyzes a local directory for user-facing text and sends the candidates to Ditto, where you can review them and turn them into a content system tailored to your product. See the `,_jsx(_components.a,{href:`/cli-reference/commands#scan`,children:`Scan documentation`}),`.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`This release includes packages that require `,_jsx(_components.strong,{children:`Node.js 20 or higher`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-10-2026`,children:`June 10, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-23`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add new variant fields `,_jsx(_components.code,{children:`variants[n].status`}),`, `,_jsx(_components.code,{children:`variants[n].assignee`}),`, `,_jsx(_components.code,{children:`variants[n].notes`}),`, and `,_jsx(_components.code,{children:`variants[n].characterLimit`}),` to the `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/create-text-items`,children:`Create text items`}),` resource.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`assignee`}),` must be a valid email matching a user in your workspace`]}),`\n`,_jsxs(_components.li,{children:[`variant `,_jsx(_components.code,{children:`status`}),` must be a valid status in your workspace`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-4-2026`,children:`June 4, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-24`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`folderId`}),` to the `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/patch-components`,children:`Update components`}),` resource, allowing users to organize their components in bulk.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`If `,_jsx(_components.code,{children:`folderId`}),` of `,_jsx(_components.code,{children:`null`}),` or `,_jsx(_components.code,{children:`\"root\"`}),` is provided, will move component into “All Components”.`]}),`\n`,_jsxs(_components.li,{children:[`If `,_jsx(_components.code,{children:`folderId`}),` omitted, component folder will remain unchanged`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/styleguides/get-styleguides`,children:`Get style guides`}),` (`,_jsx(_components.code,{children:`GET /v2/styleguides`}),`) endpoint for fetching the style guides created in your workspace, along with their sections and rules.`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-28-2026`,children:`May 28, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-25`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`assignee`}),`, along with new variant fields `,_jsx(_components.code,{children:`variants[n].status`}),`, `,_jsx(_components.code,{children:`variants[n].assignee`}),`, `,_jsx(_components.code,{children:`variants[n].notes`}),`, and `,_jsx(_components.code,{children:`variants[n].characterLimit`}),` to the `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/create-components`,children:`Create components`}),` resource.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`assignee`}),` must be a valid email matching a user in your workspace`]}),`\n`,_jsxs(_components.li,{children:[`variant `,_jsx(_components.code,{children:`status`}),` must be a valid status in your workspace`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-18-2026`,children:`May 18, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-26`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`characterLimit`}),` field to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`) responses.`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Each text item and component in the response now includes a `,_jsx(_components.code,{children:`characterLimit`}),` field: a positive integer when a limit is set, or `,_jsx(_components.code,{children:`null`}),` when no limit is configured.`]}),`\n`,_jsxs(_components.li,{children:[`For variant responses, `,_jsx(_components.code,{children:`characterLimit`}),` reflects the variant’s own character limit rather than the base value.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-12-2026`,children:`May 12, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-27`,children:`API`}),`\n`,_jsx(_components.p,{children:`Update Text Item and Component endpoints to support variant assignee, notes and character limit.`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`) now return variant assignee and notes in variant response objects, not the base properties.`]}),`\n`,_jsxs(_components.li,{children:[`Requests that include an assignee filter and a variantId return only items whose base and variant assignees both match the filter. This applies to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`), `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`), and `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`).`]}),`\n`,_jsxs(_components.li,{children:[`Requests that include assignee, notes and/or character limit along with a variantId in the payload of `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/patch-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PATCH /v2/textItems`}),`) or `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/patch-components`,children:`Update components`}),` (`,_jsx(_components.code,{children:`PATCH /v2/components`}),`) will update that variant’s properties, not the base values.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`april-30-2026`,children:`April 30, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-28`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add component name to the response of `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`) endpoint. Each component in the response will now include a `,_jsx(_components.code,{children:`name`}),` field matching the component name. The same component name will be returned across base text, variants and plural forms.`]}),`\n`,_jsx(Heading,{level:`2`,id:`april-6-2026`,children:`April 6, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-29`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/patch-components`,children:`Update components`}),` (`,_jsx(_components.code,{children:`PATCH /v2/components`}),`) endpoint.\nSupports updating text, tags, status, and assignee on components identified by developer ID. Includes optional variant targeting with `,_jsx(_components.code,{children:`variantId`}),` and `,_jsx(_components.code,{children:`forceVariantCreation`}),` parameters.`]}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`PATCH /v2/textItems`}),` as the preferred method for updating text items. `,_jsx(_components.code,{children:`PUT /v2/textItems`}),` continues to work but is now deprecated.`]}),`\n`,_jsx(Heading,{level:`2`,id:`april-1-2026`,children:`April 1, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-5-1`,children:`Ditto CLI - 5.5.1`}),`\n`,_jsxs(_components.p,{children:[`Dependency updates and internal improvements. See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.5.1`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-31-2026`,children:`March 31, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-5-0`,children:`Ditto CLI - 5.5.0`}),`\n`,_jsxs(_components.p,{children:[`Add CLI support for filtering by tags. Add a `,_jsx(_components.code,{children:`tags`}),` configuration to your config file to scope text items and components by one or more tags, with support for `,_jsx(_components.code,{children:`AND`}),`/`,_jsx(_components.code,{children:`OR`}),` operators.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`tags`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` values`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"tag-1\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"tag-2\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` operator`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"AND\"`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`tags`}),` filter can be specified at the top level of your config or within individual outputs (output-level overrides top-level). When `,_jsx(_components.code,{children:`operator`}),` is `,_jsx(_components.code,{children:`\"AND\"`}),`, only items with all specified tags are returned. When `,_jsx(_components.code,{children:`operator`}),` is `,_jsx(_components.code,{children:`\"OR\"`}),` (or omitted), items with any of the specified tags are returned.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.5.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-27-2026`,children:`March 27, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-17`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#get_workspace_tags`,children:_jsx(_components.code,{children:`get_workspace_tags`})}),` tool, which lists the tags currently in use across the workspace — useful before adding tags to a style guide rule, since only existing tags are allowed. Add the first tools for creating, updating, and deleting style guide rules from your editor.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-26-2026`,children:`March 26, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-30`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`assignee`}),` and `,_jsx(_components.code,{children:`tags`}),` filters to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`),\n`,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`),\nand `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`).\nThe `,_jsx(_components.code,{children:`assignee`}),` filter accepts an email address or `,_jsx(_components.code,{children:`null`}),` to match unassigned items. The `,_jsx(_components.code,{children:`tags`}),` filter accepts an array of tag values with an optional `,_jsx(_components.code,{children:`operator`}),` field (`,_jsx(_components.code,{children:`AND`}),` or `,_jsx(_components.code,{children:`OR`}),`, defaulting to `,_jsx(_components.code,{children:`OR`}),`).`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-24-2026`,children:`March 24, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-4-0`,children:`Ditto CLI - 5.4.0`}),`\n`,_jsxs(_components.p,{children:[`Add CLI support for filtering by integration status. Add `,_jsx(_components.code,{children:`integrated: true`}),` to your config file to fetch only text items and components that have been marked as integrated into development.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.4.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-31`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add the ability to update the `,_jsx(_components.code,{children:`integrated`}),` flag of a text item via `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`).`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-23-2026`,children:`March 23, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-32`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`integrated`}),` field to the response data of:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`).`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Add optional `,_jsx(_components.code,{children:`integrated`}),` boolean filter to:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-20-2026`,children:`March 20, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-18`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`The Ditto MCP server can now run remotely over Streamable HTTP, instead of only as a local stdio server. See `,_jsx(_components.a,{href:`/guides/connect-the-mcp`,children:`Installation`}),` for how to connect Claude Code, Cursor, VS Code, Windsurf, Codex, and other MCP clients.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-19-2026`,children:`March 19, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-33`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`plurals`}),` field to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`) API endpoint.\nThe `,_jsx(_components.code,{children:`plurals`}),` field supports `,_jsx(_components.code,{children:`upsert`}),` and `,_jsx(_components.code,{children:`remove`}),` operations for managing plural forms (zero, one, two, few, many, other) on text items.\nExisting plural forms not mentioned in either operation are preserved. Supports variant plurals via the `,_jsx(_components.code,{children:`variantId`}),` parameter.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-18-2026`,children:`March 18, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-34`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`assignee`}),` and `,_jsx(_components.code,{children:`tags`}),` filters to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`).\nThe `,_jsx(_components.code,{children:`assignee`}),` filter accepts an email address or `,_jsx(_components.code,{children:`null`}),` to match unassigned text items. The `,_jsx(_components.code,{children:`tags`}),` filter accepts an array of tag values with an optional `,_jsx(_components.code,{children:`operator`}),` field (`,_jsx(_components.code,{children:`AND`}),` or `,_jsx(_components.code,{children:`OR`}),`, defaulting to `,_jsx(_components.code,{children:`OR`}),`).`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`)\nand `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`)\nnow include the `,_jsx(_components.code,{children:`assignee`}),` field in the response payload, returned as the assignee’s email address or `,_jsx(_components.code,{children:`null`}),` if unassigned.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-16-2026`,children:`March 16, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-35`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`assignee`}),` field to `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`) API endpoint.\nThe `,_jsx(_components.code,{children:`assignee`}),` field accepts an optional email string of a user in the workspace to assign to the text item. Setting `,_jsx(_components.code,{children:`assignee`}),` to `,_jsx(_components.code,{children:`null`}),` will remove the current assignee.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-12-2026`,children:`March 12, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-19`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Add the `,_jsx(_components.a,{href:`/mcp-reference/tools#search_ditto_text`,children:_jsx(_components.code,{children:`search_ditto_text`})}),` tool, which searches your workspace for existing text items and library components by content — so agents can find and reuse strings instead of generating new ones.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-5-2026`,children:`March 5, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`mcp-20`,children:`MCP`}),`\n`,_jsxs(_components.p,{children:[`Ditto’s MCP server is here! It connects AI coding agents to your team’s content in Ditto, starting with the `,_jsx(_components.a,{href:`/mcp-reference/tools#get_styleguide_rules`,children:_jsx(_components.code,{children:`get_styleguide_rules`})}),` tool for fetching workspace and project-level style guide rules. See the `,_jsx(_components.a,{href:`/mcp-reference/overview`,children:`MCP overview`}),` to get started.`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-10-2026`,children:`February 10, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-36`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/create-components`,children:`Create components`}),` (`,_jsx(_components.code,{children:`POST /v2/components`}),`) endpoint for creating new library components.`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-2-2026`,children:`February 2, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-37`,children:`API`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`),\n`,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`),\n`,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`),\nand `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)\nnow return a `,_jsx(_components.code,{children:`400`}),` error response when statuses that don’t exist in your workspace are provided in the status filter.`]}),`\n`,_jsx(Heading,{level:`2`,id:`january-14-2026`,children:`January 14, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-38`,children:`API`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`)\nand `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`)\nnow return separate records for each plural form. Plural forms follow the standard i18n plural forms outlined `,_jsx(_components.a,{href:`https://www.i18next.com/translation-function/plurals`,children:`here`}),`.\nEach record in the response includes a `,_jsx(_components.code,{children:`pluralForm`}),` value, and for each `,_jsx(_components.code,{children:`pluralForm`}),` on a text item or component, a separate record is returned with\nthat `,_jsx(_components.code,{children:`pluralForm`}),` and its respective value. If a record has a `,_jsx(_components.code,{children:`pluralForm`}),`, it will be appended to the end of the developer ID.`]}),`\n`,_jsx(_components.p,{children:`Example response:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`[`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"some-items\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Some items\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"pluralForm\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`null`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`...`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"some-items_other\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Some items\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"pluralForm\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"other\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`...`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`},`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"id\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"some-items_one\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"An item\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"pluralForm\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"one\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`...`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-3-1`,children:`Ditto CLI - 5.3.1`}),`\n`,_jsxs(_components.p,{children:[`Default `,_jsx(_components.a,{href:`https://developer.dittowords.com/cli-reference/files#json`,children:`JSON file formats`}),` now include plurals, where the standard\nunicode plural rule (zero, one, two, few, many, other) is appended to the end of the developer ID key.`]}),`\n`,_jsx(_components.p,{children:`Example output:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"some-items\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Some items\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"some-items_one\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"An item\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"some-items_other\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"{{count}} items\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.3.1`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`january-7-2026`,children:`January 7, 2026`}),`\n`,_jsx(Heading,{level:`3`,id:`api-39`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/export-text-items`,children:`Export text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems/export`}),`)\nand `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/export-components`,children:`Export components`}),` (`,_jsx(_components.code,{children:`GET /v2/components/export`}),`)\nendpoints for fetching text items and components in `,_jsx(_components.code,{children:`.json`}),` ICU, `,_jsx(_components.code,{children:`.json`}),` i18next, `,_jsx(_components.code,{children:`.json`}),` Vue i18n, `,_jsx(_components.code,{children:`.strings`}),`, `,_jsx(_components.code,{children:`.stringsdict`}),`, or `,_jsx(_components.code,{children:`.xml`}),` formats.`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-3-0`,children:`Ditto CLI - 5.3.0`}),`\n`,_jsxs(_components.p,{children:[`Add CLI support for Android `,_jsx(_components.code,{children:`.xml`}),`, iOS `,_jsx(_components.code,{children:`.strings`}),` and `,_jsx(_components.code,{children:`.stringsdict`}),`, and ICU `,_jsx(_components.code,{children:`.json`}),` formats. In conjunction with iOS format additions,\nadd iOS Locale directory generation for configured variant -> locale mappings in config. If iOS locales are configured, CLI will also auto-generate\na Ditto.swift file for reading locale values.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.3.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`december-11-2025`,children:`December 11, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-2-0`,children:`Ditto CLI - 5.2.0`}),`\n`,_jsxs(_components.p,{children:[`Add CLI support for filtering `,_jsx(_components.a,{href:`/cli-reference/configuration#statuses`,children:`text items/components by status`}),` when pulling changes.\nThe filtering logic used for the cli is the same as the `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) and the `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`) API endpoints.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.2.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`december-10-2025`,children:`December 10, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-40`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Relax requirement in `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`) API endpoint that requires text to be included in the request.\nAdd `,_jsx(_components.code,{children:`tags`}),` field which is an optional `,_jsx(_components.code,{children:`string[]`}),` that if set in the request will replace the existing tags with the specified tags on the textItem.`]}),`\n`,_jsx(Heading,{level:`2`,id:`december-9-2025`,children:`December 9, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-41`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Clarified expected behavior with variant and status filtering for `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) API endpoint.\nVariants that match the variant filter should only be returned if they match the status filter and their base text also matches the status filter.`]}),`\n`,_jsxs(_components.p,{children:[`Added query param in `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`) API endpoint status filter that allows for filtering components by status.\nVariants that match the variant filter should only be returned if they match the status filter and their base text also matches the status filter.`]}),`\n`,_jsx(Heading,{level:`2`,id:`december-5-2025`,children:`December 5, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-42`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`Fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) API endpoint status filter that allows for fetching textItems by status.`]}),`\n`,_jsxs(_components.p,{children:[`Relax requirement in `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items`,children:`Update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`) API endpoints that requires all textItems to be in the same project.\nNow updates can include textItems that span multiple projects and all will be updated.`]}),`\n`,_jsx(Heading,{level:`3`,id:`documentation-2`,children:`Documentation`}),`\n`,_jsxs(_components.p,{children:[`Fix env var naming used in the cli for setting the ditto api token to the correct value `,_jsx(_components.code,{children:`DITTO_TOKEN`})]}),`\n`,_jsx(Heading,{level:`2`,id:`november-5-2025`,children:`November 5, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-43`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/delete-text-items`,children:`delete text items`}),` (`,_jsx(_components.code,{children:`DELETE /v2/textItems`}),`) API endpoint for deleting text items.`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-6-2025`,children:`October 6, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-github-action-1-0-2`,children:`Ditto Github Action - 1.0.2`}),`\n`,_jsxs(_components.p,{children:[`Updates the Github Action to work with CLI `,_jsx(_components.code,{children:`v5.x`}),`, compatible with both new and legacy Ditto. After upgrading, the Github Action will fetch from new Ditto projects/components by default.`]}),`\n`,_jsxs(_components.p,{children:[`Legacy users will need to add `,_jsx(_components.code,{children:`pull-from-legacy: \"true\"`}),` to their workflow file to continue fetching legacy text.`]}),`\n`,_jsxs(_components.p,{children:[`If you wish to use this action for both new and legacy Ditto, simply create separate steps with different inputs. See the `,_jsx(_components.a,{href:`https://github.com/marketplace/actions/ditto-github-action`,children:`README`}),` for more details and examples.`]}),`\n`,_jsx(_components.p,{children:`Release notes:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/ditto-github-action/releases/tag/v1.0.2`,children:`1.0.2`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/ditto-github-action/releases/tag/v1.0.1`,children:`1.0.1`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/ditto-github-action/releases/tag/v1.0.0`,children:`1.0.0`})}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-1-0`,children:`Ditto CLI - 5.1.0`}),`\n`,_jsxs(_components.p,{children:[`A small update to support the `,_jsx(_components.code,{children:`-m`}),` and `,_jsx(_components.code,{children:`--meta`}),` flags in commands. This is used internally for analytics and should not affect customer workflows.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.1.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-1-2025`,children:`October 1, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-0-0`,children:`Ditto CLI - 5.0.0`}),`\n`,_jsx(_components.p,{children:`First official stable release that provides support for fetching project text and components from the new Ditto experience, including all features from the v5 Beta release (through 5.0.0-beta.8).`}),`\n`,_jsxs(_components.p,{children:[`This version maintains full support for fetching from legacy projects and components. Simply include the `,_jsx(_components.code,{children:`--legacy`}),` flag along with any command from `,_jsx(_components.code,{children:`v4.x`}),`. Users with both new and legacy projects may pull data from both places into the same codebase by maintaining two separate config files and output directories, and including the path to the right config file in your pull command.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-29-2025`,children:`September 29, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-44`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/components/get-components`,children:`fetch components`}),` (`,_jsx(_components.code,{children:`GET /v2/components`}),`) API endpoint for fetching components in the user’s workspace.`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-0-0-beta-8`,children:`Ditto CLI - 5.0.0-beta.8`}),`\n`,_jsxs(_components.p,{children:[`Added support for fetching components in addition to project text via the CLI. Include `,_jsx(_components.code,{children:`components`}),` in your config file to fetch components from the specified folders. Include `,_jsx(_components.code,{children:`projects`}),` in your config file to fetch text from the specified projects.`]}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Breaking change:`}),` If `,_jsx(_components.code,{children:`projects`}),` or `,_jsx(_components.code,{children:`components`}),` are omitted from the config file, will not fetch text from that area. Previously, if `,_jsx(_components.code,{children:`projects`}),` was omitted, it would fetch text from all projects.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.8`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-11-2025`,children:`September 11, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-45`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Added the ability to create variants from `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items#body-force-variant-creation`,children:`update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`) API endpoint with the `,_jsx(_components.code,{children:`forceVariantCreation`}),` parameter.`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-18-2025`,children:`August 18, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-0-0-beta-7`,children:`Ditto CLI - 5.0.0-beta.7`}),`\n`,_jsxs(_components.p,{children:[`Added support for fetching and outputting rich text (HTML) content for Ditto text, by adding `,_jsx(_components.code,{children:`richText: html`}),` to the config file.`]}),`\n`,_jsxs(_components.p,{children:[`At this time, this version is still in Beta, accessible via `,_jsx(_components.code,{children:`@dittowords/cli@beta`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.7`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-24-2025`,children:`July 24, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-46`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/create-text-items`,children:`create text items`}),` (`,_jsx(_components.code,{children:`POST /v2/textItems`}),`) API endpoint for creating new text items.`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-8-2025`,children:`July 8, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-47`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/update-text-items`,children:`update text items`}),` (`,_jsx(_components.code,{children:`PUT /v2/textItems`}),`) API endpoint for editing existing text items.`]}),`\n`,_jsx(Heading,{level:`2`,id:`april-30-2025`,children:`April 30, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5-0-0-beta-6`,children:`Ditto CLI - 5.0.0-beta.6`}),`\n`,_jsxs(_components.p,{children:[`Beta release of CLI for Ditto 2.0. This version supports fetching text from new, non-legacy Ditto projects. It requires a new format for the config file and supports returning json files formatted for i18next. This version is still in beta, and can be accessed via `,_jsx(_components.code,{children:`@dittowords/cli@beta`}),`. Supports all legacy features via `,_jsx(_components.code,{children:`--legacy`}),` flag.`]}),`\n`,_jsx(_components.p,{children:`Release notes:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.6`,children:`5.0.0-beta.6`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.5`,children:`5.0.0-beta.5`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.4`,children:`5.0.0-beta.4`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.3`,children:`5.0.0-beta.3`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.2`,children:`5.0.0-beta.2`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.1`,children:`5.0.0-beta.1`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v5.0.0-beta.0`,children:`5.0.0-beta.0`})}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-28-2025`,children:`March 28, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-48`,children:`API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/legacy/api-reference-legacy/project-folders/fetch-project-folders`,children:`fetch project folders`}),` (`,_jsx(_components.code,{children:`GET /v1/project-folders`}),`) API endpoint for fetching project folders in the user’s workspace.`]}),`\n`,_jsxs(_components.li,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/legacy/api-reference-legacy/project-folders/fetch-projects-by-project-folder-id`,children:`fetch projects by project folder id`}),` (`,_jsx(_components.code,{children:`GET /v1/project-folders/:folder_id/projects`}),`) API endpoint for fetching projects in the specified folder.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-24-2025`,children:`March 24, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-49`,children:`API`}),`\n`,_jsx(_components.p,{children:`Added the first set of v2 endpoints to the API:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/projects/get-projects`,children:`fetch projects`}),` (`,_jsx(_components.code,{children:`GET /v2/projects`}),`) API endpoint for fetching projects in the user’s workspace.`]}),`\n`,_jsxs(_components.li,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-items/get-text-items`,children:`fetch text items`}),` (`,_jsx(_components.code,{children:`GET /v2/textItems`}),`) API endpoint for fetching text items in the user’s workspace.`]}),`\n`,_jsxs(_components.li,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variables/get-variables`,children:`fetch variables`}),` (`,_jsx(_components.code,{children:`GET /v2/variables`}),`) API endpoint for fetching variables in the user’s workspace.`]}),`\n`,_jsxs(_components.li,{children:[`Added `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/variants/get-variants`,children:`fetch variants`}),` (`,_jsx(_components.code,{children:`GET /v2/variants`}),`) API endpoint for fetching variants in the user’s workspace.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-3-2025`,children:`February 3, 2025`}),`\n`,_jsx(Heading,{level:`3`,id:`api-50`,children:`API`}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.a,{href:`https://developer.dittowords.com/legacy/api-reference-legacy/components/fetch-component-text`,children:`fetch component text`}),` (`,_jsx(_components.code,{children:`GET /v1/components`}),`) API endpoint now supports the `,_jsx(_components.code,{children:`includeTimeData`}),` query parameter.`]}),`\n`,_jsxs(_components.p,{children:[`When `,_jsx(_components.code,{children:`includeTimeData`}),` is set to `,_jsx(_components.code,{children:`true`}),`, the response will include the `,_jsx(_components.code,{children:`createdAt`}),` and `,_jsx(_components.code,{children:`updatedAt`}),` fields for each component. This feature is only available when the `,_jsx(_components.code,{children:`structured`}),` format is used.`]}),`\n`,_jsx(Heading,{level:`2`,id:`november-11-2024`,children:`November 11, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-1-6-3`,children:`Ditto React - 1.6.3`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Dependency upgrades`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.6.3`,children:`here`})]}),`\n`,_jsx(Heading,{level:`2`,id:`may-21-2024`,children:`May 21, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-5-2`,children:`Ditto CLI - 4.5.2`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Fix to include header distinguishing Ditto CLI requests from direct API requests.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.5.2`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-7-2024`,children:`May 7, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-5-1`,children:`Ditto CLI - 4.5.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Fix issue with error logs not being flushed before exiting the CLI`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.5.1`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-3-2024`,children:`May 3, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-github-action-0-3-0`,children:`Ditto Github Action - 0.3.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`add optional name input parameter pr-title-prefix to distinguish prs with multi config setups`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v0.3.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-2-2024`,children:`May 2, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`api-/-web-app`,children:`API / Web App`}),`\n`,_jsxs(_components.p,{children:[`Pluralization is now supported for all JSON formats when importing components via the Ditto web app or the `,_jsx(_components.a,{href:`https://developer.dittowords.com/legacy/api-reference-legacy/components/fetch-component-text`,children:`Fetch component text`}),` API endpoint.`]}),`\n`,_jsx(_components.p,{children:`Example import data:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"fruit\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"You have fruit in your cart.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"fruit_one\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"You have one fruit in your cart.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"fruit_other\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"You have some fruit in your cart.\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`april-16-2024`,children:`April 16, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`cli`,children:`CLI`}),`\n`,_jsxs(_components.p,{children:[`v4.5.0 released to add support for a new option which disables the generation of `,_jsx(_components.code,{children:`index.js`}),` and `,_jsx(_components.code,{children:`index.d.ts`}),` files when working with JSON formats.`]}),`\n`,_jsxs(_components.p,{children:[`See the release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.5.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-22-2024`,children:`March 22, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`cli-2`,children:`CLI`}),`\n`,_jsx(_components.p,{children:`v4.4.1 released to fix periodic hanging from attempting to exit the CLI process using Ctrl + C.`}),`\n`,_jsxs(_components.p,{children:[`See full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.4.1`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-15-2024`,children:`March 15, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`documentation-3`,children:`Documentation`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Small fixes and wording clarifications on the `,_jsx(_components.a,{href:`/legacy/legacy-tools`,children:`SDKs`}),` page`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-13-2024`,children:`March 13, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-1-6-1`,children:`Ditto React - 1.6.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Fix crash when rich text is enabled`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See release notes: `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.6.1`,children:`https://github.com/dittowords/ditto-react/releases/tag/v1.6.1`})]}),`\n`,_jsx(Heading,{level:`2`,id:`february-29-2024`,children:`February 29, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-4-0`,children:`Ditto CLI - 4.4.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Add `,_jsx(_components.code,{children:`pull`}),` —sample-data flag for variants`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See release notes: `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.4.0`,children:`https://github.com/dittowords/cli/releases/tag/v4.4.0`})]}),`\n`,_jsx(Heading,{level:`2`,id:`february-27-2024`,children:`February 27, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`/v1/variants`}),` now supports the `,_jsx(_components.code,{children:`showSampleData`}),` query parameter`]}),`\n`,_jsxs(_components.li,{children:[`Fix `,_jsx(_components.code,{children:`/v1/variants`}),` for `,_jsx(_components.code,{children:`projectIds`}),` query parameter`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-19-2024`,children:`February 19, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-3-0`,children:`Ditto CLI - 4.3.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`nested`}),` format is now supported`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See release notes: `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.3.0`,children:`https://github.com/dittowords/cli/releases/tag/v4.3.0`})]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-2-3`,children:`Ditto CLI - 4.2.3`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Upgrades to several dependencies`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See release notes: `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.2.3`,children:`https://github.com/dittowords/cli/releases/tag/v4.2.3`})]}),`\n`,_jsx(Heading,{level:`2`,id:`january-22-2024`,children:`January 22, 2024`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-2-2`,children:`Ditto CLI - 4.2.2`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Stop component folders with emojis from creating a leading separator`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See release notes: `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.2.2`,children:`https://github.com/dittowords/cli/releases/tag/v4.2.2`})]}),`\n`,_jsx(Heading,{level:`2`,id:`december-12-2023`,children:`December 12, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-2`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`The `,_jsx(_components.code,{children:`/components/file`}),` `,_jsx(_components.a,{href:`https://developer.dittowords.com/legacy/api-reference-legacy/components/import-components-via-a-file`,children:`endpoint`}),`\nnow supports a `,_jsx(_components.code,{children:`folderId`}),` query parameter. You can supply the Developer ID of one of\nyour component folders, and all the components will be imported to that folder.`]}),`\n`,_jsx(Heading,{level:`2`,id:`december-7-2023`,children:`December 7, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react`,children:`Ditto React`}),`\n`,_jsx(_components.p,{children:`v1.3.2 released to fix a bug that incorrectly tracked the “Searching” location.`}),`\n`,_jsx(Heading,{level:`2`,id:`november-28-2023`,children:`November 28, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-2-1`,children:`Ditto CLI - 4.2.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Only run init() on commands that need it in `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/pull/89`,children:`https://github.com/dittowords/cli/pull/89`})]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`This change prevents the `,_jsx(_components.code,{children:`ditto`}),` directory from being created on commands that don’t need it (e.g. `,_jsx(_components.code,{children:`generate-suggestions`}),`)`]}),`\n`,_jsxs(_components.p,{children:[`See release notes: `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.2.1`,children:`https://github.com/dittowords/cli/releases/tag/v4.2.1`})]}),`\n`,_jsx(Heading,{level:`2`,id:`november-16-2023`,children:`November 16, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4-2-0`,children:`Ditto CLI - 4.2.0`}),`\n`,_jsxs(_components.p,{children:[`Add `,_jsx(_components.code,{children:`--sample-data`}),` flag to the `,_jsx(_components.code,{children:`components-folders`}),` command in `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/pull/88`,children:`https://github.com/dittowords/cli/pull/88`})]}),`\n`,_jsxs(_components.p,{children:[`See release notes: `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.2.0`,children:`https://github.com/dittowords/cli/releases/tag/v4.2.0`})]}),`\n`,_jsx(Heading,{level:`2`,id:`november-2-2023`,children:`November 2, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-2`,children:`Ditto React`}),`\n`,_jsxs(_components.p,{children:[`Ditto text items with rich text can now be rendered natively by passing the `,_jsx(_components.code,{children:`richText`}),` property on either `,_jsx(_components.code,{children:`Ditto`}),` or `,_jsx(_components.code,{children:`DittoText`}),`.`]}),`\n`,_jsx(_components.p,{children:`This expands rich text support from v1.5.0 which introduced support for rich text on components.`}),`\n`,_jsx(_components.p,{children:`Example:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`jsx`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`jsx`,children:_jsxs(_components.code,{language:`jsx`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:`\u003c`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#4EC9B0`},children:`Ditto`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:` textId`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"text_61e7238bbae5dc00fb66de15\"`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:` variables`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`{`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{ `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`itemCount:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 5`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`}`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:` richText`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#808080`},children:` />`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`october-30-2023`,children:`October 30, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-4-1-0`,children:`Ditto CLI — 4.1.0`}),`\n`,_jsx(_components.p,{children:`This release includes features designed to tighten integration for a variety of environments, including iOS, TypeScript, and more.`}),`\n`,_jsxs(_components.p,{children:[`See the release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.1.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`new-example-apps`,children:`New example apps`}),`\n`,_jsx(_components.p,{children:`We’ve released new versions of our example applications, which have been updated to include the latest in recommended practices for integrating Ditto into development.`}),`\n`,_jsxs(_components.p,{children:[`See the full list `,_jsx(_components.a,{href:`/example-apps#repositories`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-29-2023`,children:`September 29, 2023`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.a,{href:`/additional-tools/webhooks`,children:`Ditto Webhooks`}),` have been released!`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-29-2023`,children:`August 29, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-3`,children:`Ditto React`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Ditto components with rich text can now be rendered natively by passing the richText property on either Ditto or DittoComponent.`}),`\n`,_jsxs(_components.li,{children:[`Example: `,_jsx(_components.code,{children:`\u003cDitto componentId=\"shopping-cart\" richText />`})]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-18-2023`,children:`August 18, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-3`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Endpoints for fetching project text now support an `,_jsx(_components.code,{children:`exclude_components`}),` query parameter.`]}),`\n`,_jsxs(_components.li,{children:[`When `,_jsx(_components.code,{children:`exclude_components=true`}),`, only text items not associated with Ditto components will be returned from a given endpoint.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`We’ve released a new major version (v4) of the CLI. See the release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v4.0.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`august-15-2023`,children:`August 15, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-4`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`The behavior of variables when exporting to mobile formats (`,_jsx(_components.code,{children:`.strings`}),`, `,_jsx(_components.code,{children:`.stringsdict`}),`, and `,_jsx(_components.code,{children:`.xml`}),`) has changed.`]}),`\n`,_jsx(_components.p,{children:`Variables will now maintain a consistent ordering across base text, variant text, and plural forms; they’re assigned an index according to the order of usage (starting with base text, and then variants), and that index is maintained through variant exports.`}),`\n`,_jsx(_components.p,{children:`For example, consider the following text:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`17`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`17`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Base Text`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`{username`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}}, your role is {`}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`{role`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}}.`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Variant Text`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`Tú papel es {`}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`{role`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}}, {`}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`{username`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}}.`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`Previously, exports for the base text and variant text would cause format specifier indices to be reversed for the variables:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`/* base-example.strings */`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` = `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"%1$@, your role is %2$@.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`/* spanish-example.strings */`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` = `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Tú papel es %1$@, %2$@.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`To facilitate ease of integration into development, exports for variant text will now ensure that the format specifier indices match those in the base text:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`/* base-example.strings */`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` = `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"%1$@, your role is %2$@.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`/* spanish-example.strings */`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` = `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Tú papel es %2$@, %1$@.\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`august-7-2023`,children:`August 7, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-5`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Support has been added for an `,_jsx(_components.code,{children:`exclude_components`}),` query parameter to the endpoint.`]}),`\n`,_jsxs(_components.li,{children:[`When set to `,_jsx(_components.code,{children:`true`}),`, only text items not associated with components will be returned from the endpoint.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-2`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Small bug fix to ensure files aren’t written to disk for empty API responses.`}),`\n`,_jsxs(_components.li,{children:[`For more information, please refer to the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v3.10.1`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-26-2023`,children:`July 26, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-6`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`When exporting data for variants, variant metadata (name and description) is now included.`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`In the JSON formats, two new meta keys are added at the top level: `,_jsx(_components.code,{children:`variant_name`}),` and `,_jsx(_components.code,{children:`variant-description`})]}),`\n`,_jsxs(_components.li,{children:[`In the Android `,_jsx(_components.code,{children:`.xml`}),`, iOS `,_jsx(_components.code,{children:`.strings`}),`, and iOS `,_jsx(_components.code,{children:`.stringsdict`}),` formats, a comment is added for each field at the top of the file`]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`july-17-2023`,children:`July 17, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-7`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The `,_jsx(_components.code,{children:`flat`}),` format now supports rich text.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-27-2023`,children:`June 27, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-3`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Added support for specifying a list of formats in the format configuration property.`}),`\n`,_jsxs(_components.li,{children:[`For more information, please refer to the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-26-2023`,children:`June 26, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-4`,children:`Ditto React`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`v1.4.1`}),` fixes a bug introduced in `,_jsx(_components.code,{children:`v1.4.0`}),` which caused variables to ignore passed values.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-14-2023`,children:`June 14, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-4`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Added the `,_jsx(_components.code,{children:`import-components`}),` command which enables component imports via a file through the CLI. For information about the command please refer to the `,_jsx(_components.a,{href:`https://github.com/dittowords/cli#import-components`,children:`documentation`}),` in the README.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-12-2023`,children:`June 12, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-8`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`We’ve added the new `,_jsx(_components.code,{children:`POST /components/file`}),` endpoint to enable uploading components through the API.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-8-2023`,children:`June 8, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`vscode-extension`,children:`VSCode Extension`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Add the ability to only match on components from a component folder. Must be used with `,_jsx(_components.code,{children:`v3.8.0`}),` of the Ditto CLI.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-5`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Add `,_jsx(_components.code,{children:`component-folders`}),` command which lists component folders in your workspace. See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v3.8.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-5-2023`,children:`June 5, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-6`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Add the `,_jsx(_components.code,{children:`-cf`}),` (`,_jsx(_components.code,{children:`--component-folder`}),`) flag for `,_jsx(_components.code,{children:`generate-suggestions`}),`. See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v3.7.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-2-2023`,children:`June 2, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-7`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Performance improvements. See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v3.6.1`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-30-2023`,children:`May 30, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-8`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`We’ve added support for specifying the new `,_jsx(_components.code,{children:`ios-stringsdict`}),` format in the CLI configuration. See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v3.6.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-9`,children:`Ditto API`}),`\n`,_jsx(_components.p,{children:`We clarified a small point of confusion with the documentation around the request payload expected for the endpoint.`}),`\n`,_jsx(_components.p,{children:`The JSON payload should include a top-level data property:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`15`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`15`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"data\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"[API ID]\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"[TEXT OF TEXT ITEM (CAN INCLUDE VARIABLES)]\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"notes\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"[NOTES OF TEXT ITEM]\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// optional`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"tags\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [ `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`...`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ], `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// optional: array of strings`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"plurals\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [ `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// optional: array of plural objects`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"text\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"[TEXT OF PLURAL FORM]\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"form\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"[one|two|zero|few|many|other]\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`may-12-2023`,children:`May 12, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-10`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`We’ve added support for the iOS `,_jsx(_components.code,{children:`.stringsdict`}),` format to our API. Read more `,_jsx(_components.a,{href:`https://developer.dittowords.com/legacy/api-reference-legacy/text-formats#ios-.stringsdict-format-ios-stringsdict`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-3-2023`,children:`May 3, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-9`,children:`Ditto CLI`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Adds ICU support`}),`\n`,_jsx(_components.li,{children:`Fixes a bug where pulling would fail on new initializations`}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`https://github.com/dittowords/cli/compare/v3.3.0...v3.5.0`,children:`Full Changelog`})}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-1-2023`,children:`May 1, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`vs-code-extension`,children:`VS Code Extension`}),`\n`,_jsxs(_components.p,{children:[`We’ve create a VS Code extension! Check it out `,_jsx(_components.a,{href:`https://marketplace.visualstudio.com/items?itemName=dittotech.vscode-ditto`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`april-28-2023`,children:`April 28, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-11`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`We’ve added support for an ICU JSON export format to our API. Read more `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-formats#icu-json-format-icu`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`april-26-2023`,children:`April 26, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-10`,children:`Ditto CLI`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`v3.4.0`}),` of the CLI has been published, which adds a `,_jsx(_components.code,{children:`-v`}),`, `,_jsx(_components.code,{children:`--version`}),` flag to output what version of the CLI is being run.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-23-2023`,children:`March 23, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-5`,children:`Ditto React`}),`\n`,_jsxs(_components.p,{children:[`We’ve published `,_jsx(_components.code,{children:`v1.4.0`}),`, which includes explicit support for map and list variables, in addition to miscellaneous cleanup.\nRead about the release `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.4.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-22-2023`,children:`March 22, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-ditto-cli-ditto-react`,children:`Ditto API, Ditto CLI, Ditto React`}),`\n`,_jsxs(_components.p,{children:[`We’ve added a `,_jsx(_components.code,{children:`__type`}),` property to variable output in our structured export format; this enables simple discrimination between different types of variables:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`15`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`15`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"some-variable-1\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"example\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Hello world!\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"__type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"string\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"some-variable-2\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"example\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`100`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"__type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"number\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"some-variable-3\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"text:\"`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"Foo\"`}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"url\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"https://bar.com\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"__type\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"hyperlink\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`march-21-2023`,children:`March 21, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-12`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`We’ve added support for a `,_jsx(_components.code,{children:`nested`}),` JSON export format to our API. Read more `,_jsx(_components.a,{href:`https://developer.dittowords.com/api-reference/text-formats#nested-json-format-nested`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`march-9-2023`,children:`March 9, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-11`,children:`Ditto CLI`}),`\n`,_jsxs(_components.p,{children:[`We’ve published `,_jsx(_components.code,{children:`v3.0.0`}),` of the CLI, which focuses around a number breaking changes intended to better align default CLI behavior with Ditto best practices.`]}),`\n`,_jsxs(_components.p,{children:[`Read the release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v3.0.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-15-2023`,children:`February 15, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-13`,children:`Ditto API`}),`\n`,_jsx(_components.p,{children:`We’ve released two bug fixes specific to the Android XML export format:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`index values for format specifiers will now be relative to a text item’s base value AND its plurals, instead of resetting for each plural form (`,_jsx(_components.a,{href:`https://github.com/dittowords/cli/issues/48`,children:`issue`}),`)`]}),`\n`,_jsxs(_components.li,{children:[`extra whitespace is no longer added between text and variables in the final output (`,_jsx(_components.a,{href:`https://github.com/dittowords/cli/issues/49`,children:`issue`}),`)`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-14-2023`,children:`February 14, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-14`,children:`Ditto API`}),`\n`,_jsx(_components.p,{children:`We’ve released a new version of our API that includes some breaking changes. The old API endpoints are deprecated, and existing users should migrate to the new endpoints at their earliest convenience.`}),`\n`,_jsx(Heading,{level:`2`,id:`february-6-2023`,children:`February 6, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-web-app`,children:`Ditto Web App`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Removed the deprecated the full format from the export modals on the project page and in the component library`}),`\n`,_jsx(_components.li,{children:`Set the flat format to be the default export format in the web app`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-3-2023`,children:`February 3, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-15`,children:`Ditto API`}),`\n`,_jsx(_components.p,{children:`Minor documentation update to add and emphasize a deprecation notice for the full format.`}),`\n`,_jsx(Heading,{level:`2`,id:`february-1-2023`,children:`February 1, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-1-3-0`,children:`Ditto React — 1.3.0`}),`\n`,_jsxs(_components.p,{children:[`Added support for using variables in conjunction with the flat format. See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.3.0`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`january-25-2023`,children:`January 25, 2023`}),`\n`,_jsx(_components.p,{children:`We added support to the web app for importing components from two new file formats:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Android localization files (.xml)`}),`\n`,_jsx(_components.li,{children:`iOS localization files (.strings)`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Read more `,_jsx(_components.a,{href:`https://dittov3.notion.site/Importing-JSON-iOS-Android-Files-256cc8865c7a80fe94cdf135631bf8c6`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`january-19-2023`,children:`January 19, 2023`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-1-2-1`,children:`Ditto React — 1.2.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Updated README to clarify that the flat format does not currently support variables.`}),`\n`,_jsx(_components.li,{children:`Fixed a bug preventing falsy values (namely 0 and \"\") from being properly interpolated.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.2.1`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`december-15-2022`,children:`December 15, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-12`,children:`Ditto CLI`}),`\n`,_jsxs(_components.p,{children:[`Added rich text support. See more info `,_jsx(_components.a,{href:`https://github.com/dittowords/cli#richtext`,children:`here`})]}),`\n`,_jsx(Heading,{level:`2`,id:`december-13-2022`,children:`December 13, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-16`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`Added the `,_jsx(_components.code,{children:`includeRichText`}),` flag to the following endpoints (format must be full or structured):`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`/projects`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`/projects/:id`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`/projects/:id/components`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`/components`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`/component-folders/:api*id/components`})}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`november-30-2022`,children:`November 30, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-13`,children:`Ditto CLI`}),`\n`,_jsxs(_components.p,{children:[`Added the `,_jsx(_components.code,{children:`status`}),` filter as a configuration variable. To filter the fetched text by its status, you can now use the `,_jsx(_components.code,{children:`status`}),` parameter in your `,_jsx(_components.code,{children:`config.yml`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`november-29-2022`,children:`November 29, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-14`,children:`Ditto CLI`}),`\n`,_jsxs(_components.p,{children:[`Added `,_jsx(_components.code,{children:`android`}),` and `,_jsx(_components.code,{children:`ios-strings`}),` as available formats. To use these formats, specify them under the format paramter in your `,_jsx(_components.code,{children:`config.yml`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`november-10-2022`,children:`November 10, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-17`,children:`Ditto API`}),`\n`,_jsx(_components.p,{children:`Fixed a typo in an example in the documentation containing an incorrect usage of the curl command.`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-15`,children:`Ditto CLI`}),`\n`,_jsx(_components.p,{children:`Added information to the README about two supported environment variables:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`DITTO_CONFIG_FILE:`}),` used to specify an alternate file location for the CLI to read authentication information from. The default path is `,_jsx(_components.code,{children:`$HOME/.config/ditto`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`DITTO_TEXT_DIR`}),`: used to specify an alternate folder location for the CLI to write its output files to. The default path is `,_jsx(_components.code,{children:`./ditto`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`oct-11-2022`,children:`Oct 11, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-18`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Added new endpoint: Fetch component folders`}),`\n`,_jsx(_components.li,{children:`Added new endpoint: Fetch components by component folder`}),`\n`,_jsx(_components.li,{children:`Added sub-headings to divide the endpoints by the entity they’re associated with, and implemented minor miscellaneous cleanup across the endpoint documentation`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`sep-23-2022`,children:`Sep 23, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-19`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`Text items with plural values will have those plural values included in flat exports as individual key/value pairs; pluralized keys are structured like `,_jsx(_components.code,{children:`[TEXT ID]_[PLURAL FORM]`}),`. See the `,_jsx(_components.a,{href:`/string-formats/json#flat-json`,children:`flat format documentation`}),` for more details.\nFixed a bug where the status field failed to properly filter returned data when specified in conjunction with the `,_jsx(_components.code,{children:`android`}),` or `,_jsx(_components.code,{children:`ios-strings`}),` formats.`]}),`\n`,_jsx(Heading,{level:`2`,id:`sep-19-2022`,children:`Sep 19, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-1-2-0`,children:`Ditto React — 1.2.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`We exported two hooks that can be used for accessing synced data: `,_jsx(_components.code,{children:`useDittoSingleText`}),` and `,_jsx(_components.code,{children:`useDittoComponent`}),`. These hooks are experimental and will likely undergo API changes in the future.`]}),`\n`,_jsxs(_components.li,{children:[`See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.2.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-20`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Added the `,_jsx(_components.code,{children:`status`}),` field to data returned from the `,_jsx(_components.code,{children:`/components`}),` and `,_jsx(_components.code,{children:`/projects/:id/components`}),` endpoints.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`jun-30-2022`,children:`Jun 30, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-21`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Added support for including variables in payloads sent to the `,_jsx(_components.code,{children:`PUT /components`}),` endpoint.`]}),`\n`,_jsxs(_components.li,{children:[`Fixed an issue with Android \u0026 iOS export formats not escaping special characters: `,_jsx(_components.code,{children:`\\\\n`}),`, `,_jsx(_components.code,{children:`\\\\t`}),`, `,_jsx(_components.code,{children:`@`}),`, `,_jsx(_components.code,{children:`?`}),`, `,_jsx(_components.code,{children:`'`}),`, and `,_jsx(_components.code,{children:`\"`}),` characters are now properly escaped.`]}),`\n`,_jsxs(_components.li,{children:[`Added missing `,_jsx(_components.code,{children:`xliff`}),` namespace to exported Android `,_jsx(_components.code,{children:`.xml`}),` files.\n= Fixed a bug with Android `,_jsx(_components.code,{children:`.xml`}),` exports that occurred with text items with API IDs that include the `,_jsx(_components.code,{children:`-`}),` character. Now, all `,_jsx(_components.code,{children:`-`}),` characters are replaced with `,_jsx(_components.code,{children:`\\\\_`}),` characters in the name property of `,_jsx(_components.code,{children:`\u003cstring>`}),` and `,_jsx(_components.code,{children:`\u003cplural>`}),` tags, and a `,_jsx(_components.code,{children:`ditto_api_id`}),` property has been added to string and plural tags to serve as a reference to the original API ID.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-2-5-1`,children:`Ditto CLI — 2.5.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Fixed a bug when using the `,_jsx(_components.code,{children:`project add`}),` / `,_jsx(_components.code,{children:`project remove`}),` commands and selecting the component library caused incorrect modifications to be made to the CLI’s configuration file.`]}),`\n`,_jsxs(_components.li,{children:[`See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v2.5.1`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-example-projects`,children:`Ditto Example Projects`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Added new iOS Example Project showcasing how to use exported .strings files.`}),`\n`,_jsx(_components.li,{children:`Added new Android Example Project showcasing how to use exported .xml string files.`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See `,_jsx(_components.a,{href:`/example-apps`,children:`Example Projects`}),` for more details.`]}),`\n`,_jsx(Heading,{level:`2`,id:`jun-13-2022`,children:`Jun 13, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-github-action-—-0-2-0`,children:`Ditto GitHub Action — 0.2.0`}),`\n`,_jsxs(_components.p,{children:[`Added an optional `,_jsx(_components.code,{children:`ditto-dir`}),` input parameter for projects that do not have the ditto directory in the root of the repository`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-7-2022`,children:`June 7, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-22`,children:`Ditto API`}),`\n`,_jsxs(_components.p,{children:[`Added support for upserting plurals via the `,_jsx(_components.code,{children:`PUT /components`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`See our `,_jsx(_components.a,{href:`/api-reference/authentication`,children:`API documentation`}),` for more details.`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-1-2022`,children:`June 1, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-23`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Added early support for exporting text data to Android and iOS Strings formats. All endpoints that support a `,_jsx(_components.code,{children:`format`}),` query parameter can now accept values of `,_jsx(_components.code,{children:`android`}),` or `,_jsx(_components.code,{children:`ios-strings`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Added `,_jsx(_components.code,{children:`GET /variables`}),` endpoint that returns the variables in the workspace of the requesting user.`]}),`\n`,_jsxs(_components.li,{children:[`Added the ability to filter by text item status by passing a status query parameter in API requests. Supported by the following endpoints:`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`GET /projects`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`GET /projects/:id`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`GET /projects/:id/components`})}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /components`}),`\nSee our `,_jsx(_components.a,{href:`/api-reference/authentication`,children:`API documentation`}),` for more details.`]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-23-2022`,children:`May 23, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-2-5-0`,children:`Ditto CLI — 2.5.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Added meta option flag in support of the Ditto GitHub Action release. See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v2.5.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-github-action-—-0-1-0`,children:`Ditto GitHub Action — 0.1.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`v0.1.0 released! Check it out `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-github-action`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-16-2022`,children:`May 16, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-2-4-0`,children:`Ditto CLI — 2.4.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Update some user-facing CLI messages to accurately reflect our new subdomain: app.dittowords.com (instead of the old beta.dittowords.com). See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v2.4.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`may-10-2022`,children:`May 10, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-2-3-0`,children:`Ditto CLI — 2.3.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Allows users to override the output directory via a new environment variable `,_jsx(_components.code,{children:`DITTO_TEXT_DIR`})]}),`\n`,_jsxs(_components.li,{children:[`When no projects are found in the `,_jsx(_components.code,{children:`config.yml`}),` file an additional help message displays about verifying that the projects have developer mode enabled`]}),`\n`,_jsxs(_components.li,{children:[`See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v2.3.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-28-2022`,children:`February 28, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-24`,children:`Ditto API`}),`\n`,_jsx(_components.p,{children:`Added better error handling for the niche edge case where an API request is made using the token of a user that has been removed from their workspace.`}),`\n`,_jsx(Heading,{level:`2`,id:`january-20-2022`,children:`January 20, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-1-1-1`,children:`Ditto React — 1.1.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Our React SDK now supports variable interpolation by passing in values through the variables prop.`}),`\n`,_jsxs(_components.li,{children:[`Our React SDK now supports displaying plural forms through the count prop.\nFor more information about using variable interpolations and pluralization through our React SDK, check out our `,_jsx(_components.a,{href:`/legacy/legacy-tools`,children:`SDK documentation`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-2-2-0`,children:`Ditto CLI — 2.2.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`The CLI now supports reading API keys from an environment variable (`,_jsx(_components.code,{children:`DITTO_API_KEY`}),`).`]}),`\n`,_jsxs(_components.li,{children:[`See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v2.2.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`january-11-2022`,children:`January 11, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-16`,children:`Ditto CLI`}),`\n`,_jsx(_components.p,{children:`We deployed a bugfix release to fix issues introduced in the latest minor version of the package:`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`the pull command no longer crashes when projects other than the component library are specified in `,_jsx(_components.code,{children:`config.yml`})]}),`\n`,_jsx(_components.li,{children:`resolves a casing issue in the project add command that was causing it to crash`}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/v2.1.2`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`january-6-2022`,children:`January 6, 2022`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-17`,children:`Ditto CLI`}),`\n`,_jsxs(_components.p,{children:[`We’ve added a new supported property to `,_jsx(_components.code,{children:`ditto/config.yml`}),` to allow explicitly specifying that the component library should be fetched and included in the CLI’s output:\n`,_jsx(_components.code,{children:`components: true`})]}),`\n`,_jsx(_components.p,{children:`This is now the preferred alternative to the old way of specifying the component library:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`3`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`3`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`projects`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` name`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`Ditto Component Library`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` id`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`ditto_component_library`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Our goal with this change is to make the CLI easier to use and understand by aligning it with the way things work in the Ditto web app, where the component library is fundamentally different from the projects in a workspace.`}),`\n`,_jsxs(_components.p,{children:[`See the release `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v2.1.1`,children:`here`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`december-8-2021`,children:`December 8, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-25`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/:id/components`}),` can now be used to fetch the components used in a project`]}),`\n`,_jsxs(_components.li,{children:[`Return format matches the `,_jsx(_components.code,{children:`GET /components`}),` endpoint`]}),`\n`,_jsxs(_components.li,{children:[`Supports `,_jsx(_components.code,{children:`format`}),` and `,_jsx(_components.code,{children:`variant`}),` parameters (the same as the `,_jsx(_components.code,{children:`/projects`}),`, `,_jsx(_components.code,{children:`/project/:id`}),`, and `,_jsx(_components.code,{children:`/components`}),` endpoints)`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`november-29-2021`,children:`November 29, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-26`,children:`Ditto API`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /components`}),` can now be used to fetch the components in a workspace`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Supports format and variant parameters (the same as the `,_jsx(_components.code,{children:`/projects`}),` and `,_jsx(_components.code,{children:`/project/:id`}),` endpoints)`]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/ditto_component_library`}),` has been deprecated; the endpoint is still available, but references to it have been removed from the documentation.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`PUT /components`}),` can now be used to update the text of components in a workspace`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Currently only supports updating variant text via the variant query parameter (an error will be thrown if not specified)`}),`\n`,_jsx(_components.li,{children:`Currently only available to teams on Team or Enterprise plans`}),`\n`,_jsxs(_components.li,{children:[`Data is specified on data key in request body and must be in one of our `,_jsx(_components.a,{href:`https://dittov3.notion.site/Importing-JSON-iOS-Android-Files-256cc8865c7a80fe94cdf135631bf8c6`,children:`three supported import formats`})]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`november-11-2021`,children:`November 11, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-2-0-0`,children:`Ditto CLI — 2.0.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Output files are now written to disk in several different ways according to how the CLI is configured; most notably, if the variants option is set and a format of structured or flat is specified, output files will be written on a per-project per-variant basis`}),`\n`,_jsxs(_components.li,{children:[`Data for `,_jsx(_components.code,{children:`structured`}),` and `,_jsx(_components.code,{children:`flat`}),` formats is saved without arbitrary top-level nesting`]}),`\n`,_jsxs(_components.li,{children:[`Files are only written for variants that contain values for the configured projects (no more empty files)\nFor a more in-depth description (with examples) of these changes and others in the release, see the full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/cli/releases/tag/v2.0.0`,children:`here`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-1-0-0`,children:`Ditto React — 1.0.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`ditto-react`}),` now only works with CLI version `,_jsx(_components.code,{children:`2.x.x`}),` — leaning into new CLI improvements allowed us to drastically reduce many areas of complex logical overhead`]}),`\n`,_jsxs(_components.li,{children:[`We made some stabilization improvements to the way that missing/invalid `,_jsx(_components.code,{children:`frameId`}),`, `,_jsx(_components.code,{children:`blockId`}),`, `,_jsx(_components.code,{children:`textId`}),`, or `,_jsx(_components.code,{children:`componentId`}),` values are handled`]}),`\n`,_jsxs(_components.li,{children:[`We implemented significant refactoring in several areas of the project\nFor a more in-depth description of these changes, see the full release notes `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-react/releases/tag/v1.0.0`,children:`here`})]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-demo`,children:`Ditto Demo`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`We added a `,_jsx(_components.a,{href:`https://github.com/dittowords/ditto-demo/tree/react-i18next`,children:`new branch`}),` that showcases how Ditto can be integrated into a project with react-i18next`]}),`\n`,_jsx(_components.li,{children:`We updated dependencies to the latest versions of the Ditto CLI (v2.0.0) and Ditto React (v1.0.0)`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-22-2021`,children:`October 22, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-api-—-2-4-1`,children:`Ditto API — 2.4.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`We fixed a bug with the API (and in-app exports) that included hidden text in `,_jsx(_components.code,{children:`flat`}),` and `,_jsx(_components.code,{children:`structured`}),` JSON exports. Now, hidden text will correctly not be included in these export formats!`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-demo-2`,children:`Ditto Demo`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`We included the files to import into the component library separately from where they’d be synced via the CLI`}),`\n`,_jsx(_components.li,{children:`We included more instructions on linking the demo app with its corresponding design file`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`october-7-2021`,children:`October 7, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`general`,children:`General`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Refactored API documentation to be easier to navigate and communicate critical concepts more clearly`}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-cli-—-1-1-1`,children:`Ditto CLI — 1.1.1`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`When the `,_jsx(_components.code,{children:`pull`}),` command is executed, all `,_jsx(_components.code,{children:`.json`}),` and `,_jsx(_components.code,{children:`.js`}),` files are now removed from the `,_jsx(_components.code,{children:`ditto`}),` folder prior to new data being written\n= Support added for new options in `,_jsx(_components.code,{children:`ditto/config.yml`}),`:`,`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`variants`}),`: `,_jsx(_components.code,{children:`true`}),` or `,_jsx(_components.code,{children:`false`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`If set to true, data will be fetched for both base and variant text and stored in separate JSON files`}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`format`}),`: `,_jsx(_components.code,{children:`flat`}),` or `,_jsx(_components.code,{children:`structured`}),` - If specified, data will be fetched and stored in the specified format\n= Refactored `,_jsx(_components.code,{children:`README`})]}),`\n`]}),`\n`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /variants`}),` will now return names and API IDs for variants in the workspace associated with the requesting user.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-0-0-5`,children:`Ditto React — 0.0.5`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Support added for `,_jsx(_components.code,{children:`flat`}),` and structured formats`]}),`\n`,_jsxs(_components.li,{children:[`Support added for passing a `,_jsx(_components.code,{children:`variant`}),` value to `,_jsx(_components.code,{children:`DittoProvider`})]}),`\n`,_jsx(_components.li,{children:`Bug fixes around support for integrating with workspace component libraries (as opposed to individual projects)`}),`\n`,_jsxs(_components.li,{children:[`Refactored `,_jsx(_components.code,{children:`README`})]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-demo-3`,children:`Ditto Demo`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Refactored `,_jsx(_components.code,{children:`ditto-sdk`}),` usage to integrate with a component library instead of an individual project`]}),`\n`,_jsxs(_components.li,{children:[`Added a language picker to showcase `,_jsx(_components.code,{children:`ditto-react`}),` and `,_jsx(_components.code,{children:`ditto-cli`}),` support for variants`]}),`\n`,_jsxs(_components.li,{children:[`Refactored `,_jsx(_components.code,{children:`README`}),`, including adding instructions for connecting the repo to a component library`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-27-2021`,children:`September 27, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`general-2`,children:`General`}),`\n`,_jsxs(_components.p,{children:[`Fixed incorrect example of `,_jsx(_components.code,{children:`/projects`}),` usage in API Reference. The `,_jsx(_components.code,{children:`projectIds`}),` query parameter should be specified as follows:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Correct: `,_jsx(_components.code,{children:`?projectIds[]=\u003cPROJECT_ID>\u0026projectIds[]=\u003cPROJECT_ID>`})]}),`\n`,_jsxs(_components.li,{children:[`Incorrect: `,_jsx(_components.code,{children:`?projectIds[]=\u003cPROJECT_ID>,\u003cPROJECT_ID>`})]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-—-2-4-0`,children:`API — 2.4.0`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`GET /variants`}),` will now return names and API IDs for variants in the workspace associated with the requesting user.`]}),`\n`,_jsx(Heading,{level:`2`,id:`september-8-2021`,children:`September 8, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`api-—-2-3-0`,children:`API — 2.3.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects`}),` and `,_jsx(_components.code,{children:`GET /projects/:id`}),` now accept an optional query parameter of `,_jsx(_components.code,{children:`variant`}),`; when provided, the data exported will be specific to the variant with an API ID that matches the parameter’s value. For `,_jsx(_components.code,{children:`default`}),` and `,_jsx(_components.code,{children:`structured`}),` formats, the variants key will not be included when the variant parameter is provided.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Example: `,_jsx(_components.code,{children:`/projects/\u003cPROJECT_ID>?variant=xxx-xxx-xxx`})]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/:id`}),` will not include top-level projects and project_xyz keys\nExample request: `,_jsx(_components.code,{children:`GET /projects/123`})]}),`\n`]}),`\n`,_jsx(_components.p,{children:`Example response before change:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{ `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`projects`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`project_123`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`text_item`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Hello World\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`...`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }}}`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Example response after change:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{ `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`text_item`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Hello World\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#82071E`,\"--shiki-light-font-style\":`italic`,\"--shiki-dark\":`#F44747`,\"--shiki-dark-font-style\":`inherit`},children:`...`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`august-11-2021`,children:`August 11, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`api-—-2-2-0`,children:`API — 2.2.0`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`GET /projects`}),` and `,_jsx(_components.code,{children:`GET /projects/:id`}),` now accepts an optional query parameter of `,_jsx(_components.code,{children:`format`}),`, which can be either `,_jsx(_components.code,{children:`flat`}),` or `,_jsx(_components.code,{children:`structured`}),`. If no format is provided, the `,_jsx(_components.code,{children:`full`}),` JSON of the project will be returned with blocks and frames.`]}),`\n`,_jsxs(_components.p,{children:[`Example: `,_jsx(_components.code,{children:`/projects/\u003cPROJECT_ID>?format=flat`})]}),`\n`,_jsx(Heading,{level:`2`,id:`july-28-2021`,children:`July 28, 2021`}),`\n`,_jsxs(_components.p,{children:[`With the recent release of `,_jsx(_components.a,{href:`https://dittov3.notion.site/Variants-for-Components-256cc8865c7a80bb8c44da73209fb0cc`,children:`Variants for Components`}),`, we’ve included them in both exports from our web-app and the JSON response from the API.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-—-2-1-0`,children:`API — 2.1.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/:id`}),` will now return component variants. This applies both for when fetching projects or when fetching the component library (i.e. id = ditto_component_library)`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/:id`}),` will now match the project JSON export from the web-app to include component information (`,_jsx(_components.code,{children:`is_comp`}),` and `,_jsx(_components.code,{children:`component_api_id`}),`) in the text object`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-21-2021`,children:`June 21, 2021`}),`\n`,_jsxs(_components.p,{children:[`We’ve updated our React library and our demo project to work with the multi-project JSON structure that the CLI now saves in `,_jsx(_components.code,{children:`text.json`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-react-—-0-0-4`,children:`Ditto React — 0.0.4`}),`\n`,_jsx(_components.p,{children:`TypeScript bindings are now exported 🎉`}),`\n`,_jsxs(_components.p,{children:[`A new `,_jsx(_components.code,{children:`projectId`}),` prop can be passed to `,_jsx(_components.code,{children:`DittoProvider`}),` or `,_jsx(_components.code,{children:`Ditto`})]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`If passed to `,_jsx(_components.code,{children:`DittoProvider`}),`, all descendant `,_jsx(_components.code,{children:`Ditto`}),` components will default to pulling text from the associated project`]}),`\n`,_jsxs(_components.li,{children:[`If passed to `,_jsx(_components.code,{children:`Ditto`}),`, the component will pull text from the associated project`]}),`\n`,_jsxs(_components.li,{children:[`If passed to both `,_jsx(_components.code,{children:`DittoProvider`}),` and `,_jsx(_components.code,{children:`Ditto`}),`, the value passed to `,_jsx(_components.code,{children:`Ditto`}),` will take precedence`]}),`\n`,_jsxs(_components.li,{children:[`Breaking change: If a `,_jsx(_components.code,{children:`Ditto`}),` component is rendered that is not provided a `,_jsx(_components.code,{children:`projectId`}),` via direct prop or `,_jsx(_components.code,{children:`DittoContext`}),` ancestor, an error will be thrown`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`See more details in the `,_jsx(_components.a,{href:`https://www.npmjs.com/package/ditto-react`,children:`updated documentation`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`ditto-demo-4`,children:`Ditto Demo`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Upgraded `,_jsx(_components.code,{children:`ditto-react`}),` to `,_jsx(_components.code,{children:`v0.0.4`})]}),`\n`,_jsxs(_components.li,{children:[`Updated source to work with new `,_jsx(_components.code,{children:`ditto-react`}),` version by passing `,_jsx(_components.code,{children:`projectId`}),` props to all instances of `,_jsx(_components.code,{children:`DittoContext`})]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`june-7-2021`,children:`June 7, 2021`}),`\n`,_jsx(_components.p,{children:`We’ve updated both our CLI and API to handle multiple projects.`}),`\n`,_jsxs(_components.p,{children:[`Heads up! This results in some breaking changes to the CLI in order for it to list projects, and will change the format of the `,_jsx(_components.code,{children:`text.json`}),` fetched by the CLI. Please upgrade your Ditto CLI via either `,_jsx(_components.code,{children:`npm`}),` or `,_jsx(_components.code,{children:`yarn`}),`.`]}),`\n`,_jsx(Heading,{level:`3`,id:`api-—-2-0-0`,children:`API — 2.0.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /project-names`}),` is the new name of the previous `,_jsx(_components.code,{children:`GET /projects`}),` endpoint. Just as before, this will return the names and IDs of projects in your Ditto workspace with Developer Mode turned on`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/:id`}),` will now return the structured JSON in a format compatible with multiple projects`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects`}),` is a new endpoint that will return the content of multiple projects (specified via the query parameter projectIds) as a single JSON object`]}),`\n`]}),`\n`,_jsx(Heading,{level:`3`,id:`cli-—-1-0-0`,children:`CLI — 1.0.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`We’ve updated the CLI to handle syncing multiple projects in a single directory! This means several things:\n`,_jsx(_components.code,{children:`/ditto/config.yml`}),` now supports multiple projects. `,_jsx(_components.code,{children:`ditto-cli`}),` pull will pull all projects in the current directory’s /`,_jsx(_components.code,{children:`ditto/config.yml`})]}),`\n`,_jsxs(_components.li,{children:[`We’ve added two new commands to add and remove projects from `,_jsx(_components.code,{children:`/ditto/config.yml`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`ditto-cli project add`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.code,{children:`ditto-cli project remove`})}),`\n`,_jsxs(_components.li,{children:[`The regular `,_jsx(_components.code,{children:`ditto-cli project`}),` command will now function as `,_jsx(_components.code,{children:`ditto-cli project add`})]}),`\n`]}),`\n`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`april-1-2021`,children:`April 1, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`api-—-1-1-0`,children:`API — 1.1.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects`}),` now includes the Component Library if Developer Mode is enabled for the Component Library`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/:id`}),` will return the Component Library as a structured JSON if the ID provided is `,_jsx(_components.code,{children:`ditto_component_library`})]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`february-25-2021`,children:`February 25, 2021`}),`\n`,_jsx(Heading,{level:`3`,id:`api-—-1-0-0`,children:`API — 1.0.0`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects`}),` endpoint for fetching Ditto projects from workspace`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /projects/:id`}),` endpoint for fetching content in Ditto project as structured JSON`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Developer changelog","sidebarTitle":"Changelog","description":"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.","href":"/feedback-support/changelog"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"October 30, 2026","slug":"october-30-2026","depth":2,"children":[{"title":"API","slug":"api","depth":3,"children":[]}]},{"title":"October 29, 2026","slug":"october-29-2026","depth":2,"children":[{"title":"Ditto React — 1.6.4","slug":"ditto-react-—-1-6-4","depth":3,"children":[]}]},{"title":"October 21, 2026","slug":"october-21-2026","depth":2,"children":[{"title":"API","slug":"api-2","depth":3,"children":[]},{"title":"MCP","slug":"mcp","depth":3,"children":[]}]},{"title":"October 20, 2026","slug":"october-20-2026","depth":2,"children":[{"title":"Library component versioning","slug":"library-component-versioning","depth":4,"children":[]}]},{"title":"October 19, 2026","slug":"october-19-2026","depth":2,"children":[{"title":"API","slug":"api-3","depth":3,"children":[]},{"title":"MCP","slug":"mcp-2","depth":3,"children":[]},{"title":"Ditto CLI - 5.12.0","slug":"ditto-cli-5-12-0","depth":3,"children":[]}]},{"title":"October 16, 2026","slug":"october-16-2026","depth":2,"children":[{"title":"API","slug":"api-4","depth":3,"children":[]}]},{"title":"October 15, 2026","slug":"october-15-2026","depth":2,"children":[{"title":"API","slug":"api-5","depth":3,"children":[]},{"title":"Filter text items by component","slug":"filter-text-items-by-component","depth":4,"children":[]},{"title":"Readable validation errors","slug":"readable-validation-errors","depth":4,"children":[]}]},{"title":"October 12, 2026","slug":"october-12-2026","depth":2,"children":[{"title":"API","slug":"api-6","depth":3,"children":[]},{"title":"New JSON metadata parameters","slug":"new-json-metadata-parameters","depth":4,"children":[]},{"title":"Empty text is now included in exports","slug":"empty-text-is-now-included-in-exports","depth":4,"children":[]},{"title":"Consistent html and html_paragraphs rich text output","slug":"consistent-html-and-html_paragraphs-rich-text-output","depth":4,"children":[]},{"title":"Variant notes in arb and ios-strings exports","slug":"variant-notes-in-arb-and-ios-strings-exports","depth":4,"children":[]},{"title":"Ditto CLI - 5.11.0","slug":"ditto-cli-5-11-0","depth":3,"children":[]}]},{"title":"October 7, 2026","slug":"october-7-2026","depth":2,"children":[{"title":"API","slug":"api-7","depth":3,"children":[]},{"title":"MCP","slug":"mcp-3","depth":3,"children":[]}]},{"title":"October 5, 2026","slug":"october-5-2026","depth":2,"children":[{"title":"API","slug":"api-8","depth":3,"children":[]}]},{"title":"October 1, 2026","slug":"october-1-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-4","depth":3,"children":[]}]},{"title":"September 17, 2026","slug":"september-17-2026","depth":2,"children":[{"title":"Ditto CLI - 5.10.0","slug":"ditto-cli-5-10-0","depth":3,"children":[]}]},{"title":"September 3, 2026","slug":"september-3-2026","depth":2,"children":[{"title":"API","slug":"api-9","depth":3,"children":[]},{"title":"MCP","slug":"mcp-5","depth":3,"children":[]}]},{"title":"September 2, 2026","slug":"september-2-2026","depth":2,"children":[{"title":"API","slug":"api-10","depth":3,"children":[]},{"title":"MCP","slug":"mcp-6","depth":3,"children":[]}]},{"title":"August 27, 2026","slug":"august-27-2026","depth":2,"children":[{"title":"API","slug":"api-11","depth":3,"children":[]},{"title":"Ditto CLI - 5.9.0","slug":"ditto-cli-5-9-0","depth":3,"children":[]}]},{"title":"August 24, 2026","slug":"august-24-2026","depth":2,"children":[{"title":"Ditto CLI - 5.8.1","slug":"ditto-cli-5-8-1","depth":3,"children":[]}]},{"title":"August 20, 2026","slug":"august-20-2026","depth":2,"children":[{"title":"Ditto CLI - 5.8.0","slug":"ditto-cli-5-8-0","depth":3,"children":[]}]},{"title":"August 18, 2026","slug":"august-18-2026","depth":2,"children":[{"title":"Ditto CLI - 5.7.2","slug":"ditto-cli-5-7-2","depth":3,"children":[]}]},{"title":"August 17, 2026","slug":"august-17-2026","depth":2,"children":[{"title":"API","slug":"api-12","depth":3,"children":[]}]},{"title":"August 13, 2026","slug":"august-13-2026","depth":2,"children":[{"title":"Ditto CLI - 5.7.1","slug":"ditto-cli-5-7-1","depth":3,"children":[]},{"title":"MCP","slug":"mcp-7","depth":3,"children":[]},{"title":"API","slug":"api-13","depth":3,"children":[]}]},{"title":"August 11, 2026","slug":"august-11-2026","depth":2,"children":[{"title":"API","slug":"api-14","depth":3,"children":[]}]},{"title":"August 10, 2026","slug":"august-10-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-8","depth":3,"children":[]},{"title":"API","slug":"api-15","depth":3,"children":[]}]},{"title":"August 6, 2026","slug":"august-6-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-9","depth":3,"children":[]},{"title":"API","slug":"api-16","depth":3,"children":[]}]},{"title":"August 5, 2026","slug":"august-5-2026","depth":2,"children":[{"title":"Ditto CLI - 5.7.0","slug":"ditto-cli-5-7-0","depth":3,"children":[]}]},{"title":"August 3, 2026","slug":"august-3-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-10","depth":3,"children":[]},{"title":"API","slug":"api-17","depth":3,"children":[]}]},{"title":"July 31, 2026","slug":"july-31-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-11","depth":3,"children":[]}]},{"title":"July 29, 2026","slug":"july-29-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-12","depth":3,"children":[]},{"title":"API","slug":"api-18","depth":3,"children":[]}]},{"title":"July 27, 2026","slug":"july-27-2026","depth":2,"children":[{"title":"Ditto CLI - 5.6.3","slug":"ditto-cli-5-6-3","depth":3,"children":[]},{"title":"MCP","slug":"mcp-13","depth":3,"children":[]},{"title":"API","slug":"api-19","depth":3,"children":[]}]},{"title":"July 24, 2026","slug":"july-24-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-14","depth":3,"children":[]}]},{"title":"July 22, 2026","slug":"july-22-2026","depth":2,"children":[{"title":"Documentation","slug":"documentation","depth":3,"children":[]},{"title":"MCP","slug":"mcp-15","depth":3,"children":[]}]},{"title":"July 10, 2026","slug":"july-10-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-16","depth":3,"children":[]}]},{"title":"July 9, 2026","slug":"july-9-2026","depth":2,"children":[{"title":"API","slug":"api-20","depth":3,"children":[]}]},{"title":"July 1, 2026","slug":"july-1-2026","depth":2,"children":[{"title":"API","slug":"api-21","depth":3,"children":[]}]},{"title":"June 25, 2026","slug":"june-25-2026","depth":2,"children":[{"title":"API","slug":"api-22","depth":3,"children":[]}]},{"title":"June 16, 2026","slug":"june-16-2026","depth":2,"children":[{"title":"Ditto CLI - 5.6.0","slug":"ditto-cli-5-6-0","depth":3,"children":[]}]},{"title":"June 10, 2026","slug":"june-10-2026","depth":2,"children":[{"title":"API","slug":"api-23","depth":3,"children":[]}]},{"title":"June 4, 2026","slug":"june-4-2026","depth":2,"children":[{"title":"API","slug":"api-24","depth":3,"children":[]}]},{"title":"May 28, 2026","slug":"may-28-2026","depth":2,"children":[{"title":"API","slug":"api-25","depth":3,"children":[]}]},{"title":"May 18, 2026","slug":"may-18-2026","depth":2,"children":[{"title":"API","slug":"api-26","depth":3,"children":[]}]},{"title":"May 12, 2026","slug":"may-12-2026","depth":2,"children":[{"title":"API","slug":"api-27","depth":3,"children":[]}]},{"title":"April 30, 2026","slug":"april-30-2026","depth":2,"children":[{"title":"API","slug":"api-28","depth":3,"children":[]}]},{"title":"April 6, 2026","slug":"april-6-2026","depth":2,"children":[{"title":"API","slug":"api-29","depth":3,"children":[]}]},{"title":"April 1, 2026","slug":"april-1-2026","depth":2,"children":[{"title":"Ditto CLI - 5.5.1","slug":"ditto-cli-5-5-1","depth":3,"children":[]}]},{"title":"March 31, 2026","slug":"march-31-2026","depth":2,"children":[{"title":"Ditto CLI - 5.5.0","slug":"ditto-cli-5-5-0","depth":3,"children":[]}]},{"title":"March 27, 2026","slug":"march-27-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-17","depth":3,"children":[]}]},{"title":"March 26, 2026","slug":"march-26-2026","depth":2,"children":[{"title":"API","slug":"api-30","depth":3,"children":[]}]},{"title":"March 24, 2026","slug":"march-24-2026","depth":2,"children":[{"title":"Ditto CLI - 5.4.0","slug":"ditto-cli-5-4-0","depth":3,"children":[]},{"title":"API","slug":"api-31","depth":3,"children":[]}]},{"title":"March 23, 2026","slug":"march-23-2026","depth":2,"children":[{"title":"API","slug":"api-32","depth":3,"children":[]}]},{"title":"March 20, 2026","slug":"march-20-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-18","depth":3,"children":[]}]},{"title":"March 19, 2026","slug":"march-19-2026","depth":2,"children":[{"title":"API","slug":"api-33","depth":3,"children":[]}]},{"title":"March 18, 2026","slug":"march-18-2026","depth":2,"children":[{"title":"API","slug":"api-34","depth":3,"children":[]}]},{"title":"March 16, 2026","slug":"march-16-2026","depth":2,"children":[{"title":"API","slug":"api-35","depth":3,"children":[]}]},{"title":"March 12, 2026","slug":"march-12-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-19","depth":3,"children":[]}]},{"title":"March 5, 2026","slug":"march-5-2026","depth":2,"children":[{"title":"MCP","slug":"mcp-20","depth":3,"children":[]}]},{"title":"February 10, 2026","slug":"february-10-2026","depth":2,"children":[{"title":"API","slug":"api-36","depth":3,"children":[]}]},{"title":"February 2, 2026","slug":"february-2-2026","depth":2,"children":[{"title":"API","slug":"api-37","depth":3,"children":[]}]},{"title":"January 14, 2026","slug":"january-14-2026","depth":2,"children":[{"title":"API","slug":"api-38","depth":3,"children":[]},{"title":"Ditto CLI - 5.3.1","slug":"ditto-cli-5-3-1","depth":3,"children":[]}]},{"title":"January 7, 2026","slug":"january-7-2026","depth":2,"children":[{"title":"API","slug":"api-39","depth":3,"children":[]},{"title":"Ditto CLI - 5.3.0","slug":"ditto-cli-5-3-0","depth":3,"children":[]}]},{"title":"December 11, 2025","slug":"december-11-2025","depth":2,"children":[{"title":"Ditto CLI - 5.2.0","slug":"ditto-cli-5-2-0","depth":3,"children":[]}]},{"title":"December 10, 2025","slug":"december-10-2025","depth":2,"children":[{"title":"API","slug":"api-40","depth":3,"children":[]}]},{"title":"December 9, 2025","slug":"december-9-2025","depth":2,"children":[{"title":"API","slug":"api-41","depth":3,"children":[]}]},{"title":"December 5, 2025","slug":"december-5-2025","depth":2,"children":[{"title":"API","slug":"api-42","depth":3,"children":[]},{"title":"Documentation","slug":"documentation-2","depth":3,"children":[]}]},{"title":"November 5, 2025","slug":"november-5-2025","depth":2,"children":[{"title":"API","slug":"api-43","depth":3,"children":[]}]},{"title":"October 6, 2025","slug":"october-6-2025","depth":2,"children":[{"title":"Ditto Github Action - 1.0.2","slug":"ditto-github-action-1-0-2","depth":3,"children":[]},{"title":"Ditto CLI - 5.1.0","slug":"ditto-cli-5-1-0","depth":3,"children":[]}]},{"title":"October 1, 2025","slug":"october-1-2025","depth":2,"children":[{"title":"Ditto CLI - 5.0.0","slug":"ditto-cli-5-0-0","depth":3,"children":[]}]},{"title":"September 29, 2025","slug":"september-29-2025","depth":2,"children":[{"title":"API","slug":"api-44","depth":3,"children":[]},{"title":"Ditto CLI - 5.0.0-beta.8","slug":"ditto-cli-5-0-0-beta-8","depth":3,"children":[]}]},{"title":"September 11, 2025","slug":"september-11-2025","depth":2,"children":[{"title":"API","slug":"api-45","depth":3,"children":[]}]},{"title":"August 18, 2025","slug":"august-18-2025","depth":2,"children":[{"title":"Ditto CLI - 5.0.0-beta.7","slug":"ditto-cli-5-0-0-beta-7","depth":3,"children":[]}]},{"title":"July 24, 2025","slug":"july-24-2025","depth":2,"children":[{"title":"API","slug":"api-46","depth":3,"children":[]}]},{"title":"July 8, 2025","slug":"july-8-2025","depth":2,"children":[{"title":"API","slug":"api-47","depth":3,"children":[]}]},{"title":"April 30, 2025","slug":"april-30-2025","depth":2,"children":[{"title":"Ditto CLI - 5.0.0-beta.6","slug":"ditto-cli-5-0-0-beta-6","depth":3,"children":[]}]},{"title":"March 28, 2025","slug":"march-28-2025","depth":2,"children":[{"title":"API","slug":"api-48","depth":3,"children":[]}]},{"title":"March 24, 2025","slug":"march-24-2025","depth":2,"children":[{"title":"API","slug":"api-49","depth":3,"children":[]}]},{"title":"February 3, 2025","slug":"february-3-2025","depth":2,"children":[{"title":"API","slug":"api-50","depth":3,"children":[]}]},{"title":"November 11, 2024","slug":"november-11-2024","depth":2,"children":[{"title":"Ditto React - 1.6.3","slug":"ditto-react-1-6-3","depth":3,"children":[]}]},{"title":"May 21, 2024","slug":"may-21-2024","depth":2,"children":[{"title":"Ditto CLI - 4.5.2","slug":"ditto-cli-4-5-2","depth":3,"children":[]}]},{"title":"May 7, 2024","slug":"may-7-2024","depth":2,"children":[{"title":"Ditto CLI - 4.5.1","slug":"ditto-cli-4-5-1","depth":3,"children":[]}]},{"title":"May 3, 2024","slug":"may-3-2024","depth":2,"children":[{"title":"Ditto Github Action - 0.3.0","slug":"ditto-github-action-0-3-0","depth":3,"children":[]}]},{"title":"May 2, 2024","slug":"may-2-2024","depth":2,"children":[{"title":"API / Web App","slug":"api-/-web-app","depth":3,"children":[]}]},{"title":"April 16, 2024","slug":"april-16-2024","depth":2,"children":[{"title":"CLI","slug":"cli","depth":3,"children":[]}]},{"title":"March 22, 2024","slug":"march-22-2024","depth":2,"children":[{"title":"CLI","slug":"cli-2","depth":3,"children":[]}]},{"title":"March 15, 2024","slug":"march-15-2024","depth":2,"children":[{"title":"Documentation","slug":"documentation-3","depth":3,"children":[]}]},{"title":"March 13, 2024","slug":"march-13-2024","depth":2,"children":[{"title":"Ditto React - 1.6.1","slug":"ditto-react-1-6-1","depth":3,"children":[]}]},{"title":"February 29, 2024","slug":"february-29-2024","depth":2,"children":[{"title":"Ditto CLI - 4.4.0","slug":"ditto-cli-4-4-0","depth":3,"children":[]}]},{"title":"February 27, 2024","slug":"february-27-2024","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api","depth":3,"children":[]}]},{"title":"February 19, 2024","slug":"february-19-2024","depth":2,"children":[{"title":"Ditto CLI - 4.3.0","slug":"ditto-cli-4-3-0","depth":3,"children":[]},{"title":"Ditto CLI - 4.2.3","slug":"ditto-cli-4-2-3","depth":3,"children":[]}]},{"title":"January 22, 2024","slug":"january-22-2024","depth":2,"children":[{"title":"Ditto CLI - 4.2.2","slug":"ditto-cli-4-2-2","depth":3,"children":[]}]},{"title":"December 12, 2023","slug":"december-12-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-2","depth":3,"children":[]}]},{"title":"December 7, 2023","slug":"december-7-2023","depth":2,"children":[{"title":"Ditto React","slug":"ditto-react","depth":3,"children":[]}]},{"title":"November 28, 2023","slug":"november-28-2023","depth":2,"children":[{"title":"Ditto CLI - 4.2.1","slug":"ditto-cli-4-2-1","depth":3,"children":[]}]},{"title":"November 16, 2023","slug":"november-16-2023","depth":2,"children":[{"title":"Ditto CLI - 4.2.0","slug":"ditto-cli-4-2-0","depth":3,"children":[]}]},{"title":"November 2, 2023","slug":"november-2-2023","depth":2,"children":[{"title":"Ditto React","slug":"ditto-react-2","depth":3,"children":[]}]},{"title":"October 30, 2023","slug":"october-30-2023","depth":2,"children":[{"title":"Ditto CLI — 4.1.0","slug":"ditto-cli-—-4-1-0","depth":3,"children":[]},{"title":"New example apps","slug":"new-example-apps","depth":3,"children":[]}]},{"title":"September 29, 2023","slug":"september-29-2023","depth":2,"children":[]},{"title":"August 29, 2023","slug":"august-29-2023","depth":2,"children":[{"title":"Ditto React","slug":"ditto-react-3","depth":3,"children":[]}]},{"title":"August 18, 2023","slug":"august-18-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-3","depth":3,"children":[]},{"title":"Ditto CLI","slug":"ditto-cli","depth":3,"children":[]}]},{"title":"August 15, 2023","slug":"august-15-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-4","depth":3,"children":[]}]},{"title":"August 7, 2023","slug":"august-7-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-5","depth":3,"children":[]},{"title":"Ditto CLI","slug":"ditto-cli-2","depth":3,"children":[]}]},{"title":"July 26, 2023","slug":"july-26-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-6","depth":3,"children":[]}]},{"title":"July 17, 2023","slug":"july-17-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-7","depth":3,"children":[]}]},{"title":"June 27, 2023","slug":"june-27-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-3","depth":3,"children":[]}]},{"title":"June 26, 2023","slug":"june-26-2023","depth":2,"children":[{"title":"Ditto React","slug":"ditto-react-4","depth":3,"children":[]}]},{"title":"June 14, 2023","slug":"june-14-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-4","depth":3,"children":[]}]},{"title":"June 12, 2023","slug":"june-12-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-8","depth":3,"children":[]}]},{"title":"June 8, 2023","slug":"june-8-2023","depth":2,"children":[{"title":"VSCode Extension","slug":"vscode-extension","depth":3,"children":[]},{"title":"Ditto CLI","slug":"ditto-cli-5","depth":3,"children":[]}]},{"title":"June 5, 2023","slug":"june-5-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-6","depth":3,"children":[]}]},{"title":"June 2, 2023","slug":"june-2-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-7","depth":3,"children":[]}]},{"title":"May 30, 2023","slug":"may-30-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-8","depth":3,"children":[]},{"title":"Ditto API","slug":"ditto-api-9","depth":3,"children":[]}]},{"title":"May 12, 2023","slug":"may-12-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-10","depth":3,"children":[]}]},{"title":"May 3, 2023","slug":"may-3-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-9","depth":3,"children":[]}]},{"title":"May 1, 2023","slug":"may-1-2023","depth":2,"children":[{"title":"VS Code Extension","slug":"vs-code-extension","depth":3,"children":[]}]},{"title":"April 28, 2023","slug":"april-28-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-11","depth":3,"children":[]}]},{"title":"April 26, 2023","slug":"april-26-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-10","depth":3,"children":[]}]},{"title":"March 23, 2023","slug":"march-23-2023","depth":2,"children":[{"title":"Ditto React","slug":"ditto-react-5","depth":3,"children":[]}]},{"title":"March 22, 2023","slug":"march-22-2023","depth":2,"children":[{"title":"Ditto API, Ditto CLI, Ditto React","slug":"ditto-api-ditto-cli-ditto-react","depth":3,"children":[]}]},{"title":"March 21, 2023","slug":"march-21-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-12","depth":3,"children":[]}]},{"title":"March 9, 2023","slug":"march-9-2023","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-11","depth":3,"children":[]}]},{"title":"February 15, 2023","slug":"february-15-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-13","depth":3,"children":[]}]},{"title":"February 14, 2023","slug":"february-14-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-14","depth":3,"children":[]}]},{"title":"February 6, 2023","slug":"february-6-2023","depth":2,"children":[{"title":"Ditto Web App","slug":"ditto-web-app","depth":3,"children":[]}]},{"title":"February 3, 2023","slug":"february-3-2023","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-15","depth":3,"children":[]}]},{"title":"February 1, 2023","slug":"february-1-2023","depth":2,"children":[{"title":"Ditto React — 1.3.0","slug":"ditto-react-—-1-3-0","depth":3,"children":[]}]},{"title":"January 25, 2023","slug":"january-25-2023","depth":2,"children":[]},{"title":"January 19, 2023","slug":"january-19-2023","depth":2,"children":[{"title":"Ditto React — 1.2.1","slug":"ditto-react-—-1-2-1","depth":3,"children":[]}]},{"title":"December 15, 2022","slug":"december-15-2022","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-12","depth":3,"children":[]}]},{"title":"December 13, 2022","slug":"december-13-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-16","depth":3,"children":[]}]},{"title":"November 30, 2022","slug":"november-30-2022","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-13","depth":3,"children":[]}]},{"title":"November 29, 2022","slug":"november-29-2022","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-14","depth":3,"children":[]}]},{"title":"November 10, 2022","slug":"november-10-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-17","depth":3,"children":[]},{"title":"Ditto CLI","slug":"ditto-cli-15","depth":3,"children":[]}]},{"title":"Oct 11, 2022","slug":"oct-11-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-18","depth":3,"children":[]}]},{"title":"Sep 23, 2022","slug":"sep-23-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-19","depth":3,"children":[]}]},{"title":"Sep 19, 2022","slug":"sep-19-2022","depth":2,"children":[{"title":"Ditto React — 1.2.0","slug":"ditto-react-—-1-2-0","depth":3,"children":[]},{"title":"Ditto API","slug":"ditto-api-20","depth":3,"children":[]}]},{"title":"Jun 30, 2022","slug":"jun-30-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-21","depth":3,"children":[]},{"title":"Ditto CLI — 2.5.1","slug":"ditto-cli-—-2-5-1","depth":3,"children":[]},{"title":"Ditto Example Projects","slug":"ditto-example-projects","depth":3,"children":[]}]},{"title":"Jun 13, 2022","slug":"jun-13-2022","depth":2,"children":[{"title":"Ditto GitHub Action — 0.2.0","slug":"ditto-github-action-—-0-2-0","depth":3,"children":[]}]},{"title":"June 7, 2022","slug":"june-7-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-22","depth":3,"children":[]}]},{"title":"June 1, 2022","slug":"june-1-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-23","depth":3,"children":[]}]},{"title":"May 23, 2022","slug":"may-23-2022","depth":2,"children":[{"title":"Ditto CLI — 2.5.0","slug":"ditto-cli-—-2-5-0","depth":3,"children":[]},{"title":"Ditto GitHub Action — 0.1.0","slug":"ditto-github-action-—-0-1-0","depth":3,"children":[]}]},{"title":"May 16, 2022","slug":"may-16-2022","depth":2,"children":[{"title":"Ditto CLI — 2.4.0","slug":"ditto-cli-—-2-4-0","depth":3,"children":[]}]},{"title":"May 10, 2022","slug":"may-10-2022","depth":2,"children":[{"title":"Ditto CLI — 2.3.0","slug":"ditto-cli-—-2-3-0","depth":3,"children":[]}]},{"title":"February 28, 2022","slug":"february-28-2022","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-24","depth":3,"children":[]}]},{"title":"January 20, 2022","slug":"january-20-2022","depth":2,"children":[{"title":"Ditto React — 1.1.1","slug":"ditto-react-—-1-1-1","depth":3,"children":[]},{"title":"Ditto CLI — 2.2.0","slug":"ditto-cli-—-2-2-0","depth":3,"children":[]}]},{"title":"January 11, 2022","slug":"january-11-2022","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-16","depth":3,"children":[]}]},{"title":"January 6, 2022","slug":"january-6-2022","depth":2,"children":[{"title":"Ditto CLI","slug":"ditto-cli-17","depth":3,"children":[]}]},{"title":"December 8, 2021","slug":"december-8-2021","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-25","depth":3,"children":[]}]},{"title":"November 29, 2021","slug":"november-29-2021","depth":2,"children":[{"title":"Ditto API","slug":"ditto-api-26","depth":3,"children":[]}]},{"title":"November 11, 2021","slug":"november-11-2021","depth":2,"children":[{"title":"Ditto CLI — 2.0.0","slug":"ditto-cli-—-2-0-0","depth":3,"children":[]},{"title":"Ditto React — 1.0.0","slug":"ditto-react-—-1-0-0","depth":3,"children":[]},{"title":"Ditto Demo","slug":"ditto-demo","depth":3,"children":[]}]},{"title":"October 22, 2021","slug":"october-22-2021","depth":2,"children":[{"title":"Ditto API — 2.4.1","slug":"ditto-api-—-2-4-1","depth":3,"children":[]},{"title":"Ditto Demo","slug":"ditto-demo-2","depth":3,"children":[]}]},{"title":"October 7, 2021","slug":"october-7-2021","depth":2,"children":[{"title":"General","slug":"general","depth":3,"children":[]},{"title":"Ditto CLI — 1.1.1","slug":"ditto-cli-—-1-1-1","depth":3,"children":[]},{"title":"Ditto React — 0.0.5","slug":"ditto-react-—-0-0-5","depth":3,"children":[]},{"title":"Ditto Demo","slug":"ditto-demo-3","depth":3,"children":[]}]},{"title":"September 27, 2021","slug":"september-27-2021","depth":2,"children":[{"title":"General","slug":"general-2","depth":3,"children":[]},{"title":"API — 2.4.0","slug":"api-—-2-4-0","depth":3,"children":[]}]},{"title":"September 8, 2021","slug":"september-8-2021","depth":2,"children":[{"title":"API — 2.3.0","slug":"api-—-2-3-0","depth":3,"children":[]}]},{"title":"August 11, 2021","slug":"august-11-2021","depth":2,"children":[{"title":"API — 2.2.0","slug":"api-—-2-2-0","depth":3,"children":[]}]},{"title":"July 28, 2021","slug":"july-28-2021","depth":2,"children":[{"title":"API — 2.1.0","slug":"api-—-2-1-0","depth":3,"children":[]}]},{"title":"June 21, 2021","slug":"june-21-2021","depth":2,"children":[{"title":"Ditto React — 0.0.4","slug":"ditto-react-—-0-0-4","depth":3,"children":[]},{"title":"Ditto Demo","slug":"ditto-demo-4","depth":3,"children":[]}]},{"title":"June 7, 2021","slug":"june-7-2021","depth":2,"children":[{"title":"API — 2.0.0","slug":"api-—-2-0-0","depth":3,"children":[]},{"title":"CLI — 1.0.0","slug":"cli-—-1-0-0","depth":3,"children":[]}]},{"title":"April 1, 2021","slug":"april-1-2021","depth":2,"children":[{"title":"API — 1.1.0","slug":"api-—-1-1-0","depth":3,"children":[]}]},{"title":"February 25, 2021","slug":"february-25-2021","depth":2,"children":[{"title":"API — 1.0.0","slug":"api-—-1-0-0","depth":3,"children":[]}]}],"codeExamples":{}},"jsLinks":[],"subdomain":"ditto","siteName":"Ditto","title":"Developer changelog - Ditto","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-30T15:11:49.695Z","originalFileLocation":"feedback-support/changelog.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Ditto\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Developer changelog - Ditto\">\u003cmeta data-mint-head property=\"og:description\" content=\"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Ditto\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://developer.dittowords.com/feedback-support/changelog\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://ditto.mintlify.app/_mintlify/api/og/v2?division=How+can+we+help%3F\u0026amp;title=Developer+changelog\u0026amp;description=Release+notes+for+the+Ditto+API%2C+CLI%2C+MCP+server%2C+GitHub+Action%2C+and+React+SDK%2C+newest+first.\u0026amp;theme=cafcf8215feabbb48baf53ae\u0026amp;signature=3f56c9639619b9f6f68006d15213d70c764df7e1f4bac8d981c9ff0cb9c0cc36\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Developer changelog - Ditto\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://ditto.mintlify.app/_mintlify/api/og/v2?division=How+can+we+help%3F\u0026amp;title=Developer+changelog\u0026amp;description=Release+notes+for+the+Ditto+API%2C+CLI%2C+MCP+server%2C+GitHub+Action%2C+and+React+SDK%2C+newest+first.\u0026amp;theme=cafcf8215feabbb48baf53ae\u0026amp;signature=3f56c9639619b9f6f68006d15213d70c764df7e1f4bac8d981c9ff0cb9c0cc36\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/ditto/sayH8aGeMpv32blB/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Ditto\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#E2B103\">\u003clink data-mint-head rel=\"canonical\" href=\"https://developer.dittowords.com/feedback-support/changelog\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/feedback-support/changelog.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://www.dittowords.com/#organization\",\"name\":\"Ditto\",\"url\":\"https://www.dittowords.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://developer.dittowords.com/logo/ditto_logo.svg\"},\"sameAs\":[\"https://twitter.com/dittowords\",\"https://github.com/dittowords\",\"https://www.linkedin.com/company/ditto-app\"]},{\"@type\":\"WebSite\",\"@id\":\"https://developer.dittowords.com#website\",\"name\":\"Ditto\",\"url\":\"https://developer.dittowords.com\",\"publisher\":{\"@id\":\"https://www.dittowords.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://developer.dittowords.com/feedback-support/changelog#webpage\",\"url\":\"https://developer.dittowords.com/feedback-support/changelog\",\"name\":\"Developer changelog\",\"description\":\"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.\",\"dateModified\":\"2026-10-30T15:11:49.695Z\",\"isPartOf\":{\"@id\":\"https://developer.dittowords.com#website\"},\"breadcrumb\":{\"@id\":\"https://developer.dittowords.com/feedback-support/changelog#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://developer.dittowords.com/feedback-support/changelog#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"How can we help?\",\"item\":\"https://developer.dittowords.com/feedback-support/feedback-support\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Developer changelog\",\"item\":\"https://developer.dittowords.com/feedback-support/changelog\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://developer.dittowords.com/feedback-support/changelog#article\",\"headline\":\"Developer changelog\",\"name\":\"Developer changelog\",\"description\":\"Release notes for the Ditto API, CLI, MCP server, GitHub Action, and React SDK, newest first.\",\"url\":\"https://developer.dittowords.com/feedback-support/changelog\",\"mainEntityOfPage\":{\"@id\":\"https://developer.dittowords.com/feedback-support/changelog#webpage\"},\"dateModified\":\"2026-10-30T15:11:49.695Z\",\"publisher\":{\"@id\":\"https://www.dittowords.com/#organization\"},\"isPartOf\":{\"@id\":\"https://developer.dittowords.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Ditto\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Ditto","nav":{"global":{"anchors":[{"anchor":"Help Guides","icon":"book-open-cover","href":"https://help.dittowords.com/en/"},{"anchor":"What's New","icon":"newspaper","href":"https://www.dittowords.com/whats-new"},{"anchor":"Figma Plugin","icon":"figma","href":"https://www.figma.com/community/plugin/798826066406007173/ditto-manage-copy-from-design-to-production"}]},"tabs":[{"tab":"Documentation","pages":[{"title":"Documentation","href":"/introduction"}]},{"tab":"Feedback \u0026 Support","groups":[{"group":"How can we help?","pages":[{"title":"Feedback \u0026 Support","description":"Where to report issues and ask questions about the Ditto CLI, API, MCP server, React SDK, and GitHub Action.","href":"/feedback-support/feedback-support"},{"title":"Developer changelog","sidebarTitle":"Changelog","href":"/feedback-support/changelog"}]}]}]},"basePath":"","title":"Developer changelog - Ditto","buildId":"dpl_G9nrg4qeJSZtah1Ziwbc2n6WkLch","deploymentId":"dpl_G9nrg4qeJSZtah1Ziwbc2n6WkLch","dynamics":[],"chunks":[]}