npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@onderwijsin/directus-markdown-editor-bundle

v0.7.0

Published

Directus Markdown/MDC editor interface with coordinated documentation seeding

Readme

@onderwijsin/directus-markdown-editor-bundle

A Markdown Editor with support for dynamic components (MDC) and AI-assisted editing - built with Tiptap. The bundle combines the Markdown Editor field interface with supporting extensions for schema management and AI server logic.

The editor stores portable Markdown in one text or string field. It does not store Tiptap JSON and is agnostic of any specific frontend or rendering framework. The Markdown syntax is compatible with the Comark specification, and uses both components and attributes.

Features

  • headings, paragraphs, marks, lists, blockquotes, dividers, links, tables, images, video, and syntax-highlighted code blocks;
  • keyboard shortcuts, a searchable / command menu, and other Notion-like editing features;
  • full-screen editing, and direct Markdown source editing;
  • generic inline and block components with typed properties and named editable slots;
  • static or remotely loaded component metadata with one definitive JSON contract for dynamic components;
  • hydration-time component property freshness reports with editor-controlled refresh;
  • permission-aware Directus item references with source snapshots and integrity reporting;
  • opt-in AI transformations with reusable skills, custom prompts, document comparison, and stale-safe selection replacement;
  • an optional Dutch Studio Docs article for editors.

Requirements

  • Directus >=12.2.0 <13;
  • Node.js >=24.10.0 when managing the package outside the official Directus image;
  • a trusted, self-hosted Directus runtime that permits non-sandboxed API extensions; and
  • a text or string field for every Markdown document.

The server hook makes this a non-sandboxed bundle. It is not suitable for Directus environments that permit only sandboxed extensions.

Installation

Install the package in the same runtime that starts Directus, then restart Directus:

pnpm add @onderwijsin/directus-markdown-editor-bundle

For a Docker deployment, build a Directus image containing the extension:

FROM directus/directus:12.2.0

USER root
RUN corepack enable
USER node

RUN pnpm add @onderwijsin/directus-markdown-editor-bundle
services:
  directus:
    build: .
    environment:
      MARKDOWN_EDITOR_ENABLED: 'true'
	  EDITOR_AI_PROVIDER: 'openai'
	  EDITOR_AI_MODEL: 'your-model-id'
	  EDITOR_AI_API_KEY: 'replace-with-a-secret'

Pin the Directus image to a version supported by the package and use your normal image update process to upgrade. Directus loads the markdown-editor-interface app entry and markdown-editor-hook API entry from the installed bundle.

Quick start

  1. Open Settings → Data Model and choose a collection.
  2. Add a field with type Text (or String).
  3. Select the Markdown Editor interface.
  4. Leave Available editor tools empty for the first setup; an empty selection enables every tool.
  5. Save the field and open an item in the collection.

The API value remains a string:

{
  "body": "# Welcome\n\nThis content was written in Directus."
}

Interface configuration

Configure these options on each field using the Markdown Editor interface.

| Option | Default | Description | | --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Available editor tools | empty | Selects the toolbar, / menu, block actions, insertion controls, and native shortcuts available on this field. An empty selection enables every tool. If no paragraph or heading level is selected, paragraph remains available. | | Store assets as | path | Format for selected Directus images in Markdown and component image properties: id, path (/assets/{id}), or url. Existing image values are not rewritten. | | Asset base URL | unset | Required in url mode. HTTP(S) Directus base URL, for example https://directus.example.com; selected images are stored as https://directus.example.com/assets/{id}. | | Use static component metadata | false | Chooses static JSON instead of loading component metadata from a URL. | | Component metadata URL | unset | Browser-accessible JSONURL used while static metadata is disabled. | | Static component metadata | unset | Required JSON value while static metadata is enabled. | | Use item references | false | Enables the Reference picker, Reference editing, and document integrity checks. | | Reference collections | unset | Required non-empty JSON array when item references are enabled. | | Enable reference icon | false | Shows an Iconify picker in the Reference drawer when item references are enabled. Existing stored icons remain intact when disabled. | | Iconify collections | all | Searchable collection selection for Reference icons. Leave empty to include every collection. Component icon properties use their own config. | | Use Iconify API proxy | false | Uses /iconify for icons. Requires @onderwijsin/directus-iconify-bundle installed on this Directus instance; the editor does not provide the proxy. | | Reference snapshot mode | detect | Chooses snapshot, detect, or sync behavior for source snapshots. | | Enable AI editing | false | Shows AI actions for this field and allows authenticated /editor/ai requests for it. |

AI-assisted editing

AI is disabled per field by default. When enabled, AI is the first toolbar action. A non-empty selection shows AI first in the selection toolbar, and the drag-handle menu offers the same actions for its current block. The / menu starts with an AI section containing Write with AI and skills with the insert scope. Document suggestions open a side-by-side Markdown diff and change the field only after Apply changes. Selection suggestions open a floating review panel below the target selection and replace it only after confirmation. Selected headings, lists, marks, and other Markdown structure are included in the AI request. Insert suggestions are added to the document immediately. None of these flows save the Directus item automatically.

The hook provisions the versioned editor_skills collection and the Can Use Editor Skills policy. It also reconciles the bundled skill catalog during its own coordinated documentation phase. Skill seeding is independent of the global DIRECTUS_EXTENSIONS_DATA_SEED_ENABLED gate, so the catalog is still reconciled when ordinary policy and data seeding is disabled. New seeds are created; changed seeds create or refresh Directus' Incoming version by default, so maintainer edits to the main item are not overwritten. Set the strategy to override only when deployed seed content must replace the main item. Assign the policy to editor roles that may use AI. It grants create, read, and update access to skills, intentionally not delete access. Administrators can always invoke the endpoint without this policy. The endpoint separately reads the selected skill with request accountability, validates its scope and archive state, and never trusts a client-supplied stored prompt.

| Environment variable | Default | Contract | | ----------------------------------------- | ---------------- | ----------------------------------------------------------------------- | | EDITOR_AI_PROVIDER | shared value | Local provider override: openai, anthropic, google, or mistral. | | EDITOR_AI_MODEL | shared value | Local provider-native model override. | | EDITOR_AI_API_KEY | shared/Directus | Local secret override used only by the API extension. | | EDITOR_AI_BASE_URL | shared/default | Local provider-specific API base URL override. | | DIRECTUS_EXTENSIONS_AI_PROVIDER | unset | Shared provider used when EDITOR_AI_PROVIDER is unset. | | DIRECTUS_EXTENSIONS_AI_MODEL | unset | Shared model used when EDITOR_AI_MODEL is unset. | | DIRECTUS_EXTENSIONS_AI_API_KEY | Directus setting | Shared secret used before a matching Directus provider credential. | | DIRECTUS_EXTENSIONS_AI_BASE_URL | provider default | Shared provider API base URL. | | EDITOR_AI_MAX_CONTENT_LENGTH | 100000 | Positive maximum request content length in characters. | | MARKDOWN_EDITOR_SCHEMA_CHANGES_ENABLED | true | Provisions and reconciles editor_skills. | | MARKDOWN_EDITOR_SCHEMA_ABORT_ON_ERROR | true | Aborts startup when that schema reconciliation fails. | | MARKDOWN_EDITOR_SKILLS_SEED_ENABLED | true | Enables the hook-owned bundled skill seed catalog. | | MARKDOWN_EDITOR_SKILLS_SEEDING_STRATEGY | versioning | Uses versioning or override for changed seeds. |

AI configuration resolves each value from the editor-specific variables, then the shared DIRECTUS_EXTENSIONS_AI_* variables. When no API key is supplied, the endpoint reuses the encrypted Directus project credential matching the selected OpenAI, Anthropic, or Google provider. The provider and model must still be configured explicitly; Directus has no general default for either. The internal settings read happens only after endpoint authorization and no credential is returned to Studio. Mistral requires an editor-specific or shared API key.

editor_skills includes Directus versioning and the standard user_created, date_created, user_updated, and date_updated audit fields. Bundled seeds use stable UUIDs. Removing a seed from a later package release does not delete or archive an existing item.

The bundled catalog seeds Fix spelling and grammar, Improve clarity, Improve structure, Rewrite, Shorten, Expand, and Turn into bullet points. Their document/selection scopes control where each action appears.

POST /editor/ai requires an authenticated request with the Can Use Editor Skills policy, collection/field context for a Markdown field whose ai option is true, and exactly one of skillId or prompt. Stored skills must be readable, active, and compatible with scope (document, selection, or insert). Insert requests supply the complete current Markdown with an explicit insertion marker instead of replacement content. The response is { "content": "replacement or inserted Markdown" }. AI content and custom prompts are sent to the configured provider; do not enable the feature for content that organizational policy forbids sending there.

Requests also include a bounded, normalized description of the field's configured MDC components. This lets the model preserve component names, properties, and slots. The hardcoded system prompt is created per request from the target field's server-read Available editor tools, selected component metadata source, and Use item references configuration. It describes only syntax enabled for new authoring in that editor instance, while requiring existing syntax to be preserved. It also preserves every natural language used by the input unless the editing task explicitly requests another language, treats code as literal by default, and returns provider output without trimming intentional boundary whitespace.

Available editor tools can independently expose paragraphs, heading levels 1–6, bold, italic, strikethrough, inline code, blockquotes, code blocks, unordered and numbered lists, images, video, links, dividers, hard breaks, tables, clear formatting, history, source mode, and full-screen mode.

Component insertion is available whenever the selected metadata source provides components. Reference insertion and integrity checks are controlled by Use item references. These features are independent of Available editor tools. Saved component and reference tool IDs are ignored.

Component metadata contract

Component metadata tells the editor which MDC components authors can insert, which properties they can configure, and which named slots they can edit. The contract is independent of any frontend framework and accepts either an array or an object with a components array:

{
  "components": [
    {
      "name": "Callout",
      "label": "Callout",
      "description": "Highlight important supporting content.",
      "nodeType": "block",
      "props": {
        "tone": {
          "name": "Tone",
          "type": "string",
          "description": "Visual emphasis used by the website.",
          "required": true,
          "default": "info",
          "values": ["info", "warning", "danger"]
        },
        "dismissible": {
          "name": "Dismissible",
          "type": "boolean",
          "default": false
        },
        "audiences": {
          "name": "Audiences",
          "type": "array",
          "values": ["students", "teachers", "parents"]
        },
        "image": {
          "name": "Image",
          "type": "string",
          "tags": [{ "name": "specialInputType", "text": "image" }]
        }
      },
      "slots": ["default"]
    },
    {
      "name": "Icon",
      "nodeType": "inline",
      "props": [{ "name": "name", "type": "string", "required": true }],
      "slots": []
    }
  ]
}

Component fields

| Field | Required | Contract | | ------------- | -------- | --------------------------------------------------------------------------------------------------- | | name | yes | Non-empty MDC component name. Reference is reserved and omitted from generic component insertion. | | nodeType | yes | block or inline. Components with slots always insert as blocks. | | label | no | Editor-facing name; defaults to name. | | description | no | Editor-facing explanation shown during component selection. | | tags | no | JSDoc tags; deprecated marks a supported component for replacement or removal. | | props | no | Object keyed by property name, or an array whose entries contain name; defaults to {}. | | slots | no | Array of slot-name strings or { "name": "..." } objects; defaults to []. |

Property fields

| Field | Required | Contract | | ------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | name | only in array form | Property key in array form; optional editor-facing label in object form. | | type | no | Editor input hint: string, number, boolean, object, or array. Unknown legacy values fall back to text. | | description | no | Help text for the property. | | required | no | Prevents insertion until the author supplies a value; defaults to false. | | default | no | Initial JSON-compatible value applied during insertion. | | values | no | Allowed string choices. On string this renders a select; on array it renders a multiselect. | | properties | no | Child property map for an object, rendered as a labeled group. Children may themselves be objects or arrays. | | items | no | Item definition for an array. Object items render a reorderable repeater; string items without values render editable tags. | | tags | no | JSDoc tags from component metadata, with optional config; deprecated adds a hint, while specialInputType: image and specialInputType: url select richer controls. The former editor tag remains readable. |

The primitive controls preserve their corresponding values: string stores a string, number stores a number, boolean stores a boolean, and a primitive array stores a string array. A string property with values is the select form of the string control; select is not a separate property type. Arrays without values accept free-form tags that can be dragged into order. Object arrays render rows with Add, drag to reorder, keyboard move controls, and confirmed removal. Nested required fields and URL hints block Apply/Insert when invalid. Objects and object arrays persist as JSON-backed MDC attributes.

For example, a Hero can define image as { "type": "object", "properties": { "src": { "type": "string", "required": true, "tags": [{ "name": "specialInputType", "text": "image" }] } } } and actions as { "type": "array", "items": { "type": "object", "properties": { "label": { "type": "string", "required": true }, "to": { "type": "string", "tags": [{ "name": "specialInputType", "text": "url" }] } } } }. The icon hint renders an Iconify picker. Set its tag config to { "collections": ["lucide"] } to limit that property to a collection. Without configured collections, the picker offers all collections. This setting is separate from the editor's Iconify collections option for Reference icons.

For an image asset property, keep the component prop typed as string and add the Vue-compatible JSDoc tag @specialInputType image. In JSON this is { "name": "specialInputType", "text": "image" }. The drawer uses the Directus image selector, shows the selected asset as a removable thumbnail, and persists the selected format from Store assets as. The default is now /assets/{id} for newly selected MDC image properties; existing stored IDs remain unchanged. Use @specialInputType url for a string control that requires a valid HTTP(S) URL with its protocol. Existing metadata with @editor image or @editor url still works; when both tags are supplied, specialInputType wins. Arbitrary JSDoc tags remain available, while the editor interprets only documented hints and deprecated.

When a static value or metadata URL loads successfully, the editor treats that metadata as authoritative and checks components after hydration. Missing required properties, required properties whose persisted value is empty, removed properties, and added or removed slots produce an attention report and warning styling in the canvas. Components absent from authoritative metadata use error styling and expose deletion as their only action. A missing or failed metadata source is not interpreted as component deletion.

The scan never rewrites Markdown. Review opens the component drawer. Refresh properties is shown in the header only for property drift; it preserves known values, applies defaults, and removes obsolete properties. Refresh slots preserves supported slot content, removes unsupported slots and their content, and adds empty current slots. Changes are persisted only after Apply, which is blocked while required values are empty. Optional property additions do not create attention items.

Components and properties carrying a standard JSDoc deprecated tag remain functional and display a Deprecated hint. Deprecated components are labeled in both insertion menus and appear in the report and canvas as warnings so authors can replace or remove them. A deprecated property remains a UI hint only. Tag text is shown as migration guidance when supplied; no separate deprecated field is used.

Additional component and property fields are retained by validation but are not otherwise interpreted by the current editor. Refreshing newly added slots converts a legacy inline occurrence to a block because inline MDC cannot contain slots; other metadata changes preserve its node type.

When using Component metadata URL, the Directus user’s browser fetches the URL. Serve valid JSON over HTTPS with CORS headers that allow the Studio origin. Authentication headers are not added by the editor. Add the remote metadata host to Directus’s CSP connect-src directive with CONTENT_SECURITY_POLICY_DIRECTIVES__CONNECT_SRC (see Directus CSP configuration). How a frontend generates, publishes, or transports this metadata is intentionally outside this package; static JSON and the URL are equivalent inputs to the same contract.

MDC storage examples

Bare inline syntax such as :Icon is recognized only when currently loaded metadata identifies that name as an inline component. Ordinary colon text such as 14:00 uur or list:with content stays text. Explicit inline syntax (:Name{} or :Name{prop="value"}) remains supported for unknown components, including when metadata is loading or unavailable. Existing component nodes always serialize independently of metadata. Unknown bare syntax remains text; use {} to make an unknown component explicit. Empty inline nodes serialize with {} to keep adjacent text separate.

Inline components use one colon and block components use two:

Read the :Badge{tone="info"} before continuing.

::Callout{tone="warning"}
#default
Remember to publish your changes.
::

Named slots remain editable regions:

::Hero
#title
Welcome to our website
#description
Supporting **Markdown** for the introduction.
::

YAML properties are supported for block components:

::Hero
---
theme: dark
layout: wide
---
#default
Hero content
::

String attributes preserve escaped quotes and backslashes. Shorthand booleans and dynamic JSON bindings preserve their value types. Dynamic bindings use single outer quotes, so JSON objects and arrays retain their standard double-quoted JSON syntax. Unknown component names remain generic MDC nodes so stored content is not tied to the current metadata list.

Item references

References let authors select Directus items without creating a relational field. They are inline MDC snapshots, not database relations.

Enable Use item references and configure direct fields only:

[
  {
    "collection": "articles",
    "displayField": "title",
    "searchFields": ["title", "slug"],
    "dataFields": ["slug", "status", "category"]
  },
  {
    "collection": "programs",
    "displayField": "name",
    "dataFields": ["slug", "type"]
  }
]

| Field | Default | Contract | | -------------- | ---------------- | ---------------------------------------------------------------------------- | | collection | required | Unique Directus collection name. | | displayField | required | Direct field used as the stored source label. | | searchFields | [displayField] | Direct string or text fields searched with case-insensitive containment. | | dataFields | [] | Direct fields copied into the stored source snapshot. |

Changing this configuration triggers a new integrity scan. Removing a configured collection marks its persisted References as Not configured without rewriting them. Changing displayField compares stored labels with the newly selected field, while changing dataFields compares the stored data object with the newly selected field set. In detect mode differences are reported as outdated; sync updates available snapshots in one editor transaction; snapshot leaves snapshot values unchecked. Invalid collection configuration is reported without deleting stored References. Outdated and archived References use warning styling in the canvas; unconfigured, unavailable, and unverifiable References use error styling.

The editor discovers the real primary key and requests only the configured projection plus the archive field configured on the collection. Nested fields, wildcards, aliases, foreign keys, and relation traversal are rejected. Duplicate collection entries are invalid. Give Studio authors read access to the configured collection, primary key, display field, search fields, data fields, and archive field.

Snapshot modes behave as follows:

| Mode | Behavior when a document loads | | ---------- | ----------------------------------------------------------------------------------------------------------------- | | snapshot | Verifies availability and archive state without reporting ordinary snapshot differences. | | detect | Verifies sources and reports changed labels/data so the author can refresh them. | | sync | Refreshes changed labels/data in one editor transaction; the item becomes dirty but is never saved automatically. |

A stored Reference looks like this:

:Reference{collection="articles" item="article-7" label="Becoming a teacher" text="this article"
icon="school" :data='{"slug":"becoming-a-teacher"}'}

collection, item, label, and object data are required on new References. item can be a string or finite number. label and data belong to the source snapshot. Optional text and icon belong to the author and survive refresh, synchronization, and source replacement. Consumer renderers should display text ?? label.

Archived items are omitted from search and reported as Archived when still readable. Missing items and permission-hidden items are both reported as Unavailable. The editor never uses an administrator token, changes the source item, saves the containing item automatically, or creates a reverse index.

Links

Authors can insert links from the toolbar, selection bubble, slash menu, or drag-handle insert menu. The link drawer requires visible link text and offers URL, internal path, email, and phone types. URL values require an http:// or https:// protocol, internal paths must start with /, and email values must be valid addresses. Phone values are accepted as entered. Email and phone links persist as standard mailto: and tel: hrefs.

Code blocks and media

Code blocks use Shiki’s light and dark GitHub themes. Authors can choose a supported language, add a filename/path, and mark a block as collapsible. Stored Markdown remains compatible with Nuxt Content-style fences:

```ts [app/nuxt.config.ts]
export default defineNuxtConfig({})
```

Collapsible code uses an MDC ::code-collapse wrapper. Inside code blocks, Tab and Shift-Tab indent/outdent and Enter preserves indentation.

Images and video can be selected from the Directus file library or entered as HTTP(S), relative, or /assets/{id} URLs. Newly selected images follow Store assets as; id values are previewed through the current Directus /assets/ path while their Markdown keeps the bare ID. Image library browsing is filtered to image MIME types and video browsing to video MIME types. Selected images and videos show a removable preview; video previews include native playback controls. Existing image and video blocks expose Edit image or Edit video in their drag-handle action menu. The image drawer also accepts optional alt text, which is stored in the image Markdown and can be edited later. Videos are constrained to the editor or preview width while retaining their natural size when smaller. Executable and data protocols are rejected. The extension does not transform images, generate captions, or provide a frontend media renderer.

Resizable Markdown images

Drag the handle centered on an image's right edge to resize it while preserving its natural aspect ratio. The chosen pixel width survives saving and reopening through Comark-compatible attributes:

![Alt text](asset-id){width="420"}

Only width is persisted; height remains automatic. Images without a width retain the responsive full-width default. Both states are constrained to the editor container. Remove the width attribute in source mode, or drag the handle back to the container boundary, to return to full width. A small snap zone at the boundary shows a dashed outline of the full-width target during dragging. The image follows the pointer until release; releasing inside the active zone clears the stored width and animates to full width. Resizing away from full width has no snap or animation. The release animation is disabled when reduced motion is preferred. Invalid, zero, or negative widths use the default state. Directus asset IDs remain unchanged in Markdown and resolve to asset URLs for editor previews. Frontend image components should honor the width attribute and use max-width: 100%; height: auto; to avoid overflow on narrower screens. Comark supports this attribute syntax without a custom plugin.

Studio Docs article

Install @onderwijsin/directus-studio-docs-bundle when editors should receive the bundled Dutch guide in Studio:

pnpm add @onderwijsin/directus-studio-docs-bundle

The Studio Docs bundle provisions studio_docs and its policies. Assign its view or manage policy to the appropriate roles. This bundle contributes the stable Editor article during the documentation startup phase.

| Environment variable | Default | Description | | --------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------- | | MARKDOWN_EDITOR_ENABLED | true | Enables the Markdown Editor server hook and its documentation contribution. The browser interface remains registered. | | MARKDOWN_EDITOR_DOCS_SEED_ENABLED | true | Enables contribution of the Editor article. | | DIRECTUS_EXTENSIONS_LOCK_PROVIDER | SYNCHRONIZATION_STORE | Startup lock: memory, redis, or fs. Use a shared provider for multiple Directus processes. | | DIRECTUS_EXTENSIONS_LOCK_REDIS_URL | resolved Directus Redis config | Optional Redis URL override for the startup lock. | | DIRECTUS_EXTENSIONS_LOCK_FS_DIRECTORY | unset | Required with the fs provider; all processes must share the directory. | | SYNCHRONIZATION_STORE | memory | Shared fallback store: memory or redis. |

The hook accepts the shared schema/data and rate-limiter environment values through the common startup schema, but its documentation phase—including the bundled editor skill catalog—is independent of the global schema and data gates. See the Studio Docs bundle configuration for seeding strategy, schema provisioning, and policy controls. With its default versioning strategy, changed article content is written to the incoming version for review rather than replacing the published article.

Security and operational boundaries

  • Install the bundle only in a trusted Directus runtime.
  • Treat remote component metadata as trusted authoring configuration and serve it over HTTPS.
  • Reference searches use the signed-in Studio user’s API session and Directus permissions.
  • Source mode warns when applying Markdown would normalize or remove unsupported syntax and requires explicit confirmation.
  • Frontend rendering, component registration, styling, content sanitization, and Reference resolution are responsibilities of the consuming application.
  • The package does not generate component metadata, inspect a frontend project, provision content collections, assign roles, or save edited Directus items automatically.

Troubleshooting

| Symptom | Check | | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Markdown Editor is missing | Confirm the package is installed in the Directus runtime, the app entry is enabled, and Directus was restarted. | | Component insertion is missing | Provide valid metadata through the selected static or URL source. | | Remote metadata fails | Check the browser console for the source URL and validation path, then verify HTTPS, CORS, and JSON validity. A successful HTTP response can still fail metadata validation. The endpoint receives no custom authentication header. | | A Reference collection is disabled | Check collection uniqueness, direct field names, primary-key metadata, field types, and relational fields. | | Authors cannot find a Reference item | Check their read permissions and whether the item is archived. Search starts after text is entered. | | A Reference is unavailable | The source is missing or hidden by permissions; replace or remove it from the integrity report. | | Updated Studio docs are not visible | Inspect the incoming content version when the Studio Docs seeding strategy is versioning. | | Startup reports a lock skip/error | Configure Redis or a shared filesystem lock for multi-process deployments. |

Default image alt text

For new image insertions, selecting a Directus file prefills alt text from its trimmed, non-empty directus_files.description. If unavailable, the editor checks again after 500 ms, 1 s, 2 s, 4 s, and 8 s, then stops silently. Waiting for image metadata… Save the image to continue in the background. Stay on this page. shows with a small spinner during these checks; typing and saving remain available. Metadata generation belongs to your project; the editor only reads descriptions using the current Studio session. Allow authors read access to the selected file's id and description for delayed descriptions to be available. Failed or denied reads leave insertion available without a default.

Editing or clearing alt text makes the author's value authoritative for the rest of that insertion, even when another image is selected. Before any manual edit, selecting another image replaces the previous automatic description and invalidates pending checks. Deselecting an image or cancelling an unsaved insertion stops its checks. Saving the image transfers the lookup to that exact Markdown image occurrence: closing or unmounting the drawer then allows the bounded retries to continue while the editor remains mounted. A result fills the open field or updates the inserted image's alt text in the Markdown value, without saving the Directus item automatically. Stay on the page until the metadata resolves; leaving the page or destroying the editor cancels pending work. Deleting, undoing, replacing, or manually changing a pending image prevents a late description from updating it. Other images using the same file are unaffected. Existing images retain their serialized alt text when edited; opening their drawer does not start a new lookup. Reopening an image that still has its insertion lookup pending shows the waiting state and permits manual edits to cancel that default. Markdown image syntax remains unchanged.

Provider-bound configuration

Provider-sensitive inheritance is restricted to matching providers. A layer without a provider belongs to the provider inherited from lower layers; lower-layer models, API keys, and base URLs never acquire an overridden provider from above. When changing provider, supply a matching model and credentials in that layer, another matching layer, or provider-matched Directus settings. Unbound lower-layer credentials are not inherited.

An empty or whitespace-only DIRECTUS_EXTENSIONS_AI_API_KEY environment value is treated as unset, allowing startup without an AI key and provider-matched credential fallback. Generation still requires a complete resolved configuration.

License

MIT