[{"data":1,"prerenderedAt":4429},["ShallowReactive",2],{"content-navigation":3,"$fY4mAj2l3kRkTDttxn6FGzqBc2O9HAJ2qp-_8LmMX7aw":2046,"\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Frichtext":2050,"\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Frichtext-surround":4383,"\u002F_partials\u002Fextensions-uid":4386,"\u002F_partials\u002Fextensions-app":4408},[4,108,115,220,329,430,799,851,1546,1565,1570,1602,1636],{"title":5,"path":6,"stem":7,"children":8,"page":89},"Partials","\u002F_partials","_partials",[9,15,20,25,29,33,38,42,47,51,56,60,64,68,90,94,99,104],{"title":10,"path":11,"stem":12,"description":13,"icon":14,"links":14},"Advanced Field Creation Mode","\u002F_partials\u002Fadvanced-field-creation-mode","_partials\u002Fadvanced-field-creation-mode","You can use these advanced options to automatically set the values of fields at specific events by clicking on \"Continue in Advanced Field Creation Mode\".",null,{"title":16,"path":17,"stem":18,"description":19,"icon":14,"links":14},"Authentication","\u002F_partials\u002Fauthentication","_partials\u002Fauthentication","While the Public role can be configured to make data available without authentication, anything that is not public requires a user to authenticate their requests.",{"title":21,"path":22,"stem":23,"description":24,"icon":14,"links":14},"Config Env Vars","\u002F_partials\u002Fconfig-env-vars","_partials\u002Fconfig-env-vars","",{"title":26,"path":27,"stem":28,"description":24,"icon":14,"links":14},"Deployment Public Instance","\u002F_partials\u002Fdeployment-public-instance","_partials\u002Fdeployment-public-instance",{"title":30,"path":31,"stem":32,"description":24,"icon":14,"links":14},"Engine Studio Box","\u002F_partials\u002Fengine-studio-box","_partials\u002Fengine-studio-box",{"title":34,"path":35,"stem":36,"description":37,"icon":14,"links":14},"Extension Hook Footguns","\u002F_partials\u002Fextension-hook-footguns","_partials\u002Fextension-hook-footguns","Directus reads system collections to operate. Be careful when modifying the output of system collection read or query events. Also ensure not to directly or indirectly emit the same event your hook is handling or you will create an infinite loop.",{"title":39,"path":40,"stem":41,"description":24,"icon":14,"links":14},"Extension Hook System Collections","\u002F_partials\u002Fextension-hook-system-collections","_partials\u002Fextension-hook-system-collections",{"title":43,"path":44,"stem":45,"description":46,"icon":14,"links":14},"Extensions Api","\u002F_partials\u002Fextensions-api","_partials\u002Fextensions-api","This extension type is loaded into the Directus process. They can use the provided services exported by the @directus\u002Fextensions-sdk package and can be written in JavaScript or TypeScript.",{"title":48,"path":49,"stem":50,"description":24,"icon":14,"links":14},"Extensions Api Internals","\u002F_partials\u002Fextensions-api-internals","_partials\u002Fextensions-api-internals",{"title":52,"path":53,"stem":54,"description":55,"icon":14,"links":14},"Extensions App","\u002F_partials\u002Fextensions-app","_partials\u002Fextensions-app","This extension type is loaded into the Directus Data Studio. They are are built with Vue 3, and can use the provided composables exported by the @directus\u002Fextensions-sdk package. Extensions can be written in JavaScript or TypeScript.",{"title":57,"path":58,"stem":59,"description":24,"icon":14,"links":14},"Extensions App Internals","\u002F_partials\u002Fextensions-app-internals","_partials\u002Fextensions-app-internals",{"title":61,"path":62,"stem":63,"description":24,"icon":14,"links":14},"Extensions Theme","\u002F_partials\u002Fextensions-theme","_partials\u002Fextensions-theme",{"title":65,"path":66,"stem":67,"description":24,"icon":14,"links":14},"Extensions Uid","\u002F_partials\u002Fextensions-uid","_partials\u002Fextensions-uid",{"title":69,"path":70,"stem":71,"children":72,"page":89},"Home Hero","\u002F_partials\u002Fhome-hero","_partials\u002Fhome-hero",[73,77,81,85],{"title":74,"path":75,"stem":76,"description":24,"icon":14,"links":14},"Auth","\u002F_partials\u002Fhome-hero\u002Fauth","_partials\u002Fhome-hero\u002Fauth",{"title":78,"path":79,"stem":80,"description":24,"icon":14,"links":14},"Data","\u002F_partials\u002Fhome-hero\u002Fdata","_partials\u002Fhome-hero\u002Fdata",{"title":82,"path":83,"stem":84,"description":24,"icon":14,"links":14},"File","\u002F_partials\u002Fhome-hero\u002Ffile","_partials\u002Fhome-hero\u002Ffile",{"title":86,"path":87,"stem":88,"description":24,"icon":14,"links":14},"Realtime","\u002F_partials\u002Fhome-hero\u002Frealtime","_partials\u002Fhome-hero\u002Frealtime",false,{"title":91,"path":92,"stem":93,"description":24,"icon":14,"links":14},"License","\u002F_partials\u002Flicense","_partials\u002Flicense",{"title":95,"path":96,"stem":97,"description":98,"icon":14,"links":14},"Query Functions","\u002F_partials\u002Fquery-functions","_partials\u002Fquery-functions","Functions accept a field and return a modified value. Functions can be used in any query parameter you'd normally supply a field key, including fields, aggregation, and filters.",{"title":100,"path":101,"stem":102,"description":103,"icon":14,"links":14},"Quickstart Making Calls","\u002F_partials\u002Fquickstart-making-calls","_partials\u002Fquickstart-making-calls","You can use a visual API testing tool like Postman or Hoppscotch, a terminal-based based tool like curl or HTTPie, or make HTTP requests directly in a script written in your programming language of choice.",{"title":105,"path":106,"stem":107,"description":24,"icon":14,"links":14},"Snippet Auth Token","\u002F_partials\u002Fsnippet-auth-token","_partials\u002Fsnippet-auth-token",{"title":109,"path":110,"stem":111,"children":112,"description":114,"icon":14,"links":14},"Directus API Reference","\u002Fapi","api\u002Findex",[113],{"title":109,"path":110,"stem":111,"description":114,"icon":14,"links":14},"Learn how to use our API",{"title":116,"path":117,"stem":118,"children":119,"page":89},"Cloud","\u002Fcloud","cloud",[120,140,170,200],{"title":121,"path":122,"stem":123,"children":124,"page":89},"Getting Started","\u002Fcloud\u002Fgetting-started","cloud\u002F1.getting-started",[125,130,135],{"title":126,"path":127,"stem":128,"description":129,"icon":14,"links":14},"Introduction","\u002Fcloud\u002Fgetting-started\u002Fintroduction","cloud\u002F1.getting-started\u002F1.introduction","Whether you're a hobbyist, startup, or enterprise, our flexible Directus Cloud platform lets you get up and running with Directus quickly.",{"title":131,"path":132,"stem":133,"description":134,"icon":14,"links":14},"Cloud Teams","\u002Fcloud\u002Fgetting-started\u002Fteams","cloud\u002F1.getting-started\u002F2.teams","A team is an organizational system that groups accounts together as team members and provides consolidated billing for projects.",{"title":136,"path":137,"stem":138,"description":139,"icon":14,"links":14},"Managing Cloud Accounts","\u002Fcloud\u002Fgetting-started\u002Faccounts","cloud\u002F1.getting-started\u002F3.accounts","An account is your portal to Directus Cloud. You can use it to manage your teams, team members, projects and billing.",{"title":141,"path":142,"stem":143,"children":144,"page":89},"Projects","\u002Fcloud\u002Fprojects","cloud\u002F2.projects",[145,150,155,160,165],{"title":146,"path":147,"stem":148,"description":149,"icon":14,"links":14},"Create a Project","\u002Fcloud\u002Fprojects\u002Fcreate","cloud\u002F2.projects\u002F1.create","Create a project in Directus Cloud.",{"title":151,"path":152,"stem":153,"description":154,"icon":14,"links":14},"Destroy a Project","\u002Fcloud\u002Fprojects\u002Fdestroy","cloud\u002F2.projects\u002F2.destroy","Destroy a Directus Cloud project and cancel your subscription.",{"title":156,"path":157,"stem":158,"description":159,"icon":14,"links":14},"Version Upgrades","\u002Fcloud\u002Fprojects\u002Fversion-upgrades","cloud\u002F2.projects\u002F3.version-upgrades","Learn about automatic upgrades and version locking in Directus Cloud.",{"title":161,"path":162,"stem":163,"description":164,"icon":14,"links":14},"Monitoring Projects","\u002Fcloud\u002Fprojects\u002Fmonitoring","cloud\u002F2.projects\u002F4.monitoring","Learn how to monitor your Directus Cloud project.",{"title":166,"path":167,"stem":168,"description":169,"icon":14,"links":14},"Backups","\u002Fcloud\u002Fprojects\u002Fbackups","cloud\u002F2.projects\u002F5.backups","Learn about automatic backups in Directus Cloud.",{"title":171,"path":172,"stem":173,"children":174,"page":89},"Configuration","\u002Fcloud\u002Fconfiguration","cloud\u002F3.configuration",[175,180,185,190,195],{"title":176,"path":177,"stem":178,"description":179,"icon":14,"links":14},"Custom Domains","\u002Fcloud\u002Fconfiguration\u002Fcustom-domains","cloud\u002F3.configuration\u002F1.custom-domains","Custom domains are available for your Directus Enterprise Cloud project.",{"title":181,"path":182,"stem":183,"description":184,"icon":14,"links":14},"Environment Variables","\u002Fcloud\u002Fconfiguration\u002Fenvironment-variables","cloud\u002F3.configuration\u002F2.environment-variables","Learn about environment variables in Directus Cloud.",{"title":186,"path":187,"stem":188,"description":189,"icon":14,"links":14},"Direct Database Access","\u002Fcloud\u002Fconfiguration\u002Fdirect-database-access","cloud\u002F3.configuration\u002F3.direct-database-access","Learn how to directly access your Directus Cloud project's database.",{"title":191,"path":192,"stem":193,"description":194,"icon":14,"links":14},"Custom Extensions","\u002Fcloud\u002Fconfiguration\u002Fcustom-extensions","cloud\u002F3.configuration\u002F4.custom-extensions","Learn how to deploy custom extensions to your Directus Cloud project.",{"title":196,"path":197,"stem":198,"description":199,"icon":14,"links":14},"Datacenter Regions","\u002Fcloud\u002Fconfiguration\u002Fdatacenter-regions","cloud\u002F3.configuration\u002F5.datacenter-regions","Learn where datacenters for cloud projects are located.",{"title":201,"path":202,"stem":203,"children":204,"page":89},"Billing","\u002Fcloud\u002Fbilling","cloud\u002F4.billing",[205,210,215],{"title":206,"path":207,"stem":208,"description":209,"icon":14,"links":14},"Manage Billing","\u002Fcloud\u002Fbilling\u002Fmanage-billing","cloud\u002F4.billing\u002F1.manage-billing","Learn how to manage billing for your Directus Cloud project.",{"title":211,"path":212,"stem":213,"description":214,"icon":14,"links":14},"Changing Your Tier","\u002Fcloud\u002Fbilling\u002Fchanging-tier","cloud\u002F4.billing\u002F2.changing-tier","Learn how to change the tier of your Directus Cloud project.",{"title":216,"path":217,"stem":218,"description":219,"icon":14,"links":14},"Cancel Your Subscription","\u002Fcloud\u002Fbilling\u002Fcancel-subscription","cloud\u002F4.billing\u002F3.cancel-subscription","Learn how to cancel your Directus Cloud project subscription.",{"title":221,"path":222,"stem":223,"children":224,"page":89},"Community","\u002Fcommunity","community",[225,245,270,289,314],{"title":226,"path":227,"stem":228,"children":229,"page":89},"Overview","\u002Fcommunity\u002Foverview","community\u002F1.overview",[230,235,240],{"title":231,"path":232,"stem":233,"description":234,"icon":14,"links":14},"Welcome","\u002Fcommunity\u002Foverview\u002Fwelcome","community\u002F1.overview\u002F1.welcome","Welcome to the Directus community!",{"title":236,"path":237,"stem":238,"description":239,"icon":14,"links":14},"Code of Conduct","\u002Fcommunity\u002Foverview\u002Fconduct","community\u002F1.overview\u002F2.conduct","Our standards, responsibilities, and enforcement guidelines to create a positive community.",{"title":241,"path":242,"stem":243,"description":244,"icon":14,"links":14},"Moderation Guidelines","\u002Fcommunity\u002Foverview\u002Fmoderation","community\u002F1.overview\u002F3.moderation","Guidelines we give to community moderators.",{"title":246,"path":247,"stem":248,"children":249,"page":89},"Contribution","\u002Fcommunity\u002Fcontribution","community\u002F2.contribution",[250,255,260,265],{"title":251,"path":252,"stem":253,"description":254,"icon":14,"links":14},"Translations","\u002Fcommunity\u002Fcontribution\u002Ftranslations","community\u002F2.contribution\u002F1.translations","How to contribute to translating the Data Studio.",{"title":256,"path":257,"stem":258,"description":259,"icon":14,"links":14},"Documentation","\u002Fcommunity\u002Fcontribution\u002Fdocumentation","community\u002F2.contribution\u002F2.documentation","How to contribute to the Directus documentation.",{"title":261,"path":262,"stem":263,"description":264,"icon":14,"links":14},"Feature Requests","\u002Fcommunity\u002Fcontribution\u002Ffeature-requests","community\u002F2.contribution\u002F3.feature-requests","How to add feature requests, and our process for reviewing them.",{"title":266,"path":267,"stem":268,"description":269,"icon":14,"links":14},"Pull Requests","\u002Fcommunity\u002Fcontribution\u002Fpull-requests","community\u002F2.contribution\u002F4.pull-requests","Our process for contributing pull requests to Directus.",{"title":271,"path":272,"stem":273,"children":274,"page":89},"Codebase","\u002Fcommunity\u002Fcodebase","community\u002F3.codebase",[275,279,284],{"title":271,"path":276,"stem":277,"description":278,"icon":14,"links":14},"\u002Fcommunity\u002Fcodebase\u002Foverview","community\u002F3.codebase\u002F1.overview","Overview of the Directus codebase for new contributors",{"title":280,"path":281,"stem":282,"description":283,"icon":14,"links":14},"Development Environment","\u002Fcommunity\u002Fcodebase\u002Fdev-environment","community\u002F3.codebase\u002F2.dev-environment","How to set up and run a development environment for Directus so that you can work on the platform's source code.",{"title":285,"path":286,"stem":287,"description":288,"icon":14,"links":14},"Testing","\u002Fcommunity\u002Fcodebase\u002Ftesting","community\u002F3.codebase\u002F3.testing","How to run unit and blackbox tests in the Directus codebase.",{"title":290,"path":291,"stem":292,"children":293,"page":89},"Reporting And Support","\u002Fcommunity\u002Freporting-and-support","community\u002F4.reporting-and-support",[294,299,304,309],{"title":295,"path":296,"stem":297,"description":298,"icon":14,"links":14},"Troubleshooting Steps","\u002Fcommunity\u002Freporting-and-support\u002Ftroubleshooting-steps","community\u002F4.reporting-and-support\u002F1.troubleshooting-steps","If you're experiencing issues or think you have found a problem in Directus, be sure to follow these steps.",{"title":300,"path":301,"stem":302,"description":303,"icon":14,"links":14},"Bug Reporting","\u002Fcommunity\u002Freporting-and-support\u002Fbug-reporting","community\u002F4.reporting-and-support\u002F2.bug-reporting","How to report bugs in Directus.",{"title":305,"path":306,"stem":307,"description":308,"icon":14,"links":14},"Security Reporting","\u002Fcommunity\u002Freporting-and-support\u002Fsecurity-reporting","community\u002F4.reporting-and-support\u002F3.security-reporting","How to report security issues in Directus.",{"title":310,"path":311,"stem":312,"description":313,"icon":14,"links":14},"Customer Support","\u002Fcommunity\u002Freporting-and-support\u002Fcustomer-support","community\u002F4.reporting-and-support\u002F4.customer-support","How to get help with Directus as a user and customer.",{"title":315,"path":316,"stem":317,"children":318,"page":89},"Programs","\u002Fcommunity\u002Fprograms","community\u002F5.programs",[319,324],{"title":320,"path":321,"stem":322,"description":323,"icon":14,"links":14},"Guest Authors","\u002Fcommunity\u002Fprograms\u002Fguest-authors","community\u002F5.programs\u002F1.guest-authors","Our guest author program invites authors to join and get paid to write tutorials for the Directus community.",{"title":325,"path":326,"stem":327,"description":328,"icon":14,"links":14},"Directus Labs","\u002Fcommunity\u002Fprograms\u002Fdirectus-labs","community\u002F5.programs\u002F2.directus-labs","Directus Labs is the official organization for Directus templates, settings and experimental projects.",{"title":171,"path":330,"stem":331,"children":332,"page":89},"\u002Fconfiguration","configuration",[333,337,342,347,352,357,362,367,372,377,382,387,392,397,402,407,411,416,421,426],{"title":126,"path":334,"stem":335,"description":336,"icon":14,"links":14},"\u002Fconfiguration\u002Fintro","configuration\u002F0.intro","Environment variables are used for all configuration within a Directus project. These variables can be defined in a number of ways, which we cover below.",{"title":338,"path":339,"stem":340,"description":341,"icon":14,"links":14},"General","\u002Fconfiguration\u002Fgeneral","configuration\u002F1.general","Configuration for the general system, server, first admin user, and telemetry.",{"title":343,"path":344,"stem":345,"description":346,"icon":14,"links":14},"AI","\u002Fconfiguration\u002Fai","configuration\u002Fai","Configuration for AI Assistant and Model Context Protocol (MCP) features.",{"title":348,"path":349,"stem":350,"description":351,"icon":14,"links":14},"Auth & SSO","\u002Fconfiguration\u002Fauth-sso","configuration\u002Fauth-sso","Configuration for authentication methods, including local email\u002Fpassword, OAuth 2.0, OpenID, LDAP, and SAML.",{"title":353,"path":354,"stem":355,"description":356,"icon":14,"links":14},"Cache","\u002Fconfiguration\u002Fcache","configuration\u002Fcache","Configuration for internal and output caching.",{"title":358,"path":359,"stem":360,"description":361,"icon":14,"links":14},"Database","\u002Fconfiguration\u002Fdatabase","configuration\u002Fdatabase","Configuration for database connections.",{"title":363,"path":364,"stem":365,"description":366,"icon":14,"links":14},"Email","\u002Fconfiguration\u002Femail","configuration\u002Femail","Configuration for email settings and templates.",{"title":368,"path":369,"stem":370,"description":371,"icon":14,"links":14},"Extensions","\u002Fconfiguration\u002Fextensions","configuration\u002Fextensions","Configuration for extensions and the Directus Marketplace.",{"title":373,"path":374,"stem":375,"description":376,"icon":14,"links":14},"Files","\u002Fconfiguration\u002Ffiles","configuration\u002Ffiles","Configuration for storage locations, metadata, upload limits, and transformations.",{"title":378,"path":379,"stem":380,"description":381,"icon":14,"links":14},"Flows","\u002Fconfiguration\u002Fflows","configuration\u002Fflows","Configure environment variables, memory, and timeout for Flows.",{"title":383,"path":384,"stem":385,"description":386,"icon":14,"links":14},"Health Check","\u002Fconfiguration\u002Fhealthcheck","configuration\u002Fhealthcheck","Configuration for the server health check service.",{"title":388,"path":389,"stem":390,"description":391,"icon":14,"links":14},"Logging","\u002Fconfiguration\u002Flogging","configuration\u002Flogging","Configuration for general and Realtime logging.",{"title":393,"path":394,"stem":395,"description":396,"icon":14,"links":14},"Metrics","\u002Fconfiguration\u002Fmetrics","configuration\u002Fmetrics","Configuration for metrics.",{"title":398,"path":399,"stem":400,"description":401,"icon":14,"links":14},"Migrations","\u002Fconfiguration\u002Fmigrations","configuration\u002Fmigrations","Creation of custom migration files to automate database changes.",{"title":403,"path":404,"stem":405,"description":406,"icon":14,"links":14},"PM2","\u002Fconfiguration\u002Fpm2","configuration\u002Fpm2","Configuration for PM2, the process manager for Directus.",{"title":86,"path":408,"stem":409,"description":410,"icon":14,"links":14},"\u002Fconfiguration\u002Frealtime","configuration\u002Frealtime","Configuration for WebSockets and GraphQL Subscriptions.",{"title":412,"path":413,"stem":414,"description":415,"icon":14,"links":14},"Security & Limits","\u002Fconfiguration\u002Fsecurity-limits","configuration\u002Fsecurity-limits","Configuration for access tokens, cookies, CSP, hashing, CORS, rate limiting, and request limits.",{"title":417,"path":418,"stem":419,"description":420,"icon":14,"links":14},"Synchronization","\u002Fconfiguration\u002Fsynchronization","configuration\u002Fsynchronization","Configuration around synchronization and Redis.",{"title":422,"path":423,"stem":424,"description":425,"icon":14,"links":14},"Theming","\u002Fconfiguration\u002Ftheming","configuration\u002Ftheming","Configuration of the Data Studio's theming engine and appearance settings.",{"title":251,"path":427,"stem":428,"description":429,"icon":14,"links":14},"\u002Fconfiguration\u002Ftranslations","configuration\u002Ftranslations","Directus supports translations for both the Data Studio UI and authored content.",{"title":431,"description":14,"icon":432,"links":14,"path":433,"stem":434,"children":435,"page":89},"Frameworks","i-lucide-braces","\u002Fframeworks","frameworks",[436,508,566,606,659,675,687,699,711,723,735,747,763,775,787],{"title":437,"description":438,"icon":439,"links":14,"path":440,"stem":441,"children":442},"Next.js","Build content-driven React apps with Directus.","simple-icons:nextdotjs","\u002Fframeworks\u002Fnextjs","frameworks\u002F01.nextjs\u002Findex",[443,444,449,453,458,463,468,473,478,483,488,493,498,503],{"title":226,"path":440,"stem":441,"description":438,"icon":14,"links":14},{"title":445,"path":446,"stem":447,"description":448,"icon":14,"links":14},"Data Fetching","\u002Fframeworks\u002Fnextjs\u002Fdata-fetching","frameworks\u002F01.nextjs\u002F01.data-fetching","Learn how to integrate Directus in your Next.js web application.",{"title":16,"path":450,"stem":451,"description":452,"icon":14,"links":14},"\u002Fframeworks\u002Fnextjs\u002Fauthentication","frameworks\u002F01.nextjs\u002F02.authentication","Learn how to setup Directus authentication with Next.js.",{"title":454,"path":455,"stem":456,"description":457,"icon":14,"links":14},"Build a CMS","\u002Fframeworks\u002Fnextjs\u002Fbuild-a-cms","frameworks\u002F01.nextjs\u002F03.build-a-cms","Learn how to create a CMS using Directus and Next.js.",{"title":459,"path":460,"stem":461,"description":462,"icon":14,"links":14},"Dynamic Forms","\u002Fframeworks\u002Fnextjs\u002Fdynamic-forms","frameworks\u002F01.nextjs\u002F04.dynamic-forms","Learn how to setup Directus fields with Next.js.",{"title":464,"path":465,"stem":466,"description":467,"icon":14,"links":14},"Dynamic Pages","\u002Fframeworks\u002Fnextjs\u002Fdynamic-pages","frameworks\u002F01.nextjs\u002F05.dynamic-pages","Learn how to create dynamic pages you can use in your CMS using Directus and Next.js.",{"title":469,"path":470,"stem":471,"description":472,"icon":14,"links":14},"Form Submissions","\u002Fframeworks\u002Fnextjs\u002Fforms","frameworks\u002F01.nextjs\u002F06.forms","Learn how to submit forms using Directus and Next.js.",{"title":474,"path":475,"stem":476,"description":477,"icon":14,"links":14},"Live Preview","\u002Fframeworks\u002Fnextjs\u002Flive-preview","frameworks\u002F01.nextjs\u002F07.live-preview","Learn how to setup Directus live preview with Next.js.",{"title":479,"path":480,"stem":481,"description":482,"icon":14,"links":14},"Live Preview and Versions","\u002Fframeworks\u002Fnextjs\u002Flive-preview-content-versioning","frameworks\u002F01.nextjs\u002F08.live-preview-content-versioning","Learn how to set up Live Preview with different content versions in your Next.js application.",{"title":484,"path":485,"stem":486,"description":487,"icon":14,"links":14},"Draft Mode Preview","\u002Fframeworks\u002Fnextjs\u002Flive-preview-draft-mode","frameworks\u002F01.nextjs\u002F09.live-preview-draft-mode","Learn how to configure Live Preview with Next.js' draft mode.",{"title":489,"path":490,"stem":491,"description":492,"icon":14,"links":14},"Multilingual Content","\u002Fframeworks\u002Fnextjs\u002Fmultilingual-content","frameworks\u002F01.nextjs\u002F10.multilingual-content","Learn how to access multilingual Directus content using Next.js.",{"title":494,"path":495,"stem":496,"description":497,"icon":14,"links":14},"Pagination","\u002Fframeworks\u002Fnextjs\u002Fpagination-infinite-scroll","frameworks\u002F01.nextjs\u002F11.pagination-infinite-scroll","Learn various techniques to load paginated data in your Next.js application.",{"title":499,"path":500,"stem":501,"description":502,"icon":14,"links":14},"Reusable Blocks","\u002Fframeworks\u002Fnextjs\u002Freusable-blocks","frameworks\u002F01.nextjs\u002F12.reusable-blocks","Learn how to render dynamic blocks using Next.js.",{"title":504,"path":505,"stem":506,"description":507,"icon":14,"links":14},"Visual Editor","\u002Fframeworks\u002Fnextjs\u002Fvisual-editor","frameworks\u002F01.nextjs\u002F13.visual-editor","Learn how to integrate the Directus Visual Editor with Next.js.",{"title":509,"description":510,"icon":511,"links":14,"path":512,"stem":513,"children":514},"Nuxt","Build Vue applications and websites with Directus.","simple-icons:nuxt","\u002Fframeworks\u002Fnuxt","frameworks\u002F02.nuxt\u002Findex",[515,516,520,524,528,532,536,540,544,549,554,558,562],{"title":226,"path":512,"stem":513,"description":510,"icon":14,"links":14},{"title":445,"path":517,"stem":518,"description":519,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fdata-fetching","frameworks\u002F02.nuxt\u002F01.data-fetching","Learn how to integrate Directus in your Nuxt web application.",{"title":16,"path":521,"stem":522,"description":523,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fauthentication","frameworks\u002F02.nuxt\u002F02.authentication","Learn how to setup Directus authentication with Nuxt.",{"title":454,"path":525,"stem":526,"description":527,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fbuild-a-cms","frameworks\u002F02.nuxt\u002F03.build-a-cms","Learn how to create a CMS using Directus and Nuxt.",{"title":459,"path":529,"stem":530,"description":531,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fdynamic-forms","frameworks\u002F02.nuxt\u002F04.dynamic-forms","Learn how to setup Directus fields with Nuxt.",{"title":464,"path":533,"stem":534,"description":535,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fdynamic-pages","frameworks\u002F02.nuxt\u002F05.dynamic-pages","Learn how to create dynamic pages you can use in your CMS using Directus and Nuxt.",{"title":469,"path":537,"stem":538,"description":539,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fforms","frameworks\u002F02.nuxt\u002F06.forms","Learn how to submit forms using Directus and Nuxt.",{"title":474,"path":541,"stem":542,"description":543,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Flive-preview","frameworks\u002F02.nuxt\u002F07.live-preview","Learn how to setup Directus live preview with Nuxt.",{"title":545,"path":546,"stem":547,"description":548,"icon":14,"links":14},"Live Preview Setup","\u002Fframeworks\u002Fnuxt\u002Flive-preview-setup","frameworks\u002F02.nuxt\u002F08.live-preview-setup","Learn how to create a Nuxt preview plugin to configure Live Preview.",{"title":550,"path":551,"stem":552,"description":553,"icon":14,"links":14},"Nuxt Content Migration","\u002Fframeworks\u002Fnuxt\u002Fmigrate-from-nuxt-content","frameworks\u002F02.nuxt\u002F09.migrate-from-nuxt-content","Learn how to move from a flat-file CMS to Directus.",{"title":489,"path":555,"stem":556,"description":557,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fmultilingual-content","frameworks\u002F02.nuxt\u002F10.multilingual-content","Learn how to access multilingual Directus content using Nuxt.",{"title":499,"path":559,"stem":560,"description":561,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Freusable-blocks","frameworks\u002F02.nuxt\u002F11.reusable-blocks","Learn how to render dynamic blocks using Nuxt.",{"title":504,"path":563,"stem":564,"description":565,"icon":14,"links":14},"\u002Fframeworks\u002Fnuxt\u002Fvisual-editor","frameworks\u002F02.nuxt\u002F12.visual-editor","Learn how to integrate the Directus Visual Editor with Nuxt.",{"title":567,"description":568,"icon":569,"links":14,"path":570,"stem":571,"children":572},"Astro","Create content sites with Astro and Directus.","simple-icons:astro","\u002Fframeworks\u002Fastro","frameworks\u002F03.astro\u002Findex",[573,574,578,582,586,590,594,598,602],{"title":226,"path":570,"stem":571,"description":568,"icon":14,"links":14},{"title":445,"path":575,"stem":576,"description":577,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Fdata-fetching","frameworks\u002F03.astro\u002F01.data-fetching","Learn how to integrate Directus in your Astro web application.",{"title":16,"path":579,"stem":580,"description":581,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Fauthentication","frameworks\u002F03.astro\u002F02.authentication","Learn how to setup Directus authentication with Astro.",{"title":454,"path":583,"stem":584,"description":585,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Fbuild-a-cms","frameworks\u002F03.astro\u002F03.build-a-cms","Learn how to create a CMS using Directus and Astro.",{"title":459,"path":587,"stem":588,"description":589,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Fdynamic-forms","frameworks\u002F03.astro\u002F04.dynamic-forms","Learn how to setup Directus fields with Astro.",{"title":464,"path":591,"stem":592,"description":593,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Fdynamic-pages","frameworks\u002F03.astro\u002F05.dynamic-pages","Learn how to create dynamic pages you can use in your CMS using Directus and Astro.",{"title":474,"path":595,"stem":596,"description":597,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Flive-preview","frameworks\u002F03.astro\u002F06.live-preview","Learn how to setup Directus live preview with Astro.",{"title":489,"path":599,"stem":600,"description":601,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Fmultilingual-content","frameworks\u002F03.astro\u002F07.multilingual-content","Learn how to access multilingual Directus content using Astro.",{"title":499,"path":603,"stem":604,"description":605,"icon":14,"links":14},"\u002Fframeworks\u002Fastro\u002Freusable-blocks","frameworks\u002F03.astro\u002F08.reusable-blocks","Learn how to render dynamic blocks using Astro.",{"title":607,"description":608,"icon":609,"links":14,"path":610,"stem":611,"children":612},"SvelteKit","Use Directus as the backend for SvelteKit apps.","simple-icons:svelte","\u002Fframeworks\u002Fsveltekit","frameworks\u002F04.sveltekit\u002Findex",[613,614,618,622,626,630,634,638,643,647,651,655],{"title":226,"path":610,"stem":611,"description":608,"icon":14,"links":14},{"title":445,"path":615,"stem":616,"description":617,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fdata-fetching","frameworks\u002F04.sveltekit\u002F01.data-fetching","Learn how to integrate Directus in your SvelteKit web application.",{"title":16,"path":619,"stem":620,"description":621,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fauthentication","frameworks\u002F04.sveltekit\u002F02.authentication","Learn how to setup Directus authentication with SvelteKit.",{"title":454,"path":623,"stem":624,"description":625,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fbuild-a-cms","frameworks\u002F04.sveltekit\u002F03.build-a-cms","Learn how to create a CMS using Directus and SvelteKit.",{"title":459,"path":627,"stem":628,"description":629,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fdynamic-forms","frameworks\u002F04.sveltekit\u002F04.dynamic-forms","Learn how to setup Directus fields with SvelteKit.",{"title":464,"path":631,"stem":632,"description":633,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fdynamic-pages","frameworks\u002F04.sveltekit\u002F05.dynamic-pages","Learn how to create dynamic pages you can use in your CMS using Directus and SvelteKit.",{"title":469,"path":635,"stem":636,"description":637,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fforms","frameworks\u002F04.sveltekit\u002F06.forms","Learn how to submit forms using Directus and SvelteKit.",{"title":639,"path":640,"stem":641,"description":642,"icon":14,"links":14},"Internationalization","\u002Fframeworks\u002Fsveltekit\u002Finternationalization","frameworks\u002F04.sveltekit\u002F07.internationalization","Learn how to handle internationalization in your SvelteKit application.",{"title":474,"path":644,"stem":645,"description":646,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Flive-preview","frameworks\u002F04.sveltekit\u002F08.live-preview","Learn how to setup Directus live preview with SvelteKit.",{"title":489,"path":648,"stem":649,"description":650,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fmultilingual-content","frameworks\u002F04.sveltekit\u002F09.multilingual-content","Learn how to access multilingual Directus content using SvelteKit.",{"title":499,"path":652,"stem":653,"description":654,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Freusable-blocks","frameworks\u002F04.sveltekit\u002F10.reusable-blocks","Learn how to render dynamic blocks using SvelteKit.",{"title":504,"path":656,"stem":657,"description":658,"icon":14,"links":14},"\u002Fframeworks\u002Fsveltekit\u002Fvisual-editor","frameworks\u002F04.sveltekit\u002F11.visual-editor","Learn how to integrate the Directus Visual Editor with SvelteKit.",{"title":660,"description":661,"icon":662,"links":14,"path":663,"stem":664,"children":665},"React","Connect React apps to Directus APIs and Realtime.","simple-icons:react","\u002Fframeworks\u002Freact","frameworks\u002F05.react\u002Findex",[666,667,671],{"title":226,"path":663,"stem":664,"description":661,"icon":14,"links":14},{"title":16,"path":668,"stem":669,"description":670,"icon":14,"links":14},"\u002Fframeworks\u002Freact\u002Fauthentication","frameworks\u002F05.react\u002F01.authentication","Learn how to setup Directus authentication with React.",{"title":474,"path":672,"stem":673,"description":674,"icon":14,"links":14},"\u002Fframeworks\u002Freact\u002Flive-preview","frameworks\u002F05.react\u002F02.live-preview","Learn how to setup Directus live preview with React.",{"title":676,"description":677,"icon":678,"links":14,"path":679,"stem":680,"children":681},"Angular","Fetch and render Directus data in Angular apps.","simple-icons:angular","\u002Fframeworks\u002Fangular","frameworks\u002F06.angular\u002Findex",[682,683],{"title":226,"path":679,"stem":680,"description":677,"icon":14,"links":14},{"title":445,"path":684,"stem":685,"description":686,"icon":14,"links":14},"\u002Fframeworks\u002Fangular\u002Fdata-fetching","frameworks\u002F06.angular\u002F01.data-fetching","Learn how to integrate Directus in your Angular web application.",{"title":688,"description":689,"icon":690,"links":14,"path":691,"stem":692,"children":693},"Laravel","Use Directus with Laravel applications.","simple-icons:laravel","\u002Fframeworks\u002Flaravel","frameworks\u002F07.laravel\u002Findex",[694,695],{"title":226,"path":691,"stem":692,"description":689,"icon":14,"links":14},{"title":445,"path":696,"stem":697,"description":698,"icon":14,"links":14},"\u002Fframeworks\u002Flaravel\u002Fdata-fetching","frameworks\u002F07.laravel\u002F01.data-fetching","Learn how to integrate Directus in your Laravel web application.",{"title":700,"description":701,"icon":702,"links":14,"path":703,"stem":704,"children":705},"Django","Use Directus with Django applications.","simple-icons:django","\u002Fframeworks\u002Fdjango","frameworks\u002F08.django\u002Findex",[706,707],{"title":226,"path":703,"stem":704,"description":701,"icon":14,"links":14},{"title":445,"path":708,"stem":709,"description":710,"icon":14,"links":14},"\u002Fframeworks\u002Fdjango\u002Fdata-fetching","frameworks\u002F08.django\u002F01.data-fetching","Learn how to integrate Directus in your Django web application.",{"title":712,"description":713,"icon":714,"links":14,"path":715,"stem":716,"children":717},"Flask","Use Directus with Flask applications.","simple-icons:flask","\u002Fframeworks\u002Fflask","frameworks\u002F09.flask\u002Findex",[718,719],{"title":226,"path":715,"stem":716,"description":713,"icon":14,"links":14},{"title":445,"path":720,"stem":721,"description":722,"icon":14,"links":14},"\u002Fframeworks\u002Fflask\u002Fdata-fetching","frameworks\u002F09.flask\u002F01.data-fetching","Learn how to integrate Directus in your Flask web application.",{"title":724,"description":725,"icon":726,"links":14,"path":727,"stem":728,"children":729},"Spring Boot","Use Directus with Spring Boot applications.","simple-icons:springboot","\u002Fframeworks\u002Fspring-boot","frameworks\u002F10.spring-boot\u002Findex",[730,731],{"title":226,"path":727,"stem":728,"description":725,"icon":14,"links":14},{"title":445,"path":732,"stem":733,"description":734,"icon":14,"links":14},"\u002Fframeworks\u002Fspring-boot\u002Fdata-fetching","frameworks\u002F10.spring-boot\u002F01.data-fetching","Learn how to integrate Directus in your Spring Boot web application.",{"title":736,"description":737,"icon":738,"links":14,"path":739,"stem":740,"children":741},"Flutter","Build cross-platform apps backed by Directus.","simple-icons:flutter","\u002Fframeworks\u002Fflutter","frameworks\u002F11.flutter\u002Findex",[742,743],{"title":226,"path":739,"stem":740,"description":737,"icon":14,"links":14},{"title":445,"path":744,"stem":745,"description":746,"icon":14,"links":14},"\u002Fframeworks\u002Fflutter\u002Fdata-fetching","frameworks\u002F11.flutter\u002F01.data-fetching","Learn how to integrate Directus in your Flutter app with Dart.",{"title":748,"description":749,"icon":750,"links":14,"path":751,"stem":752,"children":753},"iOS Swift","Use Directus in native iOS apps with Swift.","simple-icons:swift","\u002Fframeworks\u002Fswift","frameworks\u002F12.swift\u002Findex",[754,755,759],{"title":226,"path":751,"stem":752,"description":749,"icon":14,"links":14},{"title":445,"path":756,"stem":757,"description":758,"icon":14,"links":14},"\u002Fframeworks\u002Fswift\u002Fdata-fetching","frameworks\u002F12.swift\u002F01.data-fetching","Learn how to integrate Directus in your iOS app with Swift.",{"title":16,"path":760,"stem":761,"description":762,"icon":14,"links":14},"\u002Fframeworks\u002Fswift\u002Fauthentication","frameworks\u002F12.swift\u002F02.authentication","Learn how to register, login, and protect content in your iOS app.",{"title":764,"description":765,"icon":766,"links":14,"path":767,"stem":768,"children":769},"Android Kotlin","Use Directus in native Android apps with Kotlin.","simple-icons:android","\u002Fframeworks\u002Fkotlin","frameworks\u002F13.kotlin\u002Findex",[770,771],{"title":226,"path":767,"stem":768,"description":765,"icon":14,"links":14},{"title":445,"path":772,"stem":773,"description":774,"icon":14,"links":14},"\u002Fframeworks\u002Fkotlin\u002Fdata-fetching","frameworks\u002F13.kotlin\u002F01.data-fetching","Learn how to integrate Directus in your Android app with Kotlin.",{"title":776,"description":777,"icon":778,"links":14,"path":779,"stem":780,"children":781},"Eleventy","Build static sites with Eleventy and Directus.","simple-icons:eleventy","\u002Fframeworks\u002Feleventy","frameworks\u002F14.eleventy\u002Findex",[782,783],{"title":226,"path":779,"stem":780,"description":777,"icon":14,"links":14},{"title":445,"path":784,"stem":785,"description":786,"icon":14,"links":14},"\u002Fframeworks\u002Feleventy\u002Fdata-fetching","frameworks\u002F14.eleventy\u002F01.data-fetching","Learn how to integrate Directus in your 11ty web application.",{"title":788,"description":789,"icon":790,"links":14,"path":791,"stem":792,"children":793},"SolidStart","Use Directus with SolidStart applications.","simple-icons:solid","\u002Fframeworks\u002Fsolidstart","frameworks\u002F15.solidstart\u002Findex",[794,795],{"title":226,"path":791,"stem":792,"description":789,"icon":14,"links":14},{"title":445,"path":796,"stem":797,"description":798,"icon":14,"links":14},"\u002Fframeworks\u002Fsolidstart\u002Fdata-fetching","frameworks\u002F15.solidstart\u002F01.data-fetching","Learn how to integrate Directus in your SolidStart web application.",{"title":121,"description":14,"icon":14,"links":14,"path":800,"stem":801,"children":802,"page":89},"\u002Fgetting-started","getting-started",[803,807,812,816,821,826,831,836,841,846],{"title":226,"path":804,"stem":805,"description":806,"icon":14,"links":14},"\u002Fgetting-started\u002Foverview","getting-started\u002F1.overview","Learn what Directus is, when to use it, and how it works.",{"title":808,"path":809,"stem":810,"description":811,"icon":14,"links":14},"Accessibility","\u002Fgetting-started\u002Faccessibility","getting-started\u002F10.accessibility","We are always looking for ways to make Directus Studio more accessible. Here are some of the methods we currently support.",{"title":146,"path":813,"stem":814,"description":815,"icon":14,"links":14},"\u002Fgetting-started\u002Fcreate-a-project","getting-started\u002F2.create-a-project","Learn about how to create a managed Directus project or self-host with Docker.",{"title":817,"path":818,"stem":819,"description":820,"icon":14,"links":14,"label":817},"Configure a Data Model","\u002Fgetting-started\u002Fdata-model","getting-started\u002F3.data-model","This guide will cover creating a collection in Directus via the Data Studio, creating fields, and configuring relationships.",{"title":822,"path":823,"stem":824,"description":825,"icon":14,"links":14},"Use the API","\u002Fgetting-started\u002Fuse-the-api","getting-started\u002F4.use-the-api","Get started with Directus APIs. Learn to interact with collections, fetch, and create data.",{"title":827,"path":828,"stem":829,"description":830,"icon":14,"links":14},"Authenticate a User","\u002Fgetting-started\u002Fauthenticate-user","getting-started\u002F5.authenticate-user","Get started with Directus Auth. Learn how to register, login, create users, and make authenticated requests.",{"title":832,"path":833,"stem":834,"description":835,"icon":14,"links":14},"Upload & Access Files","\u002Fgetting-started\u002Fupload-files","getting-started\u002F6.upload-files","This guide will cover importing a file via URL, requesting assets, and using transformation parameters.",{"title":837,"path":838,"stem":839,"description":840,"icon":14,"links":14},"Create a Flow","\u002Fgetting-started\u002Fcreate-an-automation","getting-started\u002F7.create-an-automation","Get started using flows, triggers, operations, and the data chain in Directus.",{"title":842,"path":843,"stem":844,"description":845,"icon":14,"links":14},"Connect to Realtime Data","\u002Fgetting-started\u002Fconnect-to-realtime","getting-started\u002F8.connect-to-realtime","This guide will cover connecting to Directus via WebSockets on the web, subscribing to changes, and creating new items over the connection.",{"title":847,"path":848,"stem":849,"description":850,"icon":14,"links":14},"Resources & Links","\u002Fgetting-started\u002Fresources","getting-started\u002F9.resources","Key links across the Directus ecosystem.",{"title":852,"path":853,"stem":854,"children":855,"page":89},"Guides","\u002Fguides","guides",[856,886,966,1012,1061,1090,1116,1139,1153,1270,1306,1318,1416,1537],{"title":857,"description":14,"icon":14,"links":14,"path":858,"stem":859,"children":860,"page":89},"Data Model","\u002Fguides\u002Fdata-model","guides\u002F01.data-model",[861,866,871,876,881],{"title":862,"path":863,"stem":864,"description":865,"icon":14,"links":14},"Collections","\u002Fguides\u002Fdata-model\u002Fcollections","guides\u002F01.data-model\u002F1.collections","Directus collections help you manage your data. Create custom collections, define fields, configure relationships, and leverage features like content versioning and access control. Learn how to create, configure, and manage collections in Directus.",{"title":867,"path":868,"stem":869,"description":870,"icon":14,"links":14},"Fields","\u002Fguides\u002Fdata-model\u002Ffields","guides\u002F01.data-model\u002F2.fields","Directus fields let you define how your data is stored and displayed. Learn about creating fields, data types, interfaces, validations, relationships, and more. Discover how to configure fields to perfectly suit your data modeling needs in Directus.",{"title":872,"path":873,"stem":874,"description":875,"icon":14,"links":14},"Interfaces","\u002Fguides\u002Fdata-model\u002Finterfaces","guides\u002F01.data-model\u002F3.interfaces","Manage your data effectively with Directus fields. Discover various field types, interfaces, validations, and relationships to perfectly suit your data modeling needs.",{"title":877,"path":878,"stem":879,"description":880,"icon":14,"links":14},"Rich Text","\u002Fguides\u002Fdata-model\u002Frich-text","guides\u002F01.data-model\u002F4.rich-text","Configure custom formats for the WYSIWYG interface, understand what the editor stores, and style the resulting HTML in your app's frontend CSS.",{"title":882,"path":883,"stem":884,"description":885,"icon":14,"links":14},"Relationships","\u002Fguides\u002Fdata-model\u002Frelationships","guides\u002F01.data-model\u002F5.relationships","Leverage Directus relationships to create powerful data connections. Explore Many to One, One to Many, Many to Many, and Many to Any relationships, along with Translations for multilingual content management.",{"title":887,"description":14,"icon":14,"links":14,"path":888,"stem":889,"children":890,"page":89},"Content","\u002Fguides\u002Fcontent","guides\u002F02.content",[891,896,901,906,911,915,920,924,945],{"title":892,"path":893,"stem":894,"description":895,"icon":14,"links":14},"Collection Page","\u002Fguides\u002Fcontent\u002Fexplore","guides\u002F02.content\u002F1.explore","Learn to filter, layout, batch edit and more on the collection page.",{"title":897,"path":898,"stem":899,"description":900,"icon":14,"links":14},"Item Page","\u002Fguides\u002Fcontent\u002Feditor","guides\u002F02.content\u002F2.editor","Learn to create, duplicate, archive and perform other actions with items using Directus.",{"title":902,"path":903,"stem":904,"description":905,"icon":14,"links":14},"Layouts","\u002Fguides\u002Fcontent\u002Flayouts","guides\u002F02.content\u002F3.layouts","Learn to use layouts for viewing and interacting with items in a collection using Directus.",{"title":907,"path":908,"stem":909,"description":910,"icon":14,"links":14},"Import & Export","\u002Fguides\u002Fcontent\u002Fimport-export","guides\u002F02.content\u002F4.import-export","Learn to import and export multiple items stored as files using Directus.",{"title":474,"path":912,"stem":913,"description":914,"icon":14,"links":14},"\u002Fguides\u002Fcontent\u002Flive-preview","guides\u002F02.content\u002F5.live-preview","Learn to set up your project for live previewing items from your application.",{"title":916,"path":917,"stem":918,"description":919,"icon":14,"links":14},"Content Versioning","\u002Fguides\u002Fcontent\u002Fcontent-versioning","guides\u002F02.content\u002F6.content-versioning","This guide covers the process of enabling and utilizing Content Versioning in Directus.",{"title":251,"path":921,"stem":922,"description":923,"icon":14,"links":14},"\u002Fguides\u002Fcontent\u002Ftranslations","guides\u002F02.content\u002F7.translations","Both content and the data studio can be translated into multiple languages.",{"title":504,"path":925,"stem":926,"children":927,"description":929,"icon":14,"links":14},"\u002Fguides\u002Fcontent\u002Fvisual-editor","guides\u002F02.content\u002F8.visual-editor\u002F0.index",[928,930,935,940],{"title":504,"path":925,"stem":926,"description":929,"icon":14,"links":14},"The Directus visual editor module allows you to visually edit the content of your website directly in-place.",{"title":931,"path":932,"stem":933,"description":934,"icon":14,"links":14},"Frontend Library","\u002Fguides\u002Fcontent\u002Fvisual-editor\u002Ffrontend-library","guides\u002F02.content\u002F8.visual-editor\u002F1.frontend-library","A library that allows your website to communicate with your Directus project and enables Visual Editing.",{"title":936,"path":937,"stem":938,"description":939,"icon":14,"links":14},"Studio Module","\u002Fguides\u002Fcontent\u002Fvisual-editor\u002Fstudio-module","guides\u002F02.content\u002F8.visual-editor\u002F2.studio-module","Learn how to edit your website's content in place from within the Directus Studio.",{"title":941,"path":942,"stem":943,"description":944,"icon":14,"links":14},"Customization","\u002Fguides\u002Fcontent\u002Fvisual-editor\u002Fcustomization","guides\u002F02.content\u002F8.visual-editor\u002F3.customization","Customize the styling of your Visual Editing experience to suit your brand or website theming.",{"title":946,"path":947,"stem":948,"children":949,"description":951,"icon":14,"links":14},"Collaborative Editing","\u002Fguides\u002Fcontent\u002Fcollaborative-editing","guides\u002F02.content\u002F9.collaborative-editing\u002F0.index",[950,952,956,961],{"title":946,"path":947,"stem":948,"description":951,"icon":14,"links":14},"Directus Collaborative Editing enables real-time data synchronization and collaborative editing across collections, allowing multiple users to edit content simultaneously without conflicts.",{"title":171,"path":953,"stem":954,"description":955,"icon":14,"links":14},"\u002Fguides\u002Fcontent\u002Fcollaborative-editing\u002Fconfiguration","guides\u002F02.content\u002F9.collaborative-editing\u002F1.configuration","Learn how to configure Collaborative Editing in your Directus project.",{"title":957,"path":958,"stem":959,"description":960,"icon":14,"links":14},"Usage Guide","\u002Fguides\u002Fcontent\u002Fcollaborative-editing\u002Fusage","guides\u002F02.content\u002F9.collaborative-editing\u002F2.usage","Learn how to use Collaborative Editing for real-time collaboration on content in your Directus project.",{"title":962,"path":963,"stem":964,"description":965,"icon":14,"links":14},"Development & Custom Extensions","\u002Fguides\u002Fcontent\u002Fcollaborative-editing\u002Fdevelopment","guides\u002F02.content\u002F9.collaborative-editing\u002F3.development","Learn how Custom Interfaces integrate with Collaborative Editing in Directus.",{"title":74,"description":14,"icon":14,"links":14,"path":967,"stem":968,"children":969,"page":89},"\u002Fguides\u002Fauth","guides\u002F03.auth",[970,975,980,985,990,995,1000],{"title":971,"path":972,"stem":973,"description":974,"icon":14,"links":14},"Access Tokens","\u002Fguides\u002Fauth\u002Ftokens-cookies","guides\u002F03.auth\u002F1.tokens-cookies","Learn how to authenticate requests & explore standard, session, and static token types.",{"title":976,"path":977,"stem":978,"description":979,"icon":14,"links":14},"Access Control","\u002Fguides\u002Fauth\u002Faccess-control","guides\u002F03.auth\u002F2.access-control","Manage user and role permissions and policies for interacting with data in Directus.",{"title":981,"path":982,"stem":983,"description":984,"icon":14,"links":14},"Creating Users","\u002Fguides\u002Fauth\u002Fcreating-users","guides\u002F03.auth\u002F3.creating-users","Learn about creating users in directus, including API creation, inviting users, and seamless invites.",{"title":986,"path":987,"stem":988,"description":989,"icon":14,"links":14},"Email Login","\u002Fguides\u002Fauth\u002Femail-login","guides\u002F03.auth\u002F4.email-login","Learn about user registration, login with standard\u002Fsession tokens, refresh, logout, and resetting passwords.",{"title":991,"path":992,"stem":993,"description":994,"icon":14,"links":14},"Two-Factor Auth","\u002Fguides\u002Fauth\u002F2fa","guides\u002F03.auth\u002F5.2fa","Secure your logins with one-time codes! Learn how to generate secrets, enable\u002Fdisable 2FA.",{"title":996,"path":997,"stem":998,"description":999,"icon":14,"links":14},"Accountability","\u002Fguides\u002Fauth\u002Faccountability","guides\u002F03.auth\u002F6.accountability","Learn to audit user activity and enforce accountability using the activity feed.",{"title":1001,"path":1002,"stem":1003,"children":1004,"description":1006,"icon":14,"links":14},"Single Sign-On","\u002Fguides\u002Fauth\u002Fsso","guides\u002F03.auth\u002F7.sso\u002F1.index",[1005,1007],{"title":1001,"path":1002,"stem":1003,"description":1006,"icon":14,"links":14},"Single Sign-On is a mechanism which allows to use external providers to login into systems.",{"title":1008,"path":1009,"stem":1010,"description":1011,"icon":14,"links":14},"Seamless SSO","\u002Fguides\u002Fauth\u002Fsso\u002Fseamless","guides\u002F03.auth\u002F7.sso\u002F2.seamless","Seamless SSO is a setup to allow logging in without the user ever seeing Directus' login page.",{"title":1013,"description":14,"icon":14,"links":14,"path":1014,"stem":1015,"children":1016,"page":89},"APIs","\u002Fguides\u002Fconnect","guides\u002F04.connect",[1017,1021,1026,1031,1036,1041,1046],{"title":16,"path":1018,"stem":1019,"description":1020,"icon":14,"links":14},"\u002Fguides\u002Fconnect\u002Fauthentication","guides\u002F04.connect\u002F1.authentication","Discover how to authenticate Directus API requests using authorization headers, session cookies, or query parameters.",{"title":1022,"path":1023,"stem":1024,"description":1025,"icon":14,"links":14},"Filter Rules","\u002Fguides\u002Fconnect\u002Ffilter-rules","guides\u002F04.connect\u002F2.filter-rules","Learn about filter rules in Directus - available operators, filter syntax, relational fields, dynamic variables, logical operators, and functions parameters. Understand how to build complex filters for permissions, validations, and automations.",{"title":1027,"path":1028,"stem":1029,"description":1030,"icon":14,"links":14},"Query Parameters","\u002Fguides\u002Fconnect\u002Fquery-parameters","guides\u002F04.connect\u002F3.query-parameters","Learn about Directus query parameters - fields, filter, search, sort, limit, offset, page, aggregate, groupBy, deep, alias, and export. Understand how to customize your API requests and retrieve specific data from your collections.",{"title":1032,"path":1033,"stem":1034,"description":1035,"icon":14,"links":14},"Relational Data","\u002Fguides\u002Fconnect\u002Frelations","guides\u002F04.connect\u002F4.relations","Directus enables you to manage and interact with relational data. This section will guide you through the different types of relationships and how to work with them.",{"title":1037,"path":1038,"stem":1039,"description":1040,"icon":14,"links":14},"Errors","\u002Fguides\u002Fconnect\u002Ferrors","guides\u002F04.connect\u002F5.errors","Learn how Directus returns errors over REST, GraphQL, and the SDK. Includes core error codes, HTTP status codes, response shape, and patterns for handling errors in your application.",{"title":1042,"path":1043,"stem":1044,"description":1045,"icon":14,"links":14},"Directus SDK","\u002Fguides\u002Fconnect\u002Fsdk","guides\u002F04.connect\u002F6.sdk","A JavaScript and TypeScript library that simplifies working with Directus.",{"title":1047,"path":1048,"stem":1049,"children":1050,"page":89},"Json","\u002Fguides\u002Fconnect\u002Fjson","guides\u002F04.connect\u002F7.json",[1051,1056],{"title":1052,"path":1053,"stem":1054,"description":1055,"icon":14,"links":14},"Quickstart","\u002Fguides\u002Fconnect\u002Fjson\u002Fquickstart","guides\u002F04.connect\u002F7.json\u002F1.quickstart","Quickstart for extracting and filtering values inside JSON fields with the json() function and _json filter operator.",{"title":1057,"path":1058,"stem":1059,"description":1060,"icon":14,"links":14},"Advanced Querying","\u002Fguides\u002Fconnect\u002Fjson\u002Fadvanced-querying","guides\u002F04.connect\u002F7.json\u002F2.advanced-querying","Advanced JSON querying for the `json(field, path)` function and `_json` filter operator, including path notation, relational queries, GraphQL support, SDK usage, depth limits, and database-specific behavior.",{"title":373,"description":14,"icon":14,"links":14,"path":1062,"stem":1063,"children":1064,"page":89},"\u002Fguides\u002Ffiles","guides\u002F05.files",[1065,1070,1075,1080,1085],{"title":1066,"path":1067,"stem":1068,"description":1069,"icon":14,"links":14},"Upload Files","\u002Fguides\u002Ffiles\u002Fupload","guides\u002F05.files\u002F1.upload","Learn to upload files to Directus via both the data studio or API.",{"title":1071,"path":1072,"stem":1073,"description":1074,"icon":14,"links":14},"Download Files","\u002Fguides\u002Ffiles\u002Fdownload","guides\u002F05.files\u002F2.download","Learn to download content from the File Library",{"title":1076,"path":1077,"stem":1078,"description":1079,"icon":14,"links":14},"Manage Files","\u002Fguides\u002Ffiles\u002Fmanage","guides\u002F05.files\u002F3.manage","Learn to view, modify, edit and set files' focal points.",{"title":1081,"path":1082,"stem":1083,"description":1084,"icon":14,"links":14},"Access Files","\u002Fguides\u002Ffiles\u002Faccess","guides\u002F05.files\u002F4.access","Learn how to access uploaded files, authenticate, provide optional filenames and directly download them.",{"title":1086,"path":1087,"stem":1088,"description":1089,"icon":14,"links":14},"Transform Files","\u002Fguides\u002Ffiles\u002Ftransform","guides\u002F05.files\u002F5.transform","Learn how to transform files and set custom presets for these transformations.",{"title":378,"description":14,"icon":14,"links":14,"path":1091,"stem":1092,"children":1093},"\u002Fguides\u002Fflows","guides\u002F06.flows\u002Findex",[1094,1096,1101,1106,1111],{"title":378,"path":1091,"stem":1092,"description":1095,"icon":14,"links":14},"Flows enable custom, event-driven data processing and task automation within Directus.",{"title":1097,"path":1098,"stem":1099,"description":1100,"icon":14,"links":14},"Data Chain","\u002Fguides\u002Fflows\u002Fdata-chain","guides\u002F06.flows\u002F2.data-chain","Data chains are created by each flow and hold information that can be accessed within different operations.",{"title":1102,"path":1103,"stem":1104,"description":1105,"icon":14,"links":14},"Triggers","\u002Fguides\u002Fflows\u002Ftriggers","guides\u002F06.flows\u002F3.triggers","Triggers define the action or events that start flows.",{"title":1107,"path":1108,"stem":1109,"description":1110,"icon":14,"links":14},"Operations","\u002Fguides\u002Fflows\u002Foperations","guides\u002F06.flows\u002F4.operations","Operations are individual customizable actions in a flow.",{"title":1112,"path":1113,"stem":1114,"description":1115,"icon":14,"links":14},"Manage Flows","\u002Fguides\u002Fflows\u002Fmanage-flows","guides\u002F06.flows\u002F5.manage-flows","Organize, find, activate, duplicate, import, and export Flows from the Flows module.",{"title":86,"description":14,"icon":14,"links":14,"path":1117,"stem":1118,"children":1119,"page":89},"\u002Fguides\u002Frealtime","guides\u002F07.realtime",[1120,1124,1129,1134],{"title":16,"path":1121,"stem":1122,"description":1123,"icon":14,"links":14},"\u002Fguides\u002Frealtime\u002Fauthentication","guides\u002F07.realtime\u002F1.authentication","Learn to implement the three authentication modes.",{"title":1125,"path":1126,"stem":1127,"description":1128,"icon":14,"links":14},"Subscriptions","\u002Fguides\u002Frealtime\u002Fsubscriptions","guides\u002F07.realtime\u002F2.subscriptions","Learn to manage realtime subscriptions with both websockets and GraphQL.",{"title":1130,"path":1131,"stem":1132,"description":1133,"icon":14,"links":14},"Actions","\u002Fguides\u002Frealtime\u002Factions","guides\u002F07.realtime\u002F3.actions","Learn to execute CRUD actions via websockets.",{"title":1135,"path":1136,"stem":1137,"description":1138,"icon":14,"links":14},"Custom WebSocket Handlers","\u002Fguides\u002Frealtime\u002Fcustom-handlers","guides\u002F07.realtime\u002F4.custom-handlers","Build custom WebSocket message handlers, push messages to connected clients, and react to WebSocket events using hook extensions.",{"title":1140,"description":14,"icon":14,"links":14,"path":1141,"stem":1142,"children":1143,"page":89},"Insights","\u002Fguides\u002Finsights","guides\u002F08.insights",[1144,1148],{"title":226,"path":1145,"stem":1146,"description":1147,"icon":14,"links":14},"\u002Fguides\u002Finsights\u002Foverview","guides\u002F08.insights\u002F1.overview","Insights is a module in Directus that allows rapid, no-code build-out of analytics dashboards.",{"title":1149,"path":1150,"stem":1151,"description":1152,"icon":14,"links":14},"Panels","\u002Fguides\u002Finsights\u002Fpanels","guides\u002F08.insights\u002F2.panels","Panels are the building-blocks you can add onto insights dashboards to create, save and display data analytics.",{"title":368,"description":14,"icon":14,"links":14,"path":1154,"stem":1155,"children":1156,"page":89},"\u002Fguides\u002Fextensions","guides\u002F09.extensions",[1157,1161,1165,1197,1248,1253,1265],{"title":226,"path":1158,"stem":1159,"description":1160,"icon":14,"links":14},"\u002Fguides\u002Fextensions\u002Foverview","guides\u002F09.extensions\u002F0.overview","Extensions are used to extend the functionality of Directus.",{"title":1052,"path":1162,"stem":1163,"description":1164,"icon":14,"links":14},"\u002Fguides\u002Fextensions\u002Fquickstart","guides\u002F09.extensions\u002F1.quickstart","This guide will cover how to get started with developing an extension for Directus.",{"title":1166,"path":1167,"stem":1168,"children":1169,"description":1171,"icon":14,"links":14},"API Extensions","\u002Fguides\u002Fextensions\u002Fapi-extensions","guides\u002F09.extensions\u002F2.api-extensions\u002F0.index",[1170,1172,1177,1182,1187,1192],{"title":1166,"path":1167,"stem":1168,"description":1171,"icon":14,"links":14},"API Extensions extend the functionality of the API.",{"title":1173,"path":1174,"stem":1175,"description":1176,"icon":14,"links":14},"Event Hooks","\u002Fguides\u002Fextensions\u002Fapi-extensions\u002Fhooks","guides\u002F09.extensions\u002F2.api-extensions\u002F1.hooks","Hooks allow running code when during the Directus lifecycle or database events.",{"title":1178,"path":1179,"stem":1180,"description":1181,"icon":14,"links":14},"API Endpoints","\u002Fguides\u002Fextensions\u002Fapi-extensions\u002Fendpoints","guides\u002F09.extensions\u002F2.api-extensions\u002F2.endpoints","Endpoints allow you to register new API routes in your Directus project.",{"title":1183,"path":1184,"stem":1185,"description":1186,"icon":14,"links":14},"Flow Operations","\u002Fguides\u002Fextensions\u002Fapi-extensions\u002Foperations","guides\u002F09.extensions\u002F2.api-extensions\u002F3.operations","Operations are single steps in a Flow - the no-code automation tool in Directus.",{"title":1188,"path":1189,"stem":1190,"description":1191,"icon":14,"links":14},"Services","\u002Fguides\u002Fextensions\u002Fapi-extensions\u002Fservices","guides\u002F09.extensions\u002F2.api-extensions\u002F4.services","When building extensions, you may use internal Directus services directly.",{"title":1193,"path":1194,"stem":1195,"description":1196,"icon":14,"links":14},"Sandbox","\u002Fguides\u002Fextensions\u002Fapi-extensions\u002Fsandbox","guides\u002F09.extensions\u002F2.api-extensions\u002F5.sandbox","Sandboxed Extensions run in an isolated environment and must request permission scopes.",{"title":1198,"path":1199,"stem":1200,"children":1201,"description":1203,"icon":14,"links":14},"App Extensions","\u002Fguides\u002Fextensions\u002Fapp-extensions","guides\u002F09.extensions\u002F3.app-extensions\u002F0.index",[1202,1204,1209,1214,1219,1224,1229,1234,1238,1243],{"title":1198,"path":1199,"stem":1200,"description":1203,"icon":14,"links":14},"App Extensions extend the functionality of the Data Studio.",{"title":1205,"path":1206,"stem":1207,"description":1208,"icon":14,"links":14},"Item Page Interfaces","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Finterfaces","guides\u002F09.extensions\u002F3.app-extensions\u002F1.interfaces","Interfaces are form inputs used primarily on the Directus item page.",{"title":1210,"path":1211,"stem":1212,"description":1213,"icon":14,"links":14},"Inline Displays","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Fdisplays","guides\u002F09.extensions\u002F3.app-extensions\u002F2.displays","Displays are used to display a single value throughout the Data Studio.",{"title":1215,"path":1216,"stem":1217,"description":1218,"icon":14,"links":14},"Collection Page Layouts","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Flayouts","guides\u002F09.extensions\u002F3.app-extensions\u002F3.layouts","Layouts are used to display a list of items on collection pages in different ways.",{"title":1220,"path":1221,"stem":1222,"description":1223,"icon":14,"links":14},"Dashboard Panels","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Fpanels","guides\u002F09.extensions\u002F3.app-extensions\u002F4.panels","Panels are customizable components within Directus Insights dashboards.",{"title":1225,"path":1226,"stem":1227,"description":1228,"icon":14,"links":14},"Custom Modules","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Fmodules","guides\u002F09.extensions\u002F3.app-extensions\u002F5.modules","Modules are top-level areas of the Data Studio, navigated to from the left-hand module bar.",{"title":1230,"path":1231,"stem":1232,"description":1233,"icon":14,"links":14},"Custom Themes","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Fthemes","guides\u002F09.extensions\u002F3.app-extensions\u002F6.themes","Themes are used to style elements of the Data Studio including colors and fonts.",{"title":877,"path":1235,"stem":1236,"description":1237,"icon":14,"links":14},"\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Frichtext","guides\u002F09.extensions\u002F3.app-extensions\u002F7.richtext","Rich text extensions add Tiptap nodes, marks, and toolbar buttons to the WYSIWYG interface.",{"title":1239,"path":1240,"stem":1241,"description":1242,"icon":14,"links":14},"UI Library","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Fui-library","guides\u002F09.extensions\u002F3.app-extensions\u002F8.ui-library","Directus offers globally-registered UI components for building extensions.",{"title":1244,"path":1245,"stem":1246,"description":1247,"icon":14,"links":14},"Composables","\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Fcomposables","guides\u002F09.extensions\u002F3.app-extensions\u002F9.composables","Vue composables for working with Directus services when building extensions.",{"title":1249,"path":1250,"stem":1251,"description":1252,"icon":14,"links":14},"Bundling Extensions","\u002Fguides\u002Fextensions\u002Fbundles","guides\u002F09.extensions\u002F4.bundles","Bundles are a way to group extensions together as a single distributable package.",{"title":1254,"path":1255,"stem":1256,"children":1257,"description":1259,"icon":14,"links":14},"Marketplace","\u002Fguides\u002Fextensions\u002Fmarketplace","guides\u002F09.extensions\u002F5.marketplace\u002F0.index",[1258,1260],{"title":1254,"path":1255,"stem":1256,"description":1259,"icon":14,"links":14},"The Directus Marketplace provides a way for users to install extensions in their projects directly the Data Studio.",{"title":1261,"path":1262,"stem":1263,"description":1264,"icon":14,"links":14},"Publishing Extensions","\u002Fguides\u002Fextensions\u002Fmarketplace\u002Fpublishing","guides\u002F09.extensions\u002F5.marketplace\u002F1.publishing","Publish extensions to the Directus Marketplace via npm, including required metadata, best practices, and author profile setup.",{"title":1266,"path":1267,"stem":1268,"description":1269,"icon":14,"links":14},"CLI","\u002Fguides\u002Fextensions\u002Fcli","guides\u002F09.extensions\u002F6.cli","Using the create-directus-extension to build, validate and manage extensions.",{"title":1271,"path":1272,"stem":1273,"children":1274,"description":14,"icon":14,"links":14},"Environment Sync","\u002Fguides\u002Fenvironment-sync","guides\u002F10.environment-sync\u002F0.index",[1275,1277,1281,1286,1291,1296,1301],{"title":226,"path":1272,"stem":1273,"description":1276,"icon":14,"links":14},"Move schema and configuration between Directus instances through sync files you commit to git, using the Directus CLI.",{"title":1052,"path":1278,"stem":1279,"description":1280,"icon":14,"links":14},"\u002Fguides\u002Fenvironment-sync\u002Fquickstart","guides\u002F10.environment-sync\u002F1.quickstart","Run the full pull, diff, push loop against two throwaway Directus instances, and see what the CLI does at every step.",{"title":1282,"path":1283,"stem":1284,"description":1285,"icon":14,"links":14},"How It Works","\u002Fguides\u002Fenvironment-sync\u002Fhow-it-works","guides\u002F10.environment-sync\u002F2.how-it-works","The mental model behind Environment Sync, including sync files as the source of truth, record identity across instances, how a push applies, and the safety rules every command follows.",{"title":1287,"path":1288,"stem":1289,"description":1290,"icon":14,"links":14},"Common Workflows","\u002Fguides\u002Fenvironment-sync\u002Fcommon-workflows","guides\u002F10.environment-sync\u002F3.common-workflows","End-to-end walkthroughs of the most common Environment Sync workflows, from promoting changes to production to adopting sync on an existing project, rolling back, and recovering a drifted environment.",{"title":1292,"path":1293,"stem":1294,"description":1295,"icon":14,"links":14},"CI & Automation","\u002Fguides\u002Fenvironment-sync\u002Fci-and-automation","guides\u002F10.environment-sync\u002F4.ci-and-automation","Post the production diff on every pull request and push on merge, with tokens from environment variables, machine-readable JSON reports, and explicit flags in place of prompts.",{"title":1297,"path":1298,"stem":1299,"description":1300,"icon":14,"links":14},"Secrets & Limitations","\u002Fguides\u002Fenvironment-sync\u002Fsecrets-and-limitations","guides\u002F10.environment-sync\u002F5.secrets-and-limitations","How Environment Sync keeps secret values out of the files you commit, the one exception to review before publishing a repository, and what the tool deliberately does not do.",{"title":1302,"path":1303,"stem":1304,"description":1305,"icon":14,"links":14},"Reference","\u002Fguides\u002Fenvironment-sync\u002Freference","guides\u002F10.environment-sync\u002F6.reference","Every Environment Sync command and flag, the directus.config.json format, credential resolution, scope tables, push modes, deletion gates, and JSON report formats.",{"title":1307,"path":1308,"stem":1309,"children":1310,"description":14,"icon":14,"links":14},"Deployments","\u002Fguides\u002Fdeployments","guides\u002F11.deployments\u002F0.index",[1311,1313],{"title":226,"path":1308,"stem":1309,"description":1312,"icon":14,"links":14},"Trigger, monitor, and manage frontend deployments directly from Directus.",{"title":1314,"path":1315,"stem":1316,"description":1317,"icon":14,"links":14},"Security","\u002Fguides\u002Fdeployments\u002Fsecurity","guides\u002F11.deployments\u002F1.security","Access control, permissions, and credential protection for the Deployment module.",{"title":343,"path":1319,"stem":1320,"children":1321,"description":14,"icon":14,"links":14},"\u002Fguides\u002Fai","guides\u002F12.ai\u002F0.index",[1322,1325,1356,1411],{"title":1323,"path":1319,"stem":1320,"description":1324,"icon":14,"links":14},"AI + Directus","Use AI to interact with Directus - either through the built-in AI Assistant or by connecting external AI tools via MCP.",{"title":1326,"path":1327,"stem":1328,"children":1329,"description":14,"icon":14,"links":14},"AI Assistant","\u002Fguides\u002Fai\u002Fassistant","guides\u002F12.ai\u002F1.assistant\u002F0.index",[1330,1332,1337,1342,1347,1352],{"title":226,"path":1327,"stem":1328,"description":1331,"icon":14,"links":14},"Chat with an AI assistant directly inside Directus. Create content, manage your schema, trigger automations, and explore your data through natural conversation.",{"title":1333,"path":1334,"stem":1335,"description":1336,"icon":14,"links":14},"Setup","\u002Fguides\u002Fai\u002Fassistant\u002Fsetup","guides\u002F12.ai\u002F1.assistant\u002F1.setup","Configure AI Assistant by adding your AI provider API keys and customizing assistant behavior.",{"title":1338,"path":1339,"stem":1340,"description":1341,"icon":14,"links":14},"Usage","\u002Fguides\u002Fai\u002Fassistant\u002Fusage","guides\u002F12.ai\u002F1.assistant\u002F2.usage","Learn how to use AI Assistant to interact with your Directus instance through natural conversation.",{"title":1343,"path":1344,"stem":1345,"description":1346,"icon":14,"links":14},"Tools","\u002Fguides\u002Fai\u002Fassistant\u002Ftools","guides\u002F12.ai\u002F1.assistant\u002F3.tools","Reference of all tools available to AI Assistant for interacting with your Directus instance.",{"title":1348,"path":1349,"stem":1350,"description":1351,"icon":14,"links":14},"Best Practices","\u002Fguides\u002Fai\u002Fassistant\u002Ftips","guides\u002F12.ai\u002F1.assistant\u002F4.tips","Get the most out of AI Assistant with practical tips, example prompts, and common pitfalls to avoid.",{"title":1314,"path":1353,"stem":1354,"description":1355,"icon":14,"links":14},"\u002Fguides\u002Fai\u002Fassistant\u002Fsecurity","guides\u002F12.ai\u002F1.assistant\u002F5.security","Security considerations for using AI Assistant safely with your Directus data.",{"title":1357,"path":1358,"stem":1359,"children":1360,"description":14,"icon":14,"links":14},"MCP Server","\u002Fguides\u002Fai\u002Fmcp","guides\u002F12.ai\u002F2.mcp\u002F0.index",[1361,1363,1368,1373,1377,1382,1387,1392,1396],{"title":226,"path":1358,"stem":1359,"description":1362,"icon":14,"links":14},"Connect AI assistants directly to your Directus instance. Let Claude, ChatGPT, and other AI tools manage your content without manual copy-pasting.",{"title":1364,"path":1365,"stem":1366,"description":1367,"icon":14,"links":14},"Installation","\u002Fguides\u002Fai\u002Fmcp\u002Finstallation","guides\u002F12.ai\u002F2.mcp\u002F1.installation","Set up the Directus MCP server and connect your AI tools in under 5 minutes.",{"title":1369,"path":1370,"stem":1371,"description":1372,"icon":14,"links":14},"Use Cases","\u002Fguides\u002Fai\u002Fmcp\u002Fuse-cases","guides\u002F12.ai\u002F2.mcp\u002F2.use-cases","Real examples of how to use AI with your Directus content to save time and reduce repetitive work.",{"title":1343,"path":1374,"stem":1375,"description":1376,"icon":14,"links":14},"\u002Fguides\u002Fai\u002Fmcp\u002Ftools","guides\u002F12.ai\u002F2.mcp\u002F3.tools","Learn about the tools available in the Directus remote MCP server and how they enable AI-powered content management.",{"title":1378,"path":1379,"stem":1380,"description":1381,"icon":14,"links":14},"Prompts","\u002Fguides\u002Fai\u002Fmcp\u002Fprompts","guides\u002F12.ai\u002F2.mcp\u002F4.prompts","Learn how to configure and use stored prompts with the Directus MCP Server.",{"title":1383,"path":1384,"stem":1385,"description":1386,"icon":14,"links":14},"Troubleshooting","\u002Fguides\u002Fai\u002Fmcp\u002Ftroubleshooting","guides\u002F12.ai\u002F2.mcp\u002F5.troubleshooting","Common issues and solutions when setting up and using the Directus MCP server.",{"title":1388,"path":1389,"stem":1390,"description":1391,"icon":14,"links":14},"OAuth","\u002Fguides\u002Fai\u002Fmcp\u002Foauth","guides\u002F12.ai\u002F2.mcp\u002F6.oauth","Configure browser-based OAuth authorization for the Directus MCP server.",{"title":1314,"path":1393,"stem":1394,"description":1395,"icon":14,"links":14},"\u002Fguides\u002Fai\u002Fmcp\u002Fsecurity","guides\u002F12.ai\u002F2.mcp\u002F7.security","Practical security guidelines for using the Directus MCP server safely and protecting your data.",{"title":1397,"path":1398,"stem":1399,"children":1400,"description":14,"icon":14,"links":14},"Local MCP","\u002Fguides\u002Fai\u002Fmcp\u002Flocal-mcp","guides\u002F12.ai\u002F2.mcp\u002F8.local-mcp\u002F0.index",[1401,1403,1407],{"title":1364,"path":1398,"stem":1399,"description":1402,"icon":14,"links":14},"The Directus Content MCP Server allows you to interact with your Directus data through AI tools using the Model Context Protocol.",{"title":1343,"path":1404,"stem":1405,"description":1406,"icon":14,"links":14},"\u002Fguides\u002Fai\u002Fmcp\u002Flocal-mcp\u002Ftools","guides\u002F12.ai\u002F2.mcp\u002F8.local-mcp\u002F1.tools","Learn about the tools available in the local Directus Content MCP Server and how to configure them.",{"title":1378,"path":1408,"stem":1409,"description":1410,"icon":14,"links":14},"\u002Fguides\u002Fai\u002Fmcp\u002Flocal-mcp\u002Fprompts","guides\u002F12.ai\u002F2.mcp\u002F8.local-mcp\u002F2.prompts","Configure stored prompts with the local MCP server using environment variables and manual collection setup.",{"title":1412,"path":1413,"stem":1414,"description":1415,"icon":14,"links":14},"AI Translations","\u002Fguides\u002Fai\u002Ftranslations","guides\u002F12.ai\u002F3.translations","Translate content into multiple languages using AI models directly from the Directus translations interface.",{"title":1417,"description":14,"icon":14,"links":14,"path":1418,"stem":1419,"children":1420},"Integrations","\u002Fguides\u002Fintegrations","guides\u002F13.integrations\u002Findex",[1421,1423,1444,1466,1485,1496,1507,1513,1520],{"title":1417,"path":1418,"stem":1419,"description":1422,"icon":14,"links":14},"Connect Directus with third-party tools and services to extend functionality and automate workflows.",{"title":1424,"path":1425,"stem":1426,"children":1427,"description":14,"icon":14,"links":14},"n8n","\u002Fguides\u002Fintegrations\u002Fn8n","guides\u002F13.integrations\u002F1.n8n\u002F0.index",[1428,1431,1435,1440],{"title":1429,"path":1425,"stem":1426,"description":1430,"icon":14,"links":14},"Integration","Connect Directus with n8n to automate workflows, sync data, and integrate your CMS with other services using the Directus community node.",{"title":1130,"path":1432,"stem":1433,"description":1434,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fn8n\u002Fdirectus-n8n-actions","guides\u002F13.integrations\u002F1.n8n\u002Fdirectus-n8n-actions","Complete guide for using Directus actions in n8n workflows, including working with items, users, and files.",{"title":1436,"path":1437,"stem":1438,"description":1439,"icon":14,"links":14},"Advanced","\u002Fguides\u002Fintegrations\u002Fn8n\u002Fdirectus-n8n-advanced","guides\u002F13.integrations\u002F1.n8n\u002Fdirectus-n8n-advanced","Advanced guide for using Directus raw CRUD operations in n8n, including raw JSON operations, complex filters, relational queries, and query parameters.",{"title":1102,"path":1441,"stem":1442,"description":1443,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fn8n\u002Fdirectus-n8n-triggers","guides\u002F13.integrations\u002F1.n8n\u002Fdirectus-n8n-triggers","Complete guide for using Directus triggers in n8n workflows to automate workflows when events happen in Directus.",{"title":1445,"path":1446,"stem":1447,"children":1448,"description":14,"icon":14,"links":14},"Clay","\u002Fguides\u002Fintegrations\u002Fclay","guides\u002F13.integrations\u002F2.clay\u002F0.index",[1449,1451,1456,1461],{"title":1429,"path":1446,"stem":1447,"description":1450,"icon":14,"links":14},"Connect Directus with Clay to automate data enrichment and sync content between platforms using webhooks and HTTP API templates.",{"title":1452,"path":1453,"stem":1454,"description":1455,"icon":14,"links":14},"Data Operations","\u002Fguides\u002Fintegrations\u002Fclay\u002Fdirectus-clay-data-operations","guides\u002F13.integrations\u002F2.clay\u002Fdirectus-clay-data-operations","Advanced techniques for working with Directus data in Clay, including filters, pagination, common use cases, and best practices.",{"title":1457,"path":1458,"stem":1459,"description":1460,"icon":14,"links":14},"Templates","\u002Fguides\u002Fintegrations\u002Fclay\u002Fuse-clay-templates-with-directus","guides\u002F13.integrations\u002F2.clay\u002Fuse-clay-templates-with-directus","Learn how to use Clay's pre-built HTTP API templates to connect with Directus for data enrichment and synchronization.",{"title":1462,"path":1463,"stem":1464,"description":1465,"icon":14,"links":14},"Webhooks","\u002Fguides\u002Fintegrations\u002Fclay\u002Fuse-directus-webhooks-with-clay","guides\u002F13.integrations\u002F2.clay\u002Fuse-directus-webhooks-with-clay","Learn how to set up Directus Flows to automatically send data to Clay webhooks for real-time data synchronization.",{"title":1467,"path":1468,"stem":1469,"children":1470,"description":14,"icon":14,"links":14},"Zapier","\u002Fguides\u002Fintegrations\u002Fzapier","guides\u002F13.integrations\u002F3.zapier\u002F0.index",[1471,1473,1477,1481],{"title":1429,"path":1468,"stem":1469,"description":1472,"icon":14,"links":14},"Connect Directus with Zapier to automate workflows, sync data, and integrate your CMS with thousands of other apps using the Directus Zapier integration.",{"title":1130,"path":1474,"stem":1475,"description":1476,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fzapier\u002Factions","guides\u002F13.integrations\u002F3.zapier\u002Factions","Complete guide for using Directus actions in Zapier workflows, including working with items, users, and files.",{"title":1436,"path":1478,"stem":1479,"description":1480,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fzapier\u002Fadvanced","guides\u002F13.integrations\u002F3.zapier\u002Fadvanced","Advanced guide for using Directus API features in Zapier, including raw request actions, advanced filtering, and custom API calls.",{"title":1102,"path":1482,"stem":1483,"description":1484,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fzapier\u002Ftriggers","guides\u002F13.integrations\u002F3.zapier\u002Ftriggers","Complete guide for using Directus triggers in Zapier workflows to automatically start Zaps when events happen in Directus.",{"title":1486,"path":1487,"stem":1488,"children":1489,"description":14,"icon":14,"links":14},"Vercel","\u002Fguides\u002Fintegrations\u002Fvercel","guides\u002F13.integrations\u002F4.vercel\u002F0.index",[1490,1492],{"title":1486,"path":1487,"stem":1488,"description":1491,"icon":14,"links":14},"Connect Directus with Vercel to trigger deployments, monitor build status, and manage your frontend projects directly from your Directus instance.",{"title":1307,"path":1493,"stem":1494,"description":1495,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fvercel\u002Fdeployments","guides\u002F13.integrations\u002F4.vercel\u002Fdeployments","Complete guide for triggering deployments, monitoring build status, and viewing logs for your Vercel projects from Directus.",{"title":1497,"path":1498,"stem":1499,"children":1500,"description":14,"icon":14,"links":14},"Netlify","\u002Fguides\u002Fintegrations\u002Fnetlify","guides\u002F13.integrations\u002F5.netlify\u002F0.index",[1501,1503],{"title":1497,"path":1498,"stem":1499,"description":1502,"icon":14,"links":14},"Integrate Directus with Netlify to deploy your sites, track build progress, and manage frontend projects from within your Directus instance.",{"title":1307,"path":1504,"stem":1505,"description":1506,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fnetlify\u002Fdeployments","guides\u002F13.integrations\u002F5.netlify\u002Fdeployments","Full guide for triggering builds, tracking deployment progress, and viewing logs for your Netlify sites from Directus.",{"title":1429,"path":1508,"stem":1509,"children":1510,"description":1512,"icon":14,"links":14},"\u002Fguides\u002Fintegrations\u002Fairbyte","guides\u002F13.integrations\u002F6.airbyte\u002F0.index",[1511],{"title":1429,"path":1508,"stem":1509,"description":1512,"icon":14,"links":14},"Sync data from Directus collections into a warehouse or database using the Directus Airbyte source connector.",{"title":1514,"path":1515,"stem":1516,"children":1517,"description":14,"icon":14,"links":14},"Framer","\u002Fguides\u002Fintegrations\u002Fframer","guides\u002F13.integrations\u002F6.framer\u002F0.index",[1518],{"title":1514,"path":1515,"stem":1516,"description":1519,"icon":14,"links":14},"Connect your Directus collections to Framer's CMS to sync content in both directions using the Directus Framer plugin.",{"title":1521,"path":1522,"stem":1523,"children":1524,"description":14,"icon":14,"links":14},"Supabase","\u002Fguides\u002Fintegrations\u002Fsupabase","guides\u002F13.integrations\u002F6.supabase\u002F0.index",[1525,1527,1532],{"title":1521,"path":1522,"stem":1523,"description":1526,"icon":14,"links":14},"Connect self-hosted Directus to Supabase Postgres and Supabase Storage, and use Directus Labs starters with a Supabase database.",{"title":1528,"path":1529,"stem":1530,"description":1531,"icon":14,"links":14},"Connect Supabase Postgres to Directus","\u002Fguides\u002Fintegrations\u002Fsupabase\u002Fconnect-supabase-postgres-to-directus","guides\u002F13.integrations\u002F6.supabase\u002Fconnect-supabase-postgres-to-directus","Configure a self-hosted Directus instance to use Supabase Postgres via the session pooler and verify the setup.",{"title":1533,"path":1534,"stem":1535,"description":1536,"icon":14,"links":14},"Use Supabase Storage with Directus","\u002Fguides\u002Fintegrations\u002Fsupabase\u002Fuse-supabase-storage-with-directus","guides\u002F13.integrations\u002F6.supabase\u002Fuse-supabase-storage-with-directus","Configure Directus to store files in Supabase Storage using the S3-compatible API and the Directus S3 storage driver.",{"title":1314,"path":1538,"stem":1539,"children":1540,"page":89},"\u002Fguides\u002Fsecurity","guides\u002F14.security",[1541],{"title":1542,"path":1543,"stem":1544,"description":1545,"icon":14,"links":14},"Security Best Practices","\u002Fguides\u002Fsecurity\u002Fbest-practices","guides\u002F14.security\u002F1.best-practices","Harden a Directus project.",{"title":1547,"path":1548,"stem":1549,"children":1550,"page":89},"Licensing","\u002Flicensing","licensing",[1551,1555,1560],{"title":226,"path":1552,"stem":1553,"description":1554,"icon":14,"links":14},"\u002Flicensing\u002Foverview","licensing\u002F1.overview","How Directus licensing works, how to add a license, and what happens when you exceed your plan.",{"title":1556,"path":1557,"stem":1558,"description":1559,"icon":14,"links":14},"Telemetry","\u002Flicensing\u002Ftelemetry","licensing\u002F2.telemetry","Exactly what usage data Directus collects, when it is sent, and how to disable it.",{"title":1561,"path":1562,"stem":1563,"description":1564,"icon":14,"links":14},"Open Innovation Grant","\u002Flicensing\u002Fopen-innovation-grant","licensing\u002F3.open-innovation-grant","How the Open Innovation Grant works, what it includes, and how its activations apply to multiple environments, CI pipelines, and database restores.",{"title":1566,"path":1567,"stem":1568,"description":1569,"icon":14,"links":14},"Docs MCP Server","\u002Fmcp-help","mcp-help","Connect Claude, Cursor, VS Code, or any MCP-compatible client directly to the Directus documentation.",{"title":1571,"path":1572,"stem":1573,"children":1574,"description":1576,"icon":1577,"links":14},"Releases","\u002Freleases","releases\u002F0.index",[1575,1578,1583],{"title":1571,"path":1572,"stem":1573,"description":1576,"icon":1577,"links":14},"Releases are how we roll out new features, updates, and fixes to Directus.","i-lucide-tag",{"title":1579,"path":1580,"stem":1581,"description":1582,"icon":14,"links":14},"Changelog","\u002Freleases\u002Fchangelog","releases\u002F2.changelog","A monthly summary of what's new from the Directus team.",{"title":1584,"path":1585,"stem":1586,"children":1587,"description":1589,"icon":14,"links":14},"Breaking Changes","\u002Freleases\u002Fbreaking-changes","releases\u002F3.breaking-changes\u002F0.index",[1588,1590,1594,1598],{"title":1584,"path":1585,"stem":1586,"description":1589,"icon":14,"links":14},"Breaking changes may require action on your part before upgrading.",{"title":1591,"path":1592,"stem":1593,"description":1589,"icon":14,"links":14},"Version 10","\u002Freleases\u002Fbreaking-changes\u002Fversion-10","releases\u002F3.breaking-changes\u002F1.version-10",{"title":1595,"path":1596,"stem":1597,"description":1589,"icon":14,"links":14},"Version 11","\u002Freleases\u002Fbreaking-changes\u002Fversion-11","releases\u002F3.breaking-changes\u002F2.version-11",{"title":1599,"path":1600,"stem":1601,"description":1589,"icon":14,"links":14},"Version 12","\u002Freleases\u002Fbreaking-changes\u002Fversion-12","releases\u002F3.breaking-changes\u002F3.version-12",{"title":1603,"description":14,"icon":14,"links":14,"path":1604,"stem":1605,"children":1606,"page":89},"Self-Hosting","\u002Fself-hosting","self-hosting",[1607,1611,1616,1621,1626,1631],{"title":226,"path":1608,"stem":1609,"description":1610,"icon":14,"links":14},"\u002Fself-hosting\u002Foverview","self-hosting\u002F1.overview","Self-hosting Directus means running the Directus software on your own infrastructure.",{"title":1612,"path":1613,"stem":1614,"description":1615,"icon":14,"links":14},"Requirements","\u002Fself-hosting\u002Frequirements","self-hosting\u002F2.requirements","This page outlines the requirements for self-hosting Directus.",{"title":1617,"path":1618,"stem":1619,"description":1620,"icon":14,"links":14},"Deployment","\u002Fself-hosting\u002Fdeploying","self-hosting\u002F3.deploying","This section covers the deployment process of Directus, including environment variables, versioning, persistence, and initial admin user setup.",{"title":1622,"path":1623,"stem":1624,"description":1625,"icon":14,"links":14},"Upgrading","\u002Fself-hosting\u002Fupgrading","self-hosting\u002F4.upgrading","Learn how to upgrade Directus to the latest version.",{"title":1627,"path":1628,"stem":1629,"description":1630,"icon":14,"links":14},"Including Extensions","\u002Fself-hosting\u002Fincluding-extensions","self-hosting\u002F5.including-extensions","Learn how to include extensions in your self-hosted Directus project.",{"title":1632,"path":1633,"stem":1634,"description":1635,"icon":14,"links":14},"Hardened Images","\u002Fself-hosting\u002Fhardened-images","self-hosting\u002F6.hardened-images","Understand Directus's hardened and distroless Docker images, and how to install extensions and run the CLI with them.",{"title":1637,"path":1638,"stem":1639,"children":1640},"Tutorials","\u002Ftutorials","tutorials",[1641,1644,1749,1790,1811,1928,1975],{"title":1637,"path":1638,"stem":1642,"description":1643,"icon":14,"links":14},"tutorials\u002Findex","This is a collection of step-by-step guides and practical examples to help you get the most out of our platform. Whether you're a beginner or an experienced user, our tutorials are designed to provide you with the knowledge and skills you need to succeed.",{"title":141,"path":1645,"stem":1646,"children":1647,"description":24,"icon":14,"links":14},"\u002Ftutorials\u002Fprojects","tutorials\u002F2.projects\u002Findex",[1648,1649,1654,1659,1664,1669,1674,1679,1684,1689,1694,1699,1704,1709,1714,1719,1724,1729,1734,1739,1744],{"title":141,"path":1645,"stem":1646,"description":24,"icon":14,"links":14},{"title":1650,"path":1651,"stem":1652,"description":1653,"icon":14,"links":14},"Build a Multi-User Chat with JavaScript and Directus Realtime","\u002Ftutorials\u002Fprojects\u002Fbuild-a-multi-user-chat-with-javascript-and-directus-realtime","tutorials\u002F2.projects\u002Fbuild-a-multi-user-chat-with-javascript-and-directus-realtime","Learn how to send and receive data over a realtime connection with JavaScript.",{"title":1655,"path":1656,"stem":1657,"description":1658,"icon":14,"links":14},"Build a Multi-User Chat with React and Directus Realtime","\u002Ftutorials\u002Fprojects\u002Fbuild-a-multi-user-chat-with-react-and-directus-realtime","tutorials\u002F2.projects\u002Fbuild-a-multi-user-chat-with-react-and-directus-realtime","Learn how to send and receive data over a realtime connection in React applications.",{"title":1660,"path":1661,"stem":1662,"description":1663,"icon":14,"links":14},"Build a Multi-User Chat with Vue.js and Directus Realtime","\u002Ftutorials\u002Fprojects\u002Fbuild-a-multi-user-chat-with-vue-js-and-directus-realtime","tutorials\u002F2.projects\u002Fbuild-a-multi-user-chat-with-vue-js-and-directus-realtime","Learn how to send and receive data over a realtime connection in a Vue.js application.",{"title":1665,"path":1666,"stem":1667,"description":1668,"icon":14,"links":14},"Build a Notebook Chrome Extension with Directus Auth","\u002Ftutorials\u002Fprojects\u002Fbuild-a-notebook-chrome-extension-with-directus-auth","tutorials\u002F2.projects\u002Fbuild-a-notebook-chrome-extension-with-directus-auth","Learn to build and integrate a Chrome Extension with Directus Auth.",{"title":1670,"path":1671,"stem":1672,"description":1673,"icon":14,"links":14},"Build a Realtime Chat App with Directus and Astro","\u002Ftutorials\u002Fprojects\u002Fbuild-a-realtime-chat-app-using-directus-and-astro","tutorials\u002F2.projects\u002Fbuild-a-realtime-chat-app-using-directus-and-astro","Learn how to setup Directus realtime with Astro.",{"title":1675,"path":1676,"stem":1677,"description":1678,"icon":14,"links":14},"Build a Realtime Chat App with Directus and Nuxt","\u002Ftutorials\u002Fprojects\u002Fbuild-a-realtime-chat-app-using-directus-and-nuxt","tutorials\u002F2.projects\u002Fbuild-a-realtime-chat-app-using-directus-and-nuxt","Learn how to setup Directus realtime with Nuxt.",{"title":1680,"path":1681,"stem":1682,"description":1683,"icon":14,"links":14},"Build a Realtime Chat App with Directus and Next.js","\u002Ftutorials\u002Fprojects\u002Fbuild-a-realtime-chat-app-with-directus-and-next","tutorials\u002F2.projects\u002Fbuild-a-realtime-chat-app-with-directus-and-next","Learn how to setup Directus realtime with Next.js.",{"title":1685,"path":1686,"stem":1687,"description":1688,"icon":14,"links":14},"Build a Realtime Chat App with Directus and SvelteKit","\u002Ftutorials\u002Fprojects\u002Fbuild-a-realtime-chat-app-with-directus-and-sveltekit","tutorials\u002F2.projects\u002Fbuild-a-realtime-chat-app-with-directus-and-sveltekit","Learn how to setup Directus realtime with SvelteKit.",{"title":1690,"path":1691,"stem":1692,"description":1693,"icon":14,"links":14},"Build a Testimonial Widget with SvelteKit and Directus","\u002Ftutorials\u002Fprojects\u002Fbuild-a-testimonial-widget-with-sveltekit-and-directus","tutorials\u002F2.projects\u002Fbuild-a-testimonial-widget-with-sveltekit-and-directus","Learn how to set up a testimonial widget using SvelteKit and Directus.",{"title":1695,"path":1696,"stem":1697,"description":1698,"icon":14,"links":14},"Build a User Feedback Widget with Vue.js","\u002Ftutorials\u002Fprojects\u002Fbuild-a-user-feedback-widget-with-vue-js","tutorials\u002F2.projects\u002Fbuild-a-user-feedback-widget-with-vue-js-","Learn how we built our docs feedback widget with Directus.",{"title":1700,"path":1701,"stem":1702,"description":1703,"icon":14,"links":14},"Build a Video Streaming App with SvelteKit and Directus","\u002Ftutorials\u002Fprojects\u002Fbuild-a-video-streaming-app-with-sveltekit-and-directus","tutorials\u002F2.projects\u002Fbuild-a-video-streaming-app-with-sveltekit-and-directus","Learn how to store and retrieve video metadata, and then build a streaming application.",{"title":1705,"path":1706,"stem":1707,"description":1708,"icon":14,"links":14},"Build an Ecommerce Platform with Next.js, Stripe, and Directus Flows","\u002Ftutorials\u002Fprojects\u002Fbuild-an-ecommerce-platform-with-next-js-stripe-and-directus-automate","tutorials\u002F2.projects\u002Fbuild-an-ecommerce-platform-with-next-js-stripe-and-directus-automate","Learn to integrate Stripe with Directus Flows to build an e-commerce website.",{"title":1710,"path":1711,"stem":1712,"description":1713,"icon":14,"links":14},"Build an Hotel Booking Platform with Next.js, Stripe, and Directus Flows","\u002Ftutorials\u002Fprojects\u002Fbuild-an-hotel-booking-platform-with-next-js-stripe-and-directus-automate","tutorials\u002F2.projects\u002Fbuild-an-hotel-booking-platform-with-next-js-stripe-and-directus-automate","Learn to build a hotel booking site with dynamic availability and payments via Stripe.",{"title":1715,"path":1716,"stem":1717,"description":1718,"icon":14,"links":14},"Build Directus Garden - A Passive Collaborative Event Booth Demo","\u002Ftutorials\u002Fprojects\u002Fbuild-directus-garden-a-passive-collaborative-event-booth-demo","tutorials\u002F2.projects\u002Fbuild-directus-garden-a-passive-collaborative-event-booth-demo","Learn how we built our engagement platform for live in-person events with P5.js.",{"title":1720,"path":1721,"stem":1722,"description":1723,"icon":14,"links":14},"Build the Leap Week Registration and Referral System","\u002Ftutorials\u002Fprojects\u002Fbuild-the-leap-week-registration-and-referral-system","tutorials\u002F2.projects\u002Fbuild-the-leap-week-registration-and-referral-system-","Learn how we built our referral-based ticketing and raffle system with AI-generated rabbitars.",{"title":1725,"path":1726,"stem":1727,"description":1728,"icon":14,"links":14},"Building AIVenture - An AI-Powered Game with Directus","\u002Ftutorials\u002Fprojects\u002Fbuilding-ai-venture-an-ai-powered-game-with-directus","tutorials\u002F2.projects\u002Fbuilding-ai-venture-an-ai-powered-game-with-directus","Learn the advanced techniques used with Directus Flows to build a game.",{"title":1730,"path":1731,"stem":1732,"description":1733,"icon":14,"links":14},"Create Reusable Blocks with Many-to-Any Relationships","\u002Ftutorials\u002Fprojects\u002Fcreate-reusable-blocks-with-many-to-any-relationships","tutorials\u002F2.projects\u002Fcreate-reusable-blocks-with-many-to-any-relationships","Learn how to data model for multiple, repeating sections of content.",{"title":1735,"path":1736,"stem":1737,"description":1738,"icon":14,"links":14},"How I Built an AI Open Source Santa Roast App with Directus and Nuxt","\u002Ftutorials\u002Fprojects\u002Fhow-i-built-an-ai-open-source-santa-roast-app-with-directus-and-nuxt","tutorials\u002F2.projects\u002Fhow-i-built-an-ai-open-source-santa-roast-app-with-directus-and-nuxt","Bryant breaks down how he built an AI-powered app that roasts developers based on their GitHub contributions.",{"title":1740,"path":1741,"stem":1742,"description":1743,"icon":14,"links":14},"Integrate Directus with ESP32 Hardware Sensors","\u002Ftutorials\u002Fprojects\u002Fintegrate-directus-with-esp-32-hardware-sensors","tutorials\u002F2.projects\u002Fintegrate-directus-with-esp-32-hardware-sensors","Learn how to integrate Directus with IoT systems by reading and publishing sensor data.",{"title":1745,"path":1746,"stem":1747,"description":1748,"icon":14,"links":14},"Use Directus as a Baby Health Tracker with Owlet and OpsGenie","\u002Ftutorials\u002Fprojects\u002Fuse-directus-as-a-baby-health-tracker-with-owlet-and-ops-genie","tutorials\u002F2.projects\u002Fuse-directus-as-a-baby-health-tracker-with-owlet-and-ops-genie","Learn how to integrate Directus with hardware sensors and incident response systems.",{"title":1750,"path":1751,"stem":1752,"children":1753,"description":24,"icon":14,"links":14},"Tips & Tricks","\u002Ftutorials\u002Ftips-and-tricks","tutorials\u002F3.tips-and-tricks\u002Findex",[1754,1755,1760,1765,1770,1775,1780,1785],{"title":1750,"path":1751,"stem":1752,"description":24,"icon":14,"links":14},{"title":1756,"path":1757,"stem":1758,"description":1759,"icon":14,"links":14},"Advanced Types with the Directus SDK","\u002Ftutorials\u002Ftips-and-tricks\u002Fadvanced-types-with-the-directus-sdk","tutorials\u002F3.tips-and-tricks\u002Fadvanced-types-with-the-directus-sdk","Learn how to more-easily work with types and the Directus SDK.",{"title":1761,"path":1762,"stem":1763,"description":1764,"icon":14,"links":14},"Build a Monitoring Pipeline For Flows And Extensions","\u002Ftutorials\u002Ftips-and-tricks\u002Fbuild-a-monitoring-pipeline-for-flows-and-extensions","tutorials\u002F3.tips-and-tricks\u002Fbuild-a-monitoring-pipeline-for-flows-and-extensions-","Learn how to set up complex pipelines to monitor automations and extensions.",{"title":1766,"path":1767,"stem":1768,"description":1769,"icon":14,"links":14},"Configure Okta as a Single Sign-On Provider","\u002Ftutorials\u002Ftips-and-tricks\u002Fconfigure-okta-as-a-single-sign-on-provider","tutorials\u002F3.tips-and-tricks\u002Fconfigure-okta-as-a-single-sign-on-provider","Learn how to set up Okta SSO with the SAML authentication mechanism.",{"title":1771,"path":1772,"stem":1773,"description":1774,"icon":14,"links":14},"Importing Files in Directus Flows","\u002Ftutorials\u002Ftips-and-tricks\u002Fimporting-files-in-directus-automate","tutorials\u002F3.tips-and-tricks\u002Fimporting-files-in-directus-automate","Learn how to use the Request URL operation to import files in Directus Flows.",{"title":1776,"path":1777,"stem":1778,"description":1779,"icon":14,"links":14},"Preview Files in Live Preview with Google Docs Previews","\u002Ftutorials\u002Ftips-and-tricks\u002Fpreview-files-in-live-preview-with-google-docs-previews","tutorials\u002F3.tips-and-tricks\u002Fpreview-files-in-live-preview-with-google-docs-previews","Learn how to use Google Gview to preview many file formats in Directus Editor.",{"title":1781,"path":1782,"stem":1783,"description":1784,"icon":14,"links":14},"Search Engine Optimization Best Practices","\u002Ftutorials\u002Ftips-and-tricks\u002Fsearch-engine-optimization-best-practices","tutorials\u002F3.tips-and-tricks\u002Fsearch-engine-optimization-best-practices","Learn some best practices for enabling SEO in your projects using Directus.",{"title":1786,"path":1787,"stem":1788,"description":1789,"icon":14,"links":14},"Understanding Kubernetes","\u002Ftutorials\u002Ftips-and-tricks\u002Funderstanding-kubernetes","tutorials\u002F3.tips-and-tricks\u002Funderstanding-kubernetes","Learn about key Kubernetes concepts and how they interact with each other.",{"title":1791,"path":1792,"stem":1793,"children":1794,"description":24,"icon":14,"links":14},"Migration","\u002Ftutorials\u002Fmigration","tutorials\u002F4.migration\u002Findex",[1795,1796,1801,1806],{"title":1791,"path":1792,"stem":1793,"description":24,"icon":14,"links":14},{"title":1797,"path":1798,"stem":1799,"description":1800,"icon":14,"links":14},"Migrate from Notion to Directus","\u002Ftutorials\u002Fmigration\u002Fmigrate-from-notion-to-directus","tutorials\u002F4.migration\u002Fmigrate-from-notion-to-directus","Learn how to migrate data from Notion databases to Directus.",{"title":1802,"path":1803,"stem":1804,"description":1805,"icon":14,"links":14},"Migrate from WordPress to Directus","\u002Ftutorials\u002Fmigration\u002Fmigrate-from-wordpress-to-directus","tutorials\u002F4.migration\u002Fmigrate-from-wordpress-to-directus","Learn how to migrate posts and images to Directus, with tips on plugins.",{"title":1807,"path":1808,"stem":1809,"description":1810,"icon":14,"links":14},"Promoting Changes Between Environments in Directus","\u002Ftutorials\u002Fmigration\u002Fpromoting-changes-between-environments-in-directus","tutorials\u002F4.migration\u002Fpromoting-changes-between-environments-in-directus","Learn the options to migrate schema and data between Directus projects.",{"title":368,"path":1812,"stem":1813,"children":1814,"description":1816,"icon":14,"links":14},"\u002Ftutorials\u002Fextensions","tutorials\u002F5.extensions\u002Findex",[1815,1817,1822,1827,1832,1837,1842,1847,1852,1859,1866,1873,1878,1883,1888,1893,1898,1903,1908,1913,1918,1923],{"title":368,"path":1812,"stem":1813,"description":1816,"icon":14,"links":14},"All about extensions",{"title":1818,"path":1819,"stem":1820,"description":1821,"icon":14,"links":14},"Check Permissions in a Custom Endpoint","\u002Ftutorials\u002Fextensions\u002Fcheck-permissions-in-a-custom-endpoint","tutorials\u002F5.extensions\u002Fcheck-permissions-in-a-custom-endpoint","Learn how to use internal Directus permissions when creating a custom endpoint.",{"title":1823,"path":1824,"stem":1825,"description":1826,"icon":14,"links":14},"Create Collection Items in Custom Panels","\u002Ftutorials\u002Fextensions\u002Fcreate-collection-items-in-custom-panels","tutorials\u002F5.extensions\u002Fcreate-collection-items-in-custom-panels","Learn how to use built-in interfaces and composables to create new collections.",{"title":1828,"path":1829,"stem":1830,"description":1831,"icon":14,"links":14},"Create New Customers in Stripe in a Custom Hook","\u002Ftutorials\u002Fextensions\u002Fcreate-new-customers-in-stripe-in-a-custom-hook","tutorials\u002F5.extensions\u002Fcreate-new-customers-in-stripe-in-a-custom-hook","Learn how to use the Stripe SDK to create data when actions occur in Directus.",{"title":1833,"path":1834,"stem":1835,"description":1836,"icon":14,"links":14},"Display External API Data From Vonage In Custom Panels","\u002Ftutorials\u002Fextensions\u002Fdisplay-external-api-data-from-vonage-in-custom-panels","tutorials\u002F5.extensions\u002Fdisplay-external-api-data-from-vonage-in-custom-panels","Learn how to display records from external systems in Directus Insights.",{"title":1838,"path":1839,"stem":1840,"description":1841,"icon":14,"links":14},"Display External Weather API Data In Custom Panels","\u002Ftutorials\u002Fextensions\u002Fdisplay-external-weather-api-data-in-custom-panels","tutorials\u002F5.extensions\u002Fdisplay-external-weather-api-data-in-custom-panels","Learn how to display external data in panels with a bundle and endpoint.",{"title":1843,"path":1844,"stem":1845,"description":1846,"icon":14,"links":14},"Format Dates in a Custom Display Extension","\u002Ftutorials\u002Fextensions\u002Fformat-dates-in-a-custom-display-extension","tutorials\u002F5.extensions\u002Fformat-dates-in-a-custom-display-extension","Learn how to build a custom display to format data in Directus.",{"title":1848,"path":1849,"stem":1850,"description":1851,"icon":14,"links":14},"Implement Navigation in Multipage Custom Modules","\u002Ftutorials\u002Fextensions\u002Fimplement-navigation-in-multipage-custom-modules","tutorials\u002F5.extensions\u002Fimplement-navigation-in-multipage-custom-modules","Learn how to navigate between multiple pages in module extensions.",{"title":1853,"path":1854,"stem":1855,"children":1856,"description":1858,"icon":14,"links":14},"Integrate Algolia Indexing with Custom Hooks","\u002Ftutorials\u002Fextensions\u002Fintegrate-algolia-indexing-with-custom-hooks","tutorials\u002F5.extensions\u002Fintegrate-algolia-indexing-with-custom-hooks",[1857],{"title":1853,"path":1854,"stem":1855,"description":1858,"icon":14,"links":14},"Learn how to maintain an Algolia index when data is created, updated, and deleted.",{"title":1860,"path":1861,"stem":1862,"children":1863,"description":1865,"icon":14,"links":14},"Integrate Elasticsearch Indexing with Custom Hooks","\u002Ftutorials\u002Fextensions\u002Fintegrate-elasticsearch-indexing-with-custom-hooks","tutorials\u002F5.extensions\u002Fintegrate-elasticsearch-indexing-with-custom-hooks",[1864],{"title":1860,"path":1861,"stem":1862,"description":1865,"icon":14,"links":14},"Learn how to maintain an Elasticsearch index when data is created, updated, and deleted.",{"title":1867,"path":1868,"stem":1869,"children":1870,"description":1872,"icon":14,"links":14},"Integrate Meilisearch Indexing with Custom Hooks","\u002Ftutorials\u002Fextensions\u002Fintegrate-meilisearch-indexing-with-custom-hooks","tutorials\u002F5.extensions\u002Fintegrate-meilisearch-indexing-with-custom-hooks",[1871],{"title":1867,"path":1868,"stem":1869,"description":1872,"icon":14,"links":14},"Learn how to maintain an Meilisearch index when data is created, updated, and deleted.",{"title":1874,"path":1875,"stem":1876,"description":1877,"icon":14,"links":14},"Monitor and Error Track with Sentry in Custom Hooks","\u002Ftutorials\u002Fextensions\u002Fmonitor-and-error-track-with-sentry-in-custom-hooks","tutorials\u002F5.extensions\u002Fmonitor-and-error-track-with-sentry-in-custom-hooks","Learn how to integrate Sentry error tracking in both your API and Data Studio.",{"title":1879,"path":1880,"stem":1881,"description":1882,"icon":14,"links":14},"Proxy an External API in a Custom Endpoint Extension","\u002Ftutorials\u002Fextensions\u002Fproxy-an-external-api-in-a-custom-endpoint-extension","tutorials\u002F5.extensions\u002Fproxy-an-external-api-in-a-custom-endpoint-extension","Learn how to make external APIs available via Directus in a custom endpoint.",{"title":1884,"path":1885,"stem":1886,"description":1887,"icon":14,"links":14},"Read Collection Data in Custom Layouts","\u002Ftutorials\u002Fextensions\u002Fread-collection-data-in-custom-layouts","tutorials\u002F5.extensions\u002Fread-collection-data-in-custom-layouts","Learn how to build your first layout with data from a collection.",{"title":1889,"path":1890,"stem":1891,"description":1892,"icon":14,"links":14},"Send SMS Messages with Twilio in Custom Operations","\u002Ftutorials\u002Fextensions\u002Fsend-sms-messages-with-twilio-in-custom-operations","tutorials\u002F5.extensions\u002Fsend-sms-messages-with-twilio-in-custom-operations","Learn how to build a custom operation that uses the Twilio SDK.",{"title":1894,"path":1895,"stem":1896,"description":1897,"icon":14,"links":14},"Send SMS Messages with Twilio in Custom Panels","\u002Ftutorials\u002Fextensions\u002Fsend-sms-messages-with-twilio-in-custom-panels","tutorials\u002F5.extensions\u002Fsend-sms-messages-with-twilio-in-custom-panels","Learn how to build a form inside a panel extension and use external APIs.",{"title":1899,"path":1900,"stem":1901,"description":1902,"icon":14,"links":14},"Summarize Relational Items in a Custom Display Extension","\u002Ftutorials\u002Fextensions\u002Fsummarize-relational-items-in-a-custom-display-extension","tutorials\u002F5.extensions\u002Fsummarize-relational-items-in-a-custom-display-extension","Learn how to work with relational data in display extensions.",{"title":1904,"path":1905,"stem":1906,"description":1907,"icon":14,"links":14},"Understand Available Slots in Custom Modules","\u002Ftutorials\u002Fextensions\u002Funderstand-available-slots-in-custom-modules","tutorials\u002F5.extensions\u002Funderstand-available-slots-in-custom-modules","Learn about all of the slots available in your custom modules.",{"title":1909,"path":1910,"stem":1911,"description":1912,"icon":14,"links":14},"Use Dynamic Values in Custom Email Templates","\u002Ftutorials\u002Fextensions\u002Fuse-dynamic-values-in-custom-email-templates","tutorials\u002F5.extensions\u002Fuse-dynamic-values-in-custom-email-templates","Learn how to inject dynamic data into liquid templates.",{"title":1914,"path":1915,"stem":1916,"description":1917,"icon":14,"links":14},"Use npm Packages in Custom Operations","\u002Ftutorials\u002Fextensions\u002Fuse-npm-packages-in-custom-operations","tutorials\u002F5.extensions\u002Fuse-npm-packages-in-custom-operations","Learn how to expose an npm package as an operation in Directus Flows.",{"title":1919,"path":1920,"stem":1921,"description":1922,"icon":14,"links":14},"Validate Phone Numbers with Twilio in a Custom Hook","\u002Ftutorials\u002Fextensions\u002Fvalidate-phone-numbers-with-twilio-in-a-custom-hook","tutorials\u002F5.extensions\u002Fvalidate-phone-numbers-with-twilio-in-a-custom-hook","Learn how to prevent an item from saving if it has an invalid phone number.",{"title":1924,"path":1925,"stem":1926,"description":1927,"icon":14,"links":14},"Validating Third-Party JWTs in Directus (with Okta)","\u002Ftutorials\u002Fextensions\u002Fvalidating-third-party-jwts-in-directus","tutorials\u002F5.extensions\u002Fvalidating-third-party-jwts-in-directus","Learn how to translate third-party JWTs to Directus accountability",{"title":1929,"path":1930,"stem":1931,"children":1932,"description":1934,"icon":14,"links":14},"How to Deploy Directus","\u002Ftutorials\u002Fself-hosting","tutorials\u002F6.self-hosting\u002Findex",[1933,1935,1940,1945,1950,1955,1960,1965,1970],{"title":1929,"path":1930,"stem":1931,"description":1934,"icon":14,"links":14},"Deploy Directus with Directus Cloud, self-host with Docker, or follow step-by-step guides for your preferred cloud provider.",{"title":1936,"path":1937,"stem":1938,"description":1939,"icon":14,"links":14},"Deploy Directus to an Ubuntu Server","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-an-ubuntu-server","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-an-ubuntu-server","Learn how to deploy Directus on a Docker container on an Ubuntu server.",{"title":1941,"path":1942,"stem":1943,"description":1944,"icon":14,"links":14},"Deploy Directus to AWS EC2","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-aws-ec2","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-aws-ec2","Learn how to deploy a Directus to AWS EC2, with a RDS database and a S3 storage bucket.",{"title":1946,"path":1947,"stem":1948,"description":1949,"icon":14,"links":14},"Deploy Directus to Azure Web Apps","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-azure-web-apps","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-azure-web-apps","Learn how to deploy Directus on a Docker container on Azure.",{"title":1951,"path":1952,"stem":1953,"description":1954,"icon":14,"links":14},"Deploy Directus to Digital Ocean","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-digital-ocean","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-digital-ocean","Learn how to deploy Directus on the Digital Ocean App Platform.",{"title":1956,"path":1957,"stem":1958,"description":1959,"icon":14,"links":14},"Deploy Directus to Google Cloud Platform","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-google-cloud-platform","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-google-cloud-platform","Learn how to deploy Directus on GCP with a Cloud SQL database and Cloud Storage Bucket.",{"title":1961,"path":1962,"stem":1963,"description":1964,"icon":14,"links":14},"Deploy Directus to Northflank","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-northflank","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-northflank","Deploy a production-ready Directus instance on Northflank using the official one-click stack, with PostgreSQL, Redis, and MinIO storage provisioned automatically.",{"title":1966,"path":1967,"stem":1968,"description":1969,"icon":14,"links":14},"Deploy Directus to Railway","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-railway","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-railway","Deploy Directus on Railway using the official one-click templates (blank instance or CMS template) with PostgreSQL, Redis, and S3-compatible storage.",{"title":1971,"path":1972,"stem":1973,"description":1974,"icon":14,"links":14},"Deploy Directus to Render","\u002Ftutorials\u002Fself-hosting\u002Fdeploy-directus-to-render","tutorials\u002F6.self-hosting\u002Fdeploy-directus-to-render","Deploy Directus on Render using the official blueprint repository and one-click deploy flow. Provision services from Infrastructure-as-Code and finish configuration in the Render Dashboard.",{"title":1976,"path":1977,"stem":1978,"children":1979,"description":24,"icon":14,"links":14},"Workflows","\u002Ftutorials\u002Fworkflows","tutorials\u002F7.workflows\u002Findex",[1980,1981,1986,1991,1996,2001,2006,2011,2016,2021,2026,2031,2036,2041],{"title":1976,"path":1977,"stem":1978,"description":24,"icon":14,"links":14},{"title":1982,"path":1983,"stem":1984,"description":1985,"icon":14,"links":14},"Build Content Approval Workflows with Custom Permissions","\u002Ftutorials\u002Fworkflows\u002Fbuild-content-approval-workflows-with-custom-permissions","tutorials\u002F7.workflows\u002Fbuild-content-approval-workflows-with-custom-permissions","Learn how to configure roles and permissions for complex automations.",{"title":1987,"path":1988,"stem":1989,"description":1990,"icon":14,"links":14},"Create GitHub Issues with Directus Flows","\u002Ftutorials\u002Fworkflows\u002Fcreate-github-issues-with-directus-automate","tutorials\u002F7.workflows\u002Fcreate-github-issues-with-directus-automate","Learn how to integrate GitHub with Directus Flows to create new issues.",{"title":1992,"path":1993,"stem":1994,"description":1995,"icon":14,"links":14},"Detect High-Risk Phone Numbers with Vonage and Directus Flows","\u002Ftutorials\u002Fworkflows\u002Fdetect-high-risk-phone-numbers-with-vonage-and-directus-automate","tutorials\u002F7.workflows\u002Fdetect-high-risk-phone-numbers-with-vonage-and-directus-automate","Learn how to integrate Vonage's Number Insights API with Directus Flows to validate numbers.",{"title":1997,"path":1998,"stem":1999,"description":2000,"icon":14,"links":14},"Enrich User Data with Clearbit and Directus Flows","\u002Ftutorials\u002Fworkflows\u002Fenrich-user-data-with-clearbit-and-directus-automate","tutorials\u002F7.workflows\u002Fenrich-user-data-with-clearbit-and-directus-automate","Learn how to integrate Clearbit data enrichment with Directus Flows.",{"title":2002,"path":2003,"stem":2004,"description":2005,"icon":14,"links":14},"Generate Images with DALL•E and Directus Flows","\u002Ftutorials\u002Fworkflows\u002Fgenerate-images-with-dall-e-and-directus-automate","tutorials\u002F7.workflows\u002Fgenerate-images-with-dall-e-and-directus-automate","Learn how to integrate OpenAI's Dall•E models with Directus Flows.",{"title":2007,"path":2008,"stem":2009,"description":2010,"icon":14,"links":14},"Generate Social Posts with GPT-4 and Directus Flows","\u002Ftutorials\u002Fworkflows\u002Fgenerate-social-posts-with-gpt-4-and-directus-automate","tutorials\u002F7.workflows\u002Fgenerate-social-posts-with-gpt-4-and-directus-automate","Learn how to integrate OpenAI's GPT-4 model with Directus Flows.",{"title":2012,"path":2013,"stem":2014,"description":2015,"icon":14,"links":14},"Generate Transcripts with Deepgram and Directus Flows","\u002Ftutorials\u002Fworkflows\u002Fgenerate-transcripts-with-deepgram-and-directus-automate","tutorials\u002F7.workflows\u002Fgenerate-transcripts-with-deepgram-and-directus-automate","Learn how to integrate Deepgram's Speech-to-Text API with Directus Flows.",{"title":2017,"path":2018,"stem":2019,"description":2020,"icon":14,"links":14},"Integrating Multilingual Content with Directus and Crowdin","\u002Ftutorials\u002Fworkflows\u002Fintegrating-multilingual-content-with-directus-and-crowdin","tutorials\u002F7.workflows\u002Fintegrating-multilingual-content-with-directus-and-crowdin","Learn how to localize content in Directus using Crowdin's connector with Directus.",{"title":2022,"path":2023,"stem":2024,"description":2025,"icon":14,"links":14},"Invincible AI content workflows with Inngest and Directus","\u002Ftutorials\u002Fworkflows\u002Finvincible-ai-content-workflows-with-inngest-and-directus","tutorials\u002F7.workflows\u002Finvincible-ai-content-workflows-with-inngest-and-directus","Learn how to configure integration Directus and Inngest to build durable workflows for any scale.",{"title":2027,"path":2028,"stem":2029,"description":2030,"icon":14,"links":14},"Schedule Future Content with Directus Flows","\u002Ftutorials\u002Fworkflows\u002Fschedule-future-content-with-directus-automate","tutorials\u002F7.workflows\u002Fschedule-future-content-with-directus-automate","Learn how to set content to be scheduled on a future date with Directs Automate.",{"title":2032,"path":2033,"stem":2034,"description":2035,"icon":14,"links":14},"Tag Images with Clarifai and Directus Flows","\u002Ftutorials\u002Fworkflows\u002Ftag-images-with-clarifai-and-directus-automate","tutorials\u002F7.workflows\u002Ftag-images-with-clarifai-and-directus-automate","Learn how to integrate Clarifai's image recognition APIs with Directus Flows.",{"title":2037,"path":2038,"stem":2039,"description":2040,"icon":14,"links":14},"Trigger Netlify Site Builds with Directus Flows","\u002Ftutorials\u002Fworkflows\u002Ftrigger-netlify-site-builds-with-directus-automate","tutorials\u002F7.workflows\u002Ftrigger-netlify-site-builds-with-directus-automate","Learn how to trigger new Netlify website builds through Directus Flows.",{"title":2042,"path":2043,"stem":2044,"description":2045,"icon":14,"links":14},"Trigger Vercel Site Builds with Directus Flows","\u002Ftutorials\u002Fworkflows\u002Ftrigger-vercel-site-builds-with-directus-automate","tutorials\u002F7.workflows\u002Ftrigger-vercel-site-builds-with-directus-automate","Learn how to trigger new Vercel website builds through Directus Flows.",{"id":2047,"icon":14,"content":2048,"link":2049},"5cf2f5f6-aecf-4395-8c23-69de326fdf02","AI Assistant: Query Your Data, Update Content + More","https:\u002F\u002Fdirectus.com\u002Fai",{"id":2051,"title":2052,"authors":14,"body":2053,"description":1237,"extension":4376,"headline":14,"icon":14,"links":14,"meta":4377,"navigation":4378,"path":1235,"rawbody":4379,"section":14,"seo":4380,"stableId":4381,"stem":1236,"technologies":14,"__hash__":4382},"content\u002Fguides\u002F09.extensions\u002F3.app-extensions\u002F7.richtext.md","Rich Text Extensions",{"type":2054,"value":2055,"toc":4349},"minimark",[2056,2077,2080,2084,2089,2112,2116,2123,2144,2155,2174,2184,2188,2199,2204,2207,2596,2600,2702,2705,2709,2720,2854,2858,2867,2924,2931,2935,2938,2958,2969,2972,2975,2981,2995,3001,3005,3014,3023,3056,3059,3067,3070,3074,3077,3083,3086,3164,3168,3171,3188,3192,3209,3374,3380,3391,3602,3609,3613,3616,3623,3714,3717,3723,3727,3730,3750,3758,3769,3773,3776,3794,4018,4021,4052,4056,4059,4074,4077,4080,4133,4150,4160,4163,4167,4188,4202,4205,4213,4278,4281,4290,4298,4302,4305,4328,4332,4345],[2057,2058,2059,2060,2067,2068,2072,2073,2076],"p",{},"Rich text extensions add ",[2061,2062,2066],"a",{"href":2063,"rel":2064},"https:\u002F\u002Ftiptap.dev",[2065],"nofollow","Tiptap"," nodes, marks, and toolbar buttons to the ",[2061,2069,2071],{"href":2070},"\u002Fguides\u002Fdata-model\u002Finterfaces#wysiwyg","WYSIWYG interface",". A field uses an extension only when you select it in the interface's ",[2074,2075,368],"strong",{}," option.",[2057,2078,2079],{},"You write nodes and marks with the standard Tiptap API. Directus adds a small config around them, and a set of rules that keep content intact when users save, compare, or remove an extension.",[2081,2082],"partial",{"content":2083},"extensions-app",[2085,2086,2088],"h2",{"id":2087},"before-you-start","Before You Start",[2090,2091,2092,2105],"ul",{},[2093,2094,2095,2096,2100,2101,2104],"li",{},"You know how to write a Tiptap node or mark with ",[2097,2098,2099],"code",{},"parseHTML"," and ",[2097,2102,2103],{},"renderHTML",".",[2093,2106,2107,2108,2111],{},"You have a Directus project to test in. Set ",[2097,2109,2110],{},"EXTENSIONS_AUTO_RELOAD=true"," while you develop.",[2085,2113,2115],{"id":2114},"create-an-extension","Create an Extension",[2057,2117,2118,2119,2122],{},"Run the extensions CLI and select the ",[2097,2120,2121],{},"richtext"," type:",[2124,2125,2129],"pre",{"className":2126,"code":2127,"language":2128,"meta":24,"style":24},"language-shell shiki shiki-themes directus-light directus-light directus-dark","npx create-directus-extension@latest\n","shell",[2097,2130,2131],{"__ignoreMap":24},[2132,2133,2136,2140],"span",{"class":2134,"line":2135},"line",1,[2132,2137,2139],{"class":2138},"s6TUV","npx",[2132,2141,2143],{"class":2142},"suKVh"," create-directus-extension@latest\n",[2057,2145,2146,2147,2150,2151,2104],{},"The template contains one mark and one toolbar button. It adds ",[2097,2148,2149],{},"@tiptap\u002Fcore"," as a dev dependency so your editor can type-check Tiptap imports. The build does not bundle it. See ",[2061,2152,2154],{"href":2153},"#shared-tiptap-packages","Shared Tiptap Packages",[2057,2156,2157,2158,2161,2162,2165,2166,2169,2170,2104],{},"The generated ",[2097,2159,2160],{},"package.json"," declares the extension type in ",[2097,2163,2164],{},"directus:extension",". Before you publish, set its ",[2097,2167,2168],{},"host"," field as described in ",[2061,2171,2173],{"href":2172},"#set-the-host-range","Set the Host Range",[2057,2175,2176,2177,2180,2181,2183],{},"Rich text extensions load in the Data Studio only. You can also add one to a ",[2061,2178,2179],{"href":1250},"bundle"," as a ",[2097,2182,2121],{}," entry.",[2085,2185,2187],{"id":2186},"rich-text-entrypoint","Rich Text Entrypoint",[2057,2189,2190,2191,2194,2195,2198],{},"The ",[2097,2192,2193],{},"index.js"," or ",[2097,2196,2197],{},"index.ts"," file exports the config. It lists the Tiptap extensions to add to the editor schema, and the buttons that act on them.",[2200,2201,2203],"h3",{"id":2202},"entrypoint-example","Entrypoint Example",[2057,2205,2206],{},"This example adds a callout block and a toolbar button that wraps the selection in it.",[2124,2208,2212],{"className":2209,"code":2210,"language":2211,"meta":24,"style":24},"language-js shiki shiki-themes directus-light directus-light directus-dark","import { defineRichText } from '@directus\u002Fextensions-sdk';\nimport { Node, mergeAttributes } from '@tiptap\u002Fcore';\n\nconst Callout = Node.create({\n    name: 'callout',\n    group: 'block',\n    content: 'block+',\n    parseHTML: () => [{ tag: 'div[data-callout]' }],\n    renderHTML: ({ HTMLAttributes }) => ['div', mergeAttributes(HTMLAttributes, { 'data-callout': '' }), 0],\n});\n\nexport default defineRichText({\n    id: 'callout',\n    name: 'Callout',\n    extensions: [Callout],\n    buttons: [\n        {\n            key: 'callout',\n            icon: 'info',\n            label: 'Callout',\n            command: (editor) => editor.chain().focus().toggleWrap('callout').run(),\n            isActive: (editor) => editor.isActive('callout'),\n        },\n    ],\n});\n","js",[2097,2213,2214,2240,2265,2272,2295,2307,2318,2329,2350,2403,2409,2414,2428,2438,2448,2459,2465,2471,2481,2492,2502,2551,2579,2585,2591],{"__ignoreMap":24},[2132,2215,2216,2220,2224,2228,2231,2234,2237],{"class":2134,"line":2135},[2132,2217,2219],{"class":2218},"sb-bW","import",[2132,2221,2223],{"class":2222},"sTMul"," { ",[2132,2225,2227],{"class":2226},"sNJ9c","defineRichText",[2132,2229,2230],{"class":2222}," } ",[2132,2232,2233],{"class":2218},"from",[2132,2235,2236],{"class":2142}," '@directus\u002Fextensions-sdk'",[2132,2238,2239],{"class":2222},";\n",[2132,2241,2243,2245,2247,2250,2253,2256,2258,2260,2263],{"class":2134,"line":2242},2,[2132,2244,2219],{"class":2218},[2132,2246,2223],{"class":2222},[2132,2248,2249],{"class":2226},"Node",[2132,2251,2252],{"class":2222},", ",[2132,2254,2255],{"class":2226},"mergeAttributes",[2132,2257,2230],{"class":2222},[2132,2259,2233],{"class":2218},[2132,2261,2262],{"class":2142}," '@tiptap\u002Fcore'",[2132,2264,2239],{"class":2222},[2132,2266,2268],{"class":2134,"line":2267},3,[2132,2269,2271],{"emptyLinePlaceholder":2270},true,"\n",[2132,2273,2275,2278,2281,2284,2287,2289,2292],{"class":2134,"line":2274},4,[2132,2276,2277],{"class":2218},"const",[2132,2279,2280],{"class":2138}," Callout",[2132,2282,2283],{"class":2218}," =",[2132,2285,2286],{"class":2226}," Node",[2132,2288,2104],{"class":2222},[2132,2290,2291],{"class":2138},"create",[2132,2293,2294],{"class":2222},"({\n",[2132,2296,2298,2301,2304],{"class":2134,"line":2297},5,[2132,2299,2300],{"class":2222},"    name: ",[2132,2302,2303],{"class":2142},"'callout'",[2132,2305,2306],{"class":2222},",\n",[2132,2308,2310,2313,2316],{"class":2134,"line":2309},6,[2132,2311,2312],{"class":2222},"    group: ",[2132,2314,2315],{"class":2142},"'block'",[2132,2317,2306],{"class":2222},[2132,2319,2321,2324,2327],{"class":2134,"line":2320},7,[2132,2322,2323],{"class":2222},"    content: ",[2132,2325,2326],{"class":2142},"'block+'",[2132,2328,2306],{"class":2222},[2132,2330,2332,2335,2338,2341,2344,2347],{"class":2134,"line":2331},8,[2132,2333,2334],{"class":2138},"    parseHTML",[2132,2336,2337],{"class":2222},": () ",[2132,2339,2340],{"class":2218},"=>",[2132,2342,2343],{"class":2222}," [{ tag: ",[2132,2345,2346],{"class":2142},"'div[data-callout]'",[2132,2348,2349],{"class":2222}," }],\n",[2132,2351,2353,2356,2359,2362,2365,2367,2370,2373,2375,2377,2380,2382,2385,2388,2391,2394,2397,2400],{"class":2134,"line":2352},9,[2132,2354,2355],{"class":2138},"    renderHTML",[2132,2357,2358],{"class":2222},": ({ ",[2132,2360,2361],{"class":2218},"HTMLAttributes",[2132,2363,2364],{"class":2222}," }) ",[2132,2366,2340],{"class":2218},[2132,2368,2369],{"class":2222}," [",[2132,2371,2372],{"class":2142},"'div'",[2132,2374,2252],{"class":2222},[2132,2376,2255],{"class":2138},[2132,2378,2379],{"class":2222},"(",[2132,2381,2361],{"class":2226},[2132,2383,2384],{"class":2222},", { ",[2132,2386,2387],{"class":2142},"'data-callout'",[2132,2389,2390],{"class":2222},": ",[2132,2392,2393],{"class":2142},"''",[2132,2395,2396],{"class":2222}," }), ",[2132,2398,2399],{"class":2138},"0",[2132,2401,2402],{"class":2222},"],\n",[2132,2404,2406],{"class":2134,"line":2405},10,[2132,2407,2408],{"class":2222},"});\n",[2132,2410,2412],{"class":2134,"line":2411},11,[2132,2413,2271],{"emptyLinePlaceholder":2270},[2132,2415,2417,2420,2423,2426],{"class":2134,"line":2416},12,[2132,2418,2419],{"class":2218},"export",[2132,2421,2422],{"class":2218}," default",[2132,2424,2425],{"class":2138}," defineRichText",[2132,2427,2294],{"class":2222},[2132,2429,2431,2434,2436],{"class":2134,"line":2430},13,[2132,2432,2433],{"class":2222},"    id: ",[2132,2435,2303],{"class":2142},[2132,2437,2306],{"class":2222},[2132,2439,2441,2443,2446],{"class":2134,"line":2440},14,[2132,2442,2300],{"class":2222},[2132,2444,2445],{"class":2142},"'Callout'",[2132,2447,2306],{"class":2222},[2132,2449,2451,2454,2457],{"class":2134,"line":2450},15,[2132,2452,2453],{"class":2222},"    extensions: [",[2132,2455,2456],{"class":2226},"Callout",[2132,2458,2402],{"class":2222},[2132,2460,2462],{"class":2134,"line":2461},16,[2132,2463,2464],{"class":2222},"    buttons: [\n",[2132,2466,2468],{"class":2134,"line":2467},17,[2132,2469,2470],{"class":2222},"        {\n",[2132,2472,2474,2477,2479],{"class":2134,"line":2473},18,[2132,2475,2476],{"class":2222},"            key: ",[2132,2478,2303],{"class":2142},[2132,2480,2306],{"class":2222},[2132,2482,2484,2487,2490],{"class":2134,"line":2483},19,[2132,2485,2486],{"class":2222},"            icon: ",[2132,2488,2489],{"class":2142},"'info'",[2132,2491,2306],{"class":2222},[2132,2493,2495,2498,2500],{"class":2134,"line":2494},20,[2132,2496,2497],{"class":2222},"            label: ",[2132,2499,2445],{"class":2142},[2132,2501,2306],{"class":2222},[2132,2503,2505,2508,2511,2514,2517,2519,2522,2524,2527,2530,2533,2535,2538,2540,2542,2545,2548],{"class":2134,"line":2504},21,[2132,2506,2507],{"class":2138},"            command",[2132,2509,2510],{"class":2222},": (",[2132,2512,2513],{"class":2218},"editor",[2132,2515,2516],{"class":2222},") ",[2132,2518,2340],{"class":2218},[2132,2520,2521],{"class":2226}," editor",[2132,2523,2104],{"class":2222},[2132,2525,2526],{"class":2138},"chain",[2132,2528,2529],{"class":2222},"().",[2132,2531,2532],{"class":2138},"focus",[2132,2534,2529],{"class":2222},[2132,2536,2537],{"class":2138},"toggleWrap",[2132,2539,2379],{"class":2222},[2132,2541,2303],{"class":2142},[2132,2543,2544],{"class":2222},").",[2132,2546,2547],{"class":2138},"run",[2132,2549,2550],{"class":2222},"(),\n",[2132,2552,2554,2557,2559,2561,2563,2565,2567,2569,2572,2574,2576],{"class":2134,"line":2553},22,[2132,2555,2556],{"class":2138},"            isActive",[2132,2558,2510],{"class":2222},[2132,2560,2513],{"class":2218},[2132,2562,2516],{"class":2222},[2132,2564,2340],{"class":2218},[2132,2566,2521],{"class":2226},[2132,2568,2104],{"class":2222},[2132,2570,2571],{"class":2138},"isActive",[2132,2573,2379],{"class":2222},[2132,2575,2303],{"class":2142},[2132,2577,2578],{"class":2222},"),\n",[2132,2580,2582],{"class":2134,"line":2581},23,[2132,2583,2584],{"class":2222},"        },\n",[2132,2586,2588],{"class":2134,"line":2587},24,[2132,2589,2590],{"class":2222},"    ],\n",[2132,2592,2594],{"class":2134,"line":2593},25,[2132,2595,2408],{"class":2222},[2200,2597,2599],{"id":2598},"properties","Properties",[2601,2602,2603,2619],"table",{},[2604,2605,2606],"thead",{},[2607,2608,2609,2613,2616],"tr",{},[2610,2611,2612],"th",{},"Property",[2610,2614,2615],{},"Type",[2610,2617,2618],{},"Description",[2620,2621,2622,2636,2650,2667,2686],"tbody",{},[2607,2623,2624,2630,2633],{},[2625,2626,2627],"td",{},[2097,2628,2629],{},"id",[2625,2631,2632],{},"string",[2625,2634,2635],{},"A unique identifier for this extension. Lowercase letters, digits, and hyphens only.",[2607,2637,2638,2643,2645],{},[2625,2639,2640],{},[2097,2641,2642],{},"name",[2625,2644,2632],{},[2625,2646,2647,2648,2076],{},"The name shown in the field's ",[2074,2649,368],{},[2607,2651,2652,2657,2660],{},[2625,2653,2654],{},[2097,2655,2656],{},"extensions",[2625,2658,2659],{},"array",[2625,2661,2662,2663,2104],{},"Tiptap extensions, nodes, and marks to add to the editor. Each node and mark must follow the ",[2061,2664,2666],{"href":2665},"#round-trip-rule","round-trip rule",[2607,2668,2669,2674,2676],{},[2625,2670,2671],{},[2097,2672,2673],{},"buttons",[2625,2675,2659],{},[2625,2677,2678,2682,2683,2076],{},[2061,2679,2681],{"href":2680},"#toolbar-buttons","Toolbar buttons",". Admins add them to a field in the ",[2074,2684,2685],{},"Toolbar",[2607,2687,2688,2693,2695],{},[2625,2689,2690],{},[2097,2691,2692],{},"bubbleMenus",[2625,2694,2659],{},[2625,2696,2697,2701],{},[2061,2698,2700],{"href":2699},"#bubble-menus","Bubble menus",". They show on every field that enables the extension.",[2081,2703],{"content":2704},"extensions-uid",[2200,2706,2708],{"id":2707},"toolbar-buttons","Toolbar Buttons",[2057,2710,2711,2712,2715,2716,2719],{},"A button runs a ",[2097,2713,2714],{},"command",", or opens a dropdown of ",[2097,2717,2718],{},"items",". It cannot have both.",[2601,2721,2722,2732],{},[2604,2723,2724],{},[2607,2725,2726,2728,2730],{},[2610,2727,2612],{},[2610,2729,2615],{},[2610,2731,2618],{},[2620,2733,2734,2746,2768,2780,2795,2821,2839],{},[2607,2735,2736,2741,2743],{},[2625,2737,2738],{},[2097,2739,2740],{},"key",[2625,2742,2632],{},[2625,2744,2745],{},"Unique inside the extension. Lowercase letters, digits, and hyphens only.",[2607,2747,2748,2753,2755],{},[2625,2749,2750],{},[2097,2751,2752],{},"icon",[2625,2754,2632],{},[2625,2756,2757,2758,2763,2764,2767],{},"An icon name from the ",[2061,2759,2762],{"href":2760,"rel":2761},"https:\u002F\u002Ffonts.google.com\u002Ficons",[2065],"Google Material Icons set",". An unknown name shows the ",[2097,2765,2766],{},"extension"," icon.",[2607,2769,2770,2775,2777],{},[2625,2771,2772],{},[2097,2773,2774],{},"label",[2625,2776,2632],{},[2625,2778,2779],{},"Plain text shown for the button.",[2607,2781,2782,2786,2789],{},[2625,2783,2784],{},[2097,2785,2714],{},[2625,2787,2788],{},"function",[2625,2790,2791,2792,2794],{},"Receives the Tiptap ",[2097,2793,2513],{}," and runs when the user clicks the button.",[2607,2796,2797,2801,2803],{},[2625,2798,2799],{},[2097,2800,2718],{},[2625,2802,2659],{},[2625,2804,2805,2806,2252,2808,2252,2810,2812,2813,2252,2815,2817,2818,2104],{},"Dropdown entries. Each has a ",[2097,2807,2740],{},[2097,2809,2774],{},[2097,2811,2714],{},", and optional ",[2097,2814,2752],{},[2097,2816,2571],{},", and ",[2097,2819,2820],{},"isDisabled",[2607,2822,2823,2827,2829],{},[2625,2824,2825],{},[2097,2826,2571],{},[2625,2828,2788],{},[2625,2830,2831,2832,2834,2835,2838],{},"Receives the ",[2097,2833,2513],{}," and returns ",[2097,2836,2837],{},"true"," to show the button as active. A dropdown without it is active when one of its items is.",[2607,2840,2841,2845,2847],{},[2625,2842,2843],{},[2097,2844,2820],{},[2625,2846,2788],{},[2625,2848,2831,2849,2834,2851,2853],{},[2097,2850,2513],{},[2097,2852,2837],{}," to disable the button. A disabled or read-only field disables every button anyway.",[2200,2855,2857],{"id":2856},"bubble-menus","Bubble Menus",[2057,2859,2860,2861,2864,2865,2104],{},"A bubble menu floats next to the selection when ",[2097,2862,2863],{},"shouldShow"," returns ",[2097,2866,2837],{},[2601,2868,2869,2879],{},[2604,2870,2871],{},[2607,2872,2873,2875,2877],{},[2610,2874,2612],{},[2610,2876,2615],{},[2610,2878,2618],{},[2620,2880,2881,2892,2907],{},[2607,2882,2883,2887,2889],{},[2625,2884,2885],{},[2097,2886,2740],{},[2625,2888,2632],{},[2625,2890,2891],{},"Unique inside the extension.",[2607,2893,2894,2898,2900],{},[2625,2895,2896],{},[2097,2897,2863],{},[2625,2899,2788],{},[2625,2901,2831,2902,2834,2904,2906],{},[2097,2903,2513],{},[2097,2905,2837],{}," to show the menu.",[2607,2908,2909,2913,2915],{},[2625,2910,2911],{},[2097,2912,2673],{},[2625,2914,2659],{},[2625,2916,2917,2918,2920,2921,2923],{},"Toolbar buttons with a ",[2097,2919,2714],{},". Dropdowns with ",[2097,2922,2718],{}," are not supported.",[2057,2925,2926,2927,2104],{},"The editor hides bubble menus while the field is not editable, and while the cursor is in a table. When several menus match, only the first one shows. See ",[2061,2928,2930],{"href":2929},"#load-order","Load Order",[2085,2932,2934],{"id":2933},"enable-an-extension-on-a-field","Enable an Extension on a Field",[2057,2936,2937],{},"An admin chooses which fields use an extension. Content in other fields is not affected.",[2939,2940,2941,2944,2950,2955],"ol",{},[2093,2942,2943],{},"Open the settings of a field that uses the WYSIWYG interface.",[2093,2945,2946,2947,2949],{},"In ",[2074,2948,368],{},", select your extension. This option shows only when at least one rich text extension is installed.",[2093,2951,2946,2952,2954],{},[2074,2953,2685],{},", select your extension's buttons. The list shows them after you select the extension.",[2093,2956,2957],{},"Save the field.",[2057,2959,2960,2961,2964,2965,2968],{},"The stored toolbar key of a contributed button is ",[2097,2962,2963],{},"\u003Cextension id>:\u003Cbutton key>",", for example ",[2097,2966,2967],{},"callout:callout",". A contributed key never replaces a core button.",[2057,2970,2971],{},"The editor builds its schema when it opens. After you change a field's extensions, open the item again to use them.",[2200,2973,2930],{"id":2974},"load-order",[2057,2976,2977,2978,2980],{},"Directus sorts rich text extensions by ",[2097,2979,2629],{},". This order is the same on every deployment. It sets:",[2090,2982,2983,2986,2992],{},[2093,2984,2985],{},"Which extension wins when two use the same node or mark name.",[2093,2987,2988,2989,2991],{},"The order in which the editor tries their ",[2097,2990,2099],{}," rules.",[2093,2993,2994],{},"The order of contributed buttons in the toolbar, and which bubble menu shows when several match.",[2057,2996,2997,2998,2104],{},"Contributed buttons go after the core buttons. When the toolbar is too narrow, they are the first to move into ",[2074,2999,3000],{},"Show More",[2085,3002,3004],{"id":3003},"round-trip-rule","Round-Trip Rule",[2057,3006,3007,3008,3010,3011,3013],{},"The WYSIWYG interface stores HTML. When a field loads, the editor parses the stored HTML with each ",[2097,3009,2099],{}," rule. When it saves, it writes the HTML that ",[2097,3012,2103],{}," returns.",[2057,3015,3016,3017,3019,3020,3022],{},"Every node and mark must be symmetric. ",[2097,3018,2099],{}," must read back exactly the markup that ",[2097,3021,2103],{}," writes. If not, the saved HTML differs from the loaded HTML, and every save of a field that uses the extension warns the user that saving alters the content.",[2090,3024,3025,3031],{},[2093,3026,3027,3028,3030],{},"Match each attribute and data attribute that ",[2097,3029,2103],{}," writes.",[2093,3032,3033,3034,3037,3038,3041,3042,3044,3045,3048,3049,3051,3052,3055],{},"Raise the extension's ",[2097,3035,3036],{},"priority"," when a core rule matches the same markup first. For example, the core ",[2097,3039,3040],{},"textStyle"," mark claims any ",[2097,3043,2132],{}," with a ",[2097,3046,3047],{},"data-*"," attribute, so the ",[2097,3050,2121],{}," template sets ",[2097,3053,3054],{},"priority: 200"," on its mark.",[2057,3057,3058],{},"When the Data Studio loads, Directus checks each node and mark once and logs a console warning on a mismatch:",[2124,3060,3065],{"className":3061,"code":3063,"language":3064},[3062],"language-text","Richtext extension \"callout\": node \"callout\" does not survive a round trip. renderHTML writes \u003Cdiv data-callout=\"\">...\u003C\u002Fdiv>, which parses back as ...\n","text",[2097,3066,3063],{"__ignoreMap":24},[2057,3068,3069],{},"The check is best effort. It uses default attribute values only, and skips nodes that cannot stand alone, such as a list item. It does not detect a clash between two extensions. Test your extension by saving a field, and by opening the source code view and the comparison view.",[2085,3071,3073],{"id":3072},"names-and-validation","Names and Validation",[2057,3075,3076],{},"Directus validates each extension when the Data Studio loads. An extension that breaks a rule does not load, and the browser console shows the reason:",[2124,3078,3081],{"className":3079,"code":3080,"language":3064},[3062],"Richtext extension \"callout\" was not loaded: \"paragraph\" is a core node, mark or extension name\n",[2097,3082,3080],{"__ignoreMap":24},[2057,3084,3085],{},"Other extensions and the editor keep working. An extension is rejected when:",[2090,3087,3088,3094,3115,3126,3132,3158,3161],{},[2093,3089,3090,3091,3093],{},"Its ",[2097,3092,2629],{}," is not unique, or contains characters other than lowercase letters, digits, and hyphens.",[2093,3095,3096,3097,2252,3100,2252,3103,2252,3106,2252,3109,3111,3112,2104],{},"A node, mark, or extension uses a core name, such as ",[2097,3098,3099],{},"paragraph",[2097,3101,3102],{},"heading",[2097,3104,3105],{},"bold",[2097,3107,3108],{},"link",[2097,3110,2601],{},", or ",[2097,3113,3114],{},"image",[2093,3116,3117,3118,3121,3122,2104],{},"A name starts with ",[2097,3119,3120],{},"customFormat_",". This prefix is reserved for the field's ",[2061,3123,3125],{"href":3124},"\u002Fguides\u002Fdata-model\u002Frich-text#custom-formats","custom formats",[2093,3127,3128,3129,3131],{},"A name is already used by another rich text extension. The extension whose ",[2097,3130,2629],{}," sorts first keeps the name.",[2093,3133,3134,3135,2252,3138,2252,3140,2252,3143,2252,3146,2252,3149,2252,3152,3111,3155,2104],{},"An attribute uses a name the core editor keeps on every element: ",[2097,3136,3137],{},"class",[2097,3139,2629],{},[2097,3141,3142],{},"title",[2097,3144,3145],{},"role",[2097,3147,3148],{},"lang",[2097,3150,3151],{},"dir",[2097,3153,3154],{},"dataAttributes",[2097,3156,3157],{},"ariaAttributes",[2093,3159,3160],{},"A button, menu item, or bubble menu key is not unique in its list.",[2093,3162,3163],{},"It throws while Directus validates it or builds the editor schema with it.",[2085,3165,3167],{"id":3166},"error-handling","Error Handling",[2057,3169,3170],{},"A failing extension fails alone.",[2090,3172,3173,3176],{},[2093,3174,3175],{},"If the extension's code throws while it loads, Directus skips it.",[2093,3177,3178,3179,2252,3181,2252,3183,3111,3185,3187],{},"If a ",[2097,3180,2714],{},[2097,3182,2571],{},[2097,3184,2820],{},[2097,3186,2863],{}," callback throws, the editor disables that button or menu until the editor closes. The console shows the error. The core buttons keep working.",[2085,3189,3191],{"id":3190},"node-views","Node Views",[2057,3193,3194,3195,2252,3198,2817,3201,3204,3205,3208],{},"A node can render with a Vue component in the editor. Use ",[2097,3196,3197],{},"VueNodeViewRenderer",[2097,3199,3200],{},"NodeViewWrapper",[2097,3202,3203],{},"NodeViewContent"," from the shared ",[2097,3206,3207],{},"@tiptap\u002Fvue-3"," package.",[2124,3210,3212],{"className":2209,"code":3211,"language":2211,"meta":24,"style":24},"import { Node } from '@tiptap\u002Fcore';\nimport { VueNodeViewRenderer } from '@tiptap\u002Fvue-3';\nimport CardView from '.\u002Fcard-view.vue';\n\nconst Card = Node.create({\n    name: 'card',\n    group: 'block',\n    content: 'block+',\n    parseHTML: () => [{ tag: 'div[data-card]' }],\n    renderHTML: () => ['div', { 'data-card': '' }, 0],\n    addNodeView: () => VueNodeViewRenderer(CardView),\n});\n",[2097,3213,3214,3230,3247,3262,3266,3283,3292,3300,3308,3323,3351,3370],{"__ignoreMap":24},[2132,3215,3216,3218,3220,3222,3224,3226,3228],{"class":2134,"line":2135},[2132,3217,2219],{"class":2218},[2132,3219,2223],{"class":2222},[2132,3221,2249],{"class":2226},[2132,3223,2230],{"class":2222},[2132,3225,2233],{"class":2218},[2132,3227,2262],{"class":2142},[2132,3229,2239],{"class":2222},[2132,3231,3232,3234,3236,3238,3240,3242,3245],{"class":2134,"line":2242},[2132,3233,2219],{"class":2218},[2132,3235,2223],{"class":2222},[2132,3237,3197],{"class":2226},[2132,3239,2230],{"class":2222},[2132,3241,2233],{"class":2218},[2132,3243,3244],{"class":2142}," '@tiptap\u002Fvue-3'",[2132,3246,2239],{"class":2222},[2132,3248,3249,3251,3254,3257,3260],{"class":2134,"line":2267},[2132,3250,2219],{"class":2218},[2132,3252,3253],{"class":2226}," CardView",[2132,3255,3256],{"class":2218}," from",[2132,3258,3259],{"class":2142}," '.\u002Fcard-view.vue'",[2132,3261,2239],{"class":2222},[2132,3263,3264],{"class":2134,"line":2274},[2132,3265,2271],{"emptyLinePlaceholder":2270},[2132,3267,3268,3270,3273,3275,3277,3279,3281],{"class":2134,"line":2297},[2132,3269,2277],{"class":2218},[2132,3271,3272],{"class":2138}," Card",[2132,3274,2283],{"class":2218},[2132,3276,2286],{"class":2226},[2132,3278,2104],{"class":2222},[2132,3280,2291],{"class":2138},[2132,3282,2294],{"class":2222},[2132,3284,3285,3287,3290],{"class":2134,"line":2309},[2132,3286,2300],{"class":2222},[2132,3288,3289],{"class":2142},"'card'",[2132,3291,2306],{"class":2222},[2132,3293,3294,3296,3298],{"class":2134,"line":2320},[2132,3295,2312],{"class":2222},[2132,3297,2315],{"class":2142},[2132,3299,2306],{"class":2222},[2132,3301,3302,3304,3306],{"class":2134,"line":2331},[2132,3303,2323],{"class":2222},[2132,3305,2326],{"class":2142},[2132,3307,2306],{"class":2222},[2132,3309,3310,3312,3314,3316,3318,3321],{"class":2134,"line":2352},[2132,3311,2334],{"class":2138},[2132,3313,2337],{"class":2222},[2132,3315,2340],{"class":2218},[2132,3317,2343],{"class":2222},[2132,3319,3320],{"class":2142},"'div[data-card]'",[2132,3322,2349],{"class":2222},[2132,3324,3325,3327,3329,3331,3333,3335,3337,3340,3342,3344,3347,3349],{"class":2134,"line":2405},[2132,3326,2355],{"class":2138},[2132,3328,2337],{"class":2222},[2132,3330,2340],{"class":2218},[2132,3332,2369],{"class":2222},[2132,3334,2372],{"class":2142},[2132,3336,2384],{"class":2222},[2132,3338,3339],{"class":2142},"'data-card'",[2132,3341,2390],{"class":2222},[2132,3343,2393],{"class":2142},[2132,3345,3346],{"class":2222}," }, ",[2132,3348,2399],{"class":2138},[2132,3350,2402],{"class":2222},[2132,3352,3353,3356,3358,3360,3363,3365,3368],{"class":2134,"line":2411},[2132,3354,3355],{"class":2138},"    addNodeView",[2132,3357,2337],{"class":2222},[2132,3359,2340],{"class":2218},[2132,3361,3362],{"class":2138}," VueNodeViewRenderer",[2132,3364,2379],{"class":2222},[2132,3366,3367],{"class":2226},"CardView",[2132,3369,2578],{"class":2222},[2132,3371,3372],{"class":2134,"line":2416},[2132,3373,2408],{"class":2222},[2057,3375,3376,3377,3379],{},"The field saves the ",[2097,3378,2103],{}," output, not the markup of the node view. Controls you add in the node view are never stored.",[2057,3381,3382,3383,3386,3387,3390],{},"To hide edit controls when the field is not editable, use ",[2097,3384,3385],{},"useRichTextEditable()",". Do not use ",[2097,3388,3389],{},"editor.isEditable",". It does not update when the field later becomes read-only, disabled, or locked.",[2124,3392,3396],{"className":3393,"code":3394,"language":3395,"meta":24,"style":24},"language-vue shiki shiki-themes directus-light directus-light directus-dark","\u003Ctemplate>\n    \u003CNodeViewWrapper class=\"card\">\n        \u003Cbutton v-if=\"editable\" type=\"button\" @click=\"deleteNode()\">Remove\u003C\u002Fbutton>\n        \u003CNodeViewContent \u002F>\n    \u003C\u002FNodeViewWrapper>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { useRichTextEditable } from '@directus\u002Fextensions-sdk';\nimport { NodeViewContent, NodeViewWrapper, nodeViewProps } from '@tiptap\u002Fvue-3';\n\nconst { deleteNode } = defineProps(nodeViewProps);\nconst editable = useRichTextEditable();\n\u003C\u002Fscript>\n","vue",[2097,3397,3398,3410,3428,3467,3476,3485,3494,3498,3510,3527,3552,3556,3579,3594],{"__ignoreMap":24},[2132,3399,3400,3403,3407],{"class":2134,"line":2135},[2132,3401,3402],{"class":2222},"\u003C",[2132,3404,3406],{"class":3405},"s3wuB","template",[2132,3408,3409],{"class":2222},">\n",[2132,3411,3412,3415,3417,3420,3423,3426],{"class":2134,"line":2242},[2132,3413,3414],{"class":2222},"    \u003C",[2132,3416,3200],{"class":3405},[2132,3418,3419],{"class":2138}," class",[2132,3421,3422],{"class":2222},"=",[2132,3424,3425],{"class":2142},"\"card\"",[2132,3427,3409],{"class":2222},[2132,3429,3430,3433,3436,3439,3441,3444,3447,3449,3452,3455,3457,3460,3463,3465],{"class":2134,"line":2267},[2132,3431,3432],{"class":2222},"        \u003C",[2132,3434,3435],{"class":3405},"button",[2132,3437,3438],{"class":2138}," v-if",[2132,3440,3422],{"class":2222},[2132,3442,3443],{"class":2142},"\"editable\"",[2132,3445,3446],{"class":2138}," type",[2132,3448,3422],{"class":2222},[2132,3450,3451],{"class":2142},"\"button\"",[2132,3453,3454],{"class":2138}," @click",[2132,3456,3422],{"class":2222},[2132,3458,3459],{"class":2142},"\"deleteNode()\"",[2132,3461,3462],{"class":2222},">Remove\u003C\u002F",[2132,3464,3435],{"class":3405},[2132,3466,3409],{"class":2222},[2132,3468,3469,3471,3473],{"class":2134,"line":2274},[2132,3470,3432],{"class":2222},[2132,3472,3203],{"class":3405},[2132,3474,3475],{"class":2222}," \u002F>\n",[2132,3477,3478,3481,3483],{"class":2134,"line":2297},[2132,3479,3480],{"class":2222},"    \u003C\u002F",[2132,3482,3200],{"class":3405},[2132,3484,3409],{"class":2222},[2132,3486,3487,3490,3492],{"class":2134,"line":2309},[2132,3488,3489],{"class":2222},"\u003C\u002F",[2132,3491,3406],{"class":3405},[2132,3493,3409],{"class":2222},[2132,3495,3496],{"class":2134,"line":2320},[2132,3497,2271],{"emptyLinePlaceholder":2270},[2132,3499,3500,3502,3505,3508],{"class":2134,"line":2331},[2132,3501,3402],{"class":2222},[2132,3503,3504],{"class":3405},"script",[2132,3506,3507],{"class":2138}," setup",[2132,3509,3409],{"class":2222},[2132,3511,3512,3514,3516,3519,3521,3523,3525],{"class":2134,"line":2352},[2132,3513,2219],{"class":2218},[2132,3515,2223],{"class":2222},[2132,3517,3518],{"class":2226},"useRichTextEditable",[2132,3520,2230],{"class":2222},[2132,3522,2233],{"class":2218},[2132,3524,2236],{"class":2142},[2132,3526,2239],{"class":2222},[2132,3528,3529,3531,3533,3535,3537,3539,3541,3544,3546,3548,3550],{"class":2134,"line":2405},[2132,3530,2219],{"class":2218},[2132,3532,2223],{"class":2222},[2132,3534,3203],{"class":2226},[2132,3536,2252],{"class":2222},[2132,3538,3200],{"class":2226},[2132,3540,2252],{"class":2222},[2132,3542,3543],{"class":2226},"nodeViewProps",[2132,3545,2230],{"class":2222},[2132,3547,2233],{"class":2218},[2132,3549,3244],{"class":2142},[2132,3551,2239],{"class":2222},[2132,3553,3554],{"class":2134,"line":2411},[2132,3555,2271],{"emptyLinePlaceholder":2270},[2132,3557,3558,3560,3562,3565,3567,3569,3572,3574,3576],{"class":2134,"line":2416},[2132,3559,2277],{"class":2218},[2132,3561,2223],{"class":2222},[2132,3563,3564],{"class":2138},"deleteNode",[2132,3566,2230],{"class":2222},[2132,3568,3422],{"class":2218},[2132,3570,3571],{"class":2138}," defineProps",[2132,3573,2379],{"class":2222},[2132,3575,3543],{"class":2226},[2132,3577,3578],{"class":2222},");\n",[2132,3580,3581,3583,3586,3588,3591],{"class":2134,"line":2430},[2132,3582,2277],{"class":2218},[2132,3584,3585],{"class":2138}," editable",[2132,3587,2283],{"class":2218},[2132,3589,3590],{"class":2138}," useRichTextEditable",[2132,3592,3593],{"class":2222},"();\n",[2132,3595,3596,3598,3600],{"class":2134,"line":2440},[2132,3597,3489],{"class":2222},[2132,3599,3504],{"class":3405},[2132,3601,3409],{"class":2222},[2057,3603,3604,3606,3607,2104],{},[2097,3605,3385],{}," returns a read-only ref. Outside the WYSIWYG interface, its value is always ",[2097,3608,2837],{},[2085,3610,3612],{"id":3611},"style-your-nodes","Style Your Nodes",[2057,3614,3615],{},"Import a CSS file in your entrypoint. The extensions SDK bundles it and adds it to the page when the extension loads.",[2057,3617,3618,3619,3622],{},"Scope every rule under the ",[2097,3620,3621],{},".richtext-content"," class. The editor root has this class in edit mode, in read-only mode, and in the comparison view.",[2124,3624,3628],{"className":3625,"code":3626,"language":3627,"meta":24,"style":24},"language-css shiki shiki-themes directus-light directus-light directus-dark",".richtext-content div[data-callout] {\n    padding: 12px 16px;\n    border-inline-start: 4px solid var(--theme--primary);\n    background-color: var(--theme--primary-background);\n}\n","css",[2097,3629,3630,3646,3667,3692,3709],{"__ignoreMap":24},[2132,3631,3632,3634,3637,3640,3643],{"class":2134,"line":2135},[2132,3633,3621],{"class":2138},[2132,3635,3636],{"class":3405}," div",[2132,3638,3639],{"class":2222},"[",[2132,3641,3642],{"class":2138},"data-callout",[2132,3644,3645],{"class":2222},"] {\n",[2132,3647,3648,3652,3654,3657,3660,3663,3665],{"class":2134,"line":2242},[2132,3649,3651],{"class":3650},"sxEyJ","    padding",[2132,3653,2390],{"class":2222},[2132,3655,3656],{"class":2138},"12",[2132,3658,3659],{"class":2218},"px",[2132,3661,3662],{"class":2138}," 16",[2132,3664,3659],{"class":2218},[2132,3666,2239],{"class":2222},[2132,3668,3669,3672,3674,3677,3679,3682,3685,3687,3690],{"class":2134,"line":2267},[2132,3670,3671],{"class":3650},"    border-inline-start",[2132,3673,2390],{"class":2222},[2132,3675,3676],{"class":2138},"4",[2132,3678,3659],{"class":2218},[2132,3680,3681],{"class":3650}," solid",[2132,3683,3684],{"class":3650}," var",[2132,3686,2379],{"class":2222},[2132,3688,3689],{"class":2218},"--theme--primary",[2132,3691,3578],{"class":2222},[2132,3693,3694,3697,3699,3702,3704,3707],{"class":2134,"line":2274},[2132,3695,3696],{"class":3650},"    background-color",[2132,3698,2390],{"class":2222},[2132,3700,3701],{"class":3650},"var",[2132,3703,2379],{"class":2222},[2132,3705,3706],{"class":2218},"--theme--primary-background",[2132,3708,3578],{"class":2222},[2132,3710,3711],{"class":2134,"line":2297},[2132,3712,3713],{"class":2222},"}\n",[2057,3715,3716],{},"The core editor styles use low specificity, so your rules override them. The comparison view's change highlights always stay visible.",[2057,3718,3719,3720,3722],{},"These styles apply in the Data Studio only. Your frontend renders the stored HTML, so add matching styles there. See ",[2061,3721,877],{"href":878}," for how to style the editor output on your frontend.",[2085,3724,3726],{"id":3725},"remove-an-extension","Remove an Extension",[2057,3728,3729],{},"When an admin removes an extension from a field, or uninstalls it, the field's schema no longer contains its nodes and marks. Content that still uses them follows the same flow as other markup the editor does not support:",[2939,3731,3732,3735,3738],{},[2093,3733,3734],{},"The field opens read-only and shows a notice.",[2093,3736,3737],{},"The user selects the field and can view the changes as a diff.",[2093,3739,3740,3741,2252,3744,3111,3747,2104],{},"The user chooses ",[2074,3742,3743],{},"Keep Read-only",[2074,3745,3746],{},"Edit Anyway",[2074,3748,3749],{},"Edit Raw HTML",[2057,3751,3752,3754,3755,3757],{},[2074,3753,3746],{}," removes the extension's markup when the user saves. ",[2074,3756,3749],{}," edits the stored HTML as text and keeps it. Enable the extension again to edit the content in the editor without losing markup.",[3759,3760,3763],"callout",{"color":3761,"icon":3762},"warning","i-lucide-triangle-alert",[2057,3764,3765,3766,2104],{},"Saved content keeps the extension's markup until a user saves the field without it. If a user saves without it by mistake, restore the earlier version from ",[2074,3767,3768],{},"Revisions",[2085,3770,3772],{"id":3771},"wrap-an-existing-tiptap-package","Wrap an Existing Tiptap Package",[2057,3774,3775],{},"You can add a published Tiptap extension package to Directus.",[2939,3777,3778,3781,3791],{},[2093,3779,3780],{},"Install the package as a dependency of your extension. Use a version from the same Tiptap major as Directus.",[2093,3782,3783,3784,3786,3787,3790],{},"Add it to ",[2097,3785,2656],{},", with ",[2097,3788,3789],{},".configure()"," for its options.",[2093,3792,3793],{},"Add buttons that run its commands.",[2124,3795,3797],{"className":2209,"code":3796,"language":2211,"meta":24,"style":24},"import { defineRichText } from '@directus\u002Fextensions-sdk';\nimport Youtube from '@tiptap\u002Fextension-youtube';\n\nexport default defineRichText({\n    id: 'youtube',\n    name: 'YouTube',\n    extensions: [Youtube.extend({ priority: 1000 }).configure({ nocookie: true })],\n    buttons: [\n        {\n            key: 'embed',\n            icon: 'smart_display',\n            label: 'Embed YouTube video',\n            command: (editor) => {\n                const src = window.prompt('YouTube URL');\n                if (src) editor.commands.setYoutubeVideo({ src });\n            },\n        },\n    ],\n});\n",[2097,3798,3799,3815,3829,3833,3843,3852,3861,3893,3897,3901,3910,3919,3928,3943,3968,4001,4006,4010,4014],{"__ignoreMap":24},[2132,3800,3801,3803,3805,3807,3809,3811,3813],{"class":2134,"line":2135},[2132,3802,2219],{"class":2218},[2132,3804,2223],{"class":2222},[2132,3806,2227],{"class":2226},[2132,3808,2230],{"class":2222},[2132,3810,2233],{"class":2218},[2132,3812,2236],{"class":2142},[2132,3814,2239],{"class":2222},[2132,3816,3817,3819,3822,3824,3827],{"class":2134,"line":2242},[2132,3818,2219],{"class":2218},[2132,3820,3821],{"class":2226}," Youtube",[2132,3823,3256],{"class":2218},[2132,3825,3826],{"class":2142}," '@tiptap\u002Fextension-youtube'",[2132,3828,2239],{"class":2222},[2132,3830,3831],{"class":2134,"line":2267},[2132,3832,2271],{"emptyLinePlaceholder":2270},[2132,3834,3835,3837,3839,3841],{"class":2134,"line":2274},[2132,3836,2419],{"class":2218},[2132,3838,2422],{"class":2218},[2132,3840,2425],{"class":2138},[2132,3842,2294],{"class":2222},[2132,3844,3845,3847,3850],{"class":2134,"line":2297},[2132,3846,2433],{"class":2222},[2132,3848,3849],{"class":2142},"'youtube'",[2132,3851,2306],{"class":2222},[2132,3853,3854,3856,3859],{"class":2134,"line":2309},[2132,3855,2300],{"class":2222},[2132,3857,3858],{"class":2142},"'YouTube'",[2132,3860,2306],{"class":2222},[2132,3862,3863,3865,3868,3870,3873,3876,3879,3882,3885,3888,3890],{"class":2134,"line":2320},[2132,3864,2453],{"class":2222},[2132,3866,3867],{"class":2226},"Youtube",[2132,3869,2104],{"class":2222},[2132,3871,3872],{"class":2138},"extend",[2132,3874,3875],{"class":2222},"({ priority: ",[2132,3877,3878],{"class":2138},"1000",[2132,3880,3881],{"class":2222}," }).",[2132,3883,3884],{"class":2138},"configure",[2132,3886,3887],{"class":2222},"({ nocookie: ",[2132,3889,2837],{"class":2138},[2132,3891,3892],{"class":2222}," })],\n",[2132,3894,3895],{"class":2134,"line":2331},[2132,3896,2464],{"class":2222},[2132,3898,3899],{"class":2134,"line":2352},[2132,3900,2470],{"class":2222},[2132,3902,3903,3905,3908],{"class":2134,"line":2405},[2132,3904,2476],{"class":2222},[2132,3906,3907],{"class":2142},"'embed'",[2132,3909,2306],{"class":2222},[2132,3911,3912,3914,3917],{"class":2134,"line":2411},[2132,3913,2486],{"class":2222},[2132,3915,3916],{"class":2142},"'smart_display'",[2132,3918,2306],{"class":2222},[2132,3920,3921,3923,3926],{"class":2134,"line":2416},[2132,3922,2497],{"class":2222},[2132,3924,3925],{"class":2142},"'Embed YouTube video'",[2132,3927,2306],{"class":2222},[2132,3929,3930,3932,3934,3936,3938,3940],{"class":2134,"line":2430},[2132,3931,2507],{"class":2138},[2132,3933,2510],{"class":2222},[2132,3935,2513],{"class":2218},[2132,3937,2516],{"class":2222},[2132,3939,2340],{"class":2218},[2132,3941,3942],{"class":2222}," {\n",[2132,3944,3945,3948,3951,3953,3956,3958,3961,3963,3966],{"class":2134,"line":2440},[2132,3946,3947],{"class":2218},"                const",[2132,3949,3950],{"class":2138}," src",[2132,3952,2283],{"class":2218},[2132,3954,3955],{"class":2226}," window",[2132,3957,2104],{"class":2222},[2132,3959,3960],{"class":2138},"prompt",[2132,3962,2379],{"class":2222},[2132,3964,3965],{"class":2142},"'YouTube URL'",[2132,3967,3578],{"class":2222},[2132,3969,3970,3973,3976,3979,3981,3983,3985,3988,3990,3993,3996,3998],{"class":2134,"line":2450},[2132,3971,3972],{"class":2218},"                if",[2132,3974,3975],{"class":2222}," (",[2132,3977,3978],{"class":2226},"src",[2132,3980,2516],{"class":2222},[2132,3982,2513],{"class":2226},[2132,3984,2104],{"class":2222},[2132,3986,3987],{"class":2226},"commands",[2132,3989,2104],{"class":2222},[2132,3991,3992],{"class":2138},"setYoutubeVideo",[2132,3994,3995],{"class":2222},"({ ",[2132,3997,3978],{"class":2226},[2132,3999,4000],{"class":2222}," });\n",[2132,4002,4003],{"class":2134,"line":2461},[2132,4004,4005],{"class":2222},"            },\n",[2132,4007,4008],{"class":2134,"line":2467},[2132,4009,2584],{"class":2222},[2132,4011,4012],{"class":2134,"line":2473},[2132,4013,2590],{"class":2222},[2132,4015,4016],{"class":2134,"line":2483},[2132,4017,2408],{"class":2222},[2057,4019,4020],{},"The extensions SDK bundles the package code but keeps its Tiptap and ProseMirror imports on the shared copy. Before you publish, check the package against the rules on this page:",[2090,4022,4023,4029,4049],{},[2093,4024,4025,4026,2104],{},"If its name is a core name, rename it with ",[2097,4027,4028],{},".extend({ name: '...' })",[2093,4030,4031,4032,4034,4035,4038,4039,2252,4042,2817,4045,4048],{},"If a core rule claims its markup first, raise its ",[2097,4033,3036],{}," with ",[2097,4036,4037],{},".extend()",", as in the example. The core editor parses ",[2097,4040,4041],{},"iframe",[2097,4043,4044],{},"video",[2097,4046,4047],{},"audio"," elements as media.",[2093,4050,4051],{},"Save a field that uses it, and check the console for a round-trip warning.",[2085,4053,4055],{"id":4054},"tiptap-version-policy","Tiptap Version Policy",[2057,4057,4058],{},"A rich text extension uses the copy of Tiptap that ships with the Data Studio. The extensions SDK does not bundle the shared Tiptap packages, so the editor and your extension use the same ProseMirror classes. ProseMirror checks objects by class, so objects from a second copy of ProseMirror fail these checks and the editor behaves incorrectly.",[2057,4060,4061,4062,2252,4064,2252,4067,2817,4070,4073],{},"This makes the Tiptap version part of the extension API. A new Tiptap major version can break every installed rich text extension. Directus shares ",[2097,4063,3395],{},[2097,4065,4066],{},"vue-router",[2097,4068,4069],{},"vue-i18n",[2097,4071,4072],{},"pinia"," with app extensions in the same way.",[2200,4075,2154],{"id":4076},"shared-tiptap-packages",[2057,4078,4079],{},"Import the following packages directly in your extension. The extensions SDK marks them as external when it builds, so your bundle uses the Data Studio's copy and does not include them.",[2090,4081,4082,4086,4090],{},[2093,4083,4084],{},[2097,4085,2149],{},[2093,4087,4088],{},[2097,4089,3207],{},[2093,4091,4092,4093,4096,4097,2252,4099,2252,4102,2252,4105,2252,4108,2252,4111,2252,4114,2252,4117,2252,4120,2252,4123,2817,4126,4129,4130,2104],{},"These ",[2097,4094,4095],{},"@tiptap\u002Fpm"," subpaths: ",[2097,4098,3987],{},[2097,4100,4101],{},"dropcursor",[2097,4103,4104],{},"gapcursor",[2097,4106,4107],{},"history",[2097,4109,4110],{},"keymap",[2097,4112,4113],{},"model",[2097,4115,4116],{},"schema-list",[2097,4118,4119],{},"state",[2097,4121,4122],{},"tables",[2097,4124,4125],{},"transform",[2097,4127,4128],{},"view",". For example, ",[2097,4131,4132],{},"@tiptap\u002Fpm\u002Fkeymap",[2057,4134,4135,4136,4138,4139,4141,4142,4145,4146,4149],{},"Each ",[2097,4137,4095],{}," subpath re-exports one ProseMirror package. For example, ",[2097,4140,4132],{}," re-exports ",[2097,4143,4144],{},"prosemirror-keymap",". When your code or a package you install imports a ProseMirror package behind a shared subpath by its own name, the extensions SDK changes the import to that subpath. So you can install Tiptap packages that use ProseMirror, such as ",[2097,4147,4148],{},"@tiptap\u002Fextension-table",". The SDK bundles the code of the package itself, but it uses the Data Studio's copy of ProseMirror.",[2057,4151,4152,4153,2194,4156,4159],{},"The Data Studio does not use ",[2097,4154,4155],{},"@tiptap\u002Fpm\u002Fchangeset",[2097,4157,4158],{},"@tiptap\u002Fpm\u002Finputrules",", so the extensions SDK bundles them into your extension. This is safe. They do not contain ProseMirror classes or plugin keys that the editor checks, and their own ProseMirror imports go to the shared subpaths.",[2057,4161,4162],{},"If you install other Tiptap packages, use a version from the same Tiptap major as Directus.",[2200,4164,4166],{"id":4165},"version-guarantees","Version Guarantees",[2601,4168,4169,4178],{},[2604,4170,4171],{},[2607,4172,4173,4176],{},[2610,4174,4175],{},"Directus",[2610,4177,2066],{},[2620,4179,4180],{},[2607,4181,4182,4185],{},[2625,4183,4184],{},"12.x",[2625,4186,4187],{},"3.x",[2090,4189,4190,4193,4196],{},[2093,4191,4192],{},"Directus pins the Tiptap major version. Tiptap minor and patch updates can ship in any Directus release.",[2093,4194,4195],{},"A new Tiptap major version ships only in a new Directus major version.",[2093,4197,2190,4198,4201],{},[2061,4199,4200],{"href":1585},"breaking changes"," page for that Directus version lists the Tiptap upgrade.",[2200,4203,2173],{"id":4204},"set-the-host-range",[2057,4206,2190,4207,4209,4210,4212],{},[2097,4208,2168],{}," field in your extension's ",[2097,4211,2160],{}," declares the Directus versions it supports. Set it to a caret range on the Directus version you build against.",[2124,4214,4218],{"className":4215,"code":4216,"language":4217,"meta":24,"style":24},"language-json shiki shiki-themes directus-light directus-light directus-dark","\"directus:extension\": {\n    \"type\": \"richtext\",\n    \"path\": \"dist\u002Findex.js\",\n    \"source\": \"src\u002Findex.js\",\n    \"host\": \"^12.6.0\"\n}\n","json",[2097,4219,4220,4228,4240,4252,4264,4274],{"__ignoreMap":24},[2132,4221,4222,4225],{"class":2134,"line":2135},[2132,4223,4224],{"class":2142},"\"directus:extension\"",[2132,4226,4227],{"class":2222},": {\n",[2132,4229,4230,4233,4235,4238],{"class":2134,"line":2242},[2132,4231,4232],{"class":3650},"    \"type\"",[2132,4234,2390],{"class":2222},[2132,4236,4237],{"class":2142},"\"richtext\"",[2132,4239,2306],{"class":2222},[2132,4241,4242,4245,4247,4250],{"class":2134,"line":2267},[2132,4243,4244],{"class":3650},"    \"path\"",[2132,4246,2390],{"class":2222},[2132,4248,4249],{"class":2142},"\"dist\u002Findex.js\"",[2132,4251,2306],{"class":2222},[2132,4253,4254,4257,4259,4262],{"class":2134,"line":2274},[2132,4255,4256],{"class":3650},"    \"source\"",[2132,4258,2390],{"class":2222},[2132,4260,4261],{"class":2142},"\"src\u002Findex.js\"",[2132,4263,2306],{"class":2222},[2132,4265,4266,4269,4271],{"class":2134,"line":2297},[2132,4267,4268],{"class":3650},"    \"host\"",[2132,4270,2390],{"class":2222},[2132,4272,4273],{"class":2142},"\"^12.6.0\"\n",[2132,4275,4276],{"class":2134,"line":2309},[2132,4277,3713],{"class":2222},[2057,4279,4280],{},"A caret range stops at the next major version. When a Directus major version upgrades Tiptap, your range no longer matches it.",[2057,4282,4283,4284,4286,4287,2104],{},"The Marketplace compares ",[2097,4285,2168],{}," with the project's Directus version. When the range does not match, the extension's page shows ",[2074,4288,4289],{},"Compatibility not guaranteed",[3759,4291,4292],{"color":3761,"icon":3762},[2057,4293,4294,4295,4297],{},"Directus does not check ",[2097,4296,2168],{}," when it loads an extension. An extension that you install manually loads on any version. Read the breaking changes before you upgrade a project that uses rich text extensions.",[2200,4299,4301],{"id":4300},"upgrade-after-a-tiptap-major-version","Upgrade After a Tiptap Major Version",[2057,4303,4304],{},"When a Directus major version upgrades Tiptap, update your extension before your users upgrade.",[2939,4306,4307,4310,4313,4316,4325],{},[2093,4308,4309],{},"Read the breaking changes for the new Directus version and Tiptap's upgrade notes.",[2093,4311,4312],{},"Update the Tiptap APIs your extension uses.",[2093,4314,4315],{},"Build the extension and test it on the new Directus version.",[2093,4317,4318,4319,4321,4322,2104],{},"Set ",[2097,4320,2168],{}," to the new major version, for example ",[2097,4323,4324],{},"^13.0.0",[2093,4326,4327],{},"Publish the update as a new major version of your extension.",[2085,4329,4331],{"id":4330},"next-steps","Next Steps",[2057,4333,4334,4335,4338,4339,2817,4342,4344],{},"Read about ",[2061,4336,4337],{"href":1262},"publishing to the Marketplace",", the ",[2061,4340,4341],{"href":2070},"WYSIWYG interface options",[2061,4343,3125],{"href":878}," for the editor.",[4346,4347,4348],"style",{},"html pre.shiki code .s6TUV, html code.shiki .s6TUV{--shiki-light:#531EE3;--shiki-default:#531EE3;--shiki-dark:#9B8BFF}html pre.shiki code .suKVh, html code.shiki .suKVh{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#F8FAFC}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sb-bW, html code.shiki .sb-bW{--shiki-light:#CA0C72;--shiki-default:#CA0C72;--shiki-dark:#FF97DC}html pre.shiki code .sTMul, html code.shiki .sTMul{--shiki-light:#1F2937;--shiki-default:#1F2937;--shiki-dark:#94A3B8}html pre.shiki code .sNJ9c, html code.shiki .sNJ9c{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E2E8F0}html pre.shiki code .s3wuB, html code.shiki .s3wuB{--shiki-light:#22863A;--shiki-default:#22863A;--shiki-dark:#22863A}html pre.shiki code .sxEyJ, html code.shiki .sxEyJ{--shiki-light:#4418BF;--shiki-default:#4418BF;--shiki-dark:#6644FF}",{"title":24,"searchDepth":2135,"depth":2242,"links":4350},[4351,4352,4353,4359,4362,4363,4364,4365,4366,4367,4368,4369,4375],{"id":2087,"depth":2242,"text":2088},{"id":2114,"depth":2242,"text":2115},{"id":2186,"depth":2242,"text":2187,"children":4354},[4355,4356,4357,4358],{"id":2202,"depth":2267,"text":2203},{"id":2598,"depth":2267,"text":2599},{"id":2707,"depth":2267,"text":2708},{"id":2856,"depth":2267,"text":2857},{"id":2933,"depth":2242,"text":2934,"children":4360},[4361],{"id":2974,"depth":2267,"text":2930},{"id":3003,"depth":2242,"text":3004},{"id":3072,"depth":2242,"text":3073},{"id":3166,"depth":2242,"text":3167},{"id":3190,"depth":2242,"text":3191},{"id":3611,"depth":2242,"text":3612},{"id":3725,"depth":2242,"text":3726},{"id":3771,"depth":2242,"text":3772},{"id":4054,"depth":2242,"text":4055,"children":4370},[4371,4372,4373,4374],{"id":4076,"depth":2267,"text":2154},{"id":4165,"depth":2267,"text":4166},{"id":4204,"depth":2267,"text":2173},{"id":4300,"depth":2267,"text":4301},{"id":4330,"depth":2242,"text":4331},"md",{},{"title":877},"---\nstableId: c00df192-7fcb-457e-8fc8-fc05b853f88a\ntitle: Rich Text Extensions\ndescription: Rich text extensions add Tiptap nodes, marks, and toolbar buttons to the WYSIWYG interface.\nnavigation:\n  title: Rich Text\n---\n\nRich text extensions add [Tiptap](https:\u002F\u002Ftiptap.dev) nodes, marks, and toolbar buttons to the [WYSIWYG interface](\u002Fguides\u002Fdata-model\u002Finterfaces#wysiwyg). A field uses an extension only when you select it in the interface's **Extensions** option.\n\nYou write nodes and marks with the standard Tiptap API. Directus adds a small config around them, and a set of rules that keep content intact when users save, compare, or remove an extension.\n\n:partial{content=\"extensions-app\"}\n\n## Before You Start\n\n- You know how to write a Tiptap node or mark with `parseHTML` and `renderHTML`.\n- You have a Directus project to test in. Set `EXTENSIONS_AUTO_RELOAD=true` while you develop.\n\n## Create an Extension\n\nRun the extensions CLI and select the `richtext` type:\n\n```shell\nnpx create-directus-extension@latest\n```\n\nThe template contains one mark and one toolbar button. It adds `@tiptap\u002Fcore` as a dev dependency so your editor can type-check Tiptap imports. The build does not bundle it. See [Shared Tiptap Packages](#shared-tiptap-packages).\n\nThe generated `package.json` declares the extension type in `directus:extension`. Before you publish, set its `host` field as described in [Set the Host Range](#set-the-host-range).\n\nRich text extensions load in the Data Studio only. You can also add one to a [bundle](\u002Fguides\u002Fextensions\u002Fbundles) as a `richtext` entry.\n\n## Rich Text Entrypoint\n\nThe `index.js` or `index.ts` file exports the config. It lists the Tiptap extensions to add to the editor schema, and the buttons that act on them.\n\n### Entrypoint Example\n\nThis example adds a callout block and a toolbar button that wraps the selection in it.\n\n```js\nimport { defineRichText } from '@directus\u002Fextensions-sdk';\nimport { Node, mergeAttributes } from '@tiptap\u002Fcore';\n\nconst Callout = Node.create({\n\tname: 'callout',\n\tgroup: 'block',\n\tcontent: 'block+',\n\tparseHTML: () => [{ tag: 'div[data-callout]' }],\n\trenderHTML: ({ HTMLAttributes }) => ['div', mergeAttributes(HTMLAttributes, { 'data-callout': '' }), 0],\n});\n\nexport default defineRichText({\n\tid: 'callout',\n\tname: 'Callout',\n\textensions: [Callout],\n\tbuttons: [\n\t\t{\n\t\t\tkey: 'callout',\n\t\t\ticon: 'info',\n\t\t\tlabel: 'Callout',\n\t\t\tcommand: (editor) => editor.chain().focus().toggleWrap('callout').run(),\n\t\t\tisActive: (editor) => editor.isActive('callout'),\n\t\t},\n\t],\n});\n```\n\n### Properties\n\n| Property      | Type   | Description                                                                                                                       |\n| ------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------- |\n| `id`          | string | A unique identifier for this extension. Lowercase letters, digits, and hyphens only.                                              |\n| `name`        | string | The name shown in the field's **Extensions** option.                                                                              |\n| `extensions`  | array  | Tiptap extensions, nodes, and marks to add to the editor. Each node and mark must follow the [round-trip rule](#round-trip-rule). |\n| `buttons`     | array  | [Toolbar buttons](#toolbar-buttons). Admins add them to a field in the **Toolbar** option.                                        |\n| `bubbleMenus` | array  | [Bubble menus](#bubble-menus). They show on every field that enables the extension.                                               |\n\n:partial{content=\"extensions-uid\"}\n\n### Toolbar Buttons\n\nA button runs a `command`, or opens a dropdown of `items`. It cannot have both.\n\n| Property     | Type     | Description                                                                                                                     |\n| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| `key`        | string   | Unique inside the extension. Lowercase letters, digits, and hyphens only.                                                       |\n| `icon`       | string   | An icon name from the [Google Material Icons set](https:\u002F\u002Ffonts.google.com\u002Ficons). An unknown name shows the `extension` icon.   |\n| `label`      | string   | Plain text shown for the button.                                                                                                |\n| `command`    | function | Receives the Tiptap `editor` and runs when the user clicks the button.                                                          |\n| `items`      | array    | Dropdown entries. Each has a `key`, `label`, `command`, and optional `icon`, `isActive`, and `isDisabled`.                      |\n| `isActive`   | function | Receives the `editor` and returns `true` to show the button as active. A dropdown without it is active when one of its items is. |\n| `isDisabled` | function | Receives the `editor` and returns `true` to disable the button. A disabled or read-only field disables every button anyway.     |\n\n### Bubble Menus\n\nA bubble menu floats next to the selection when `shouldShow` returns `true`.\n\n| Property     | Type     | Description                                                                 |\n| ------------ | -------- | --------------------------------------------------------------------------- |\n| `key`        | string   | Unique inside the extension.                                                |\n| `shouldShow` | function | Receives the `editor` and returns `true` to show the menu.                  |\n| `buttons`    | array    | Toolbar buttons with a `command`. Dropdowns with `items` are not supported. |\n\nThe editor hides bubble menus while the field is not editable, and while the cursor is in a table. When several menus match, only the first one shows. See [Load Order](#load-order).\n\n## Enable an Extension on a Field\n\nAn admin chooses which fields use an extension. Content in other fields is not affected.\n\n1. Open the settings of a field that uses the WYSIWYG interface.\n2. In **Extensions**, select your extension. This option shows only when at least one rich text extension is installed.\n3. In **Toolbar**, select your extension's buttons. The list shows them after you select the extension.\n4. Save the field.\n\nThe stored toolbar key of a contributed button is `\u003Cextension id>:\u003Cbutton key>`, for example `callout:callout`. A contributed key never replaces a core button.\n\nThe editor builds its schema when it opens. After you change a field's extensions, open the item again to use them.\n\n### Load Order\n\nDirectus sorts rich text extensions by `id`. This order is the same on every deployment. It sets:\n\n- Which extension wins when two use the same node or mark name.\n- The order in which the editor tries their `parseHTML` rules.\n- The order of contributed buttons in the toolbar, and which bubble menu shows when several match.\n\nContributed buttons go after the core buttons. When the toolbar is too narrow, they are the first to move into **Show More**.\n\n## Round-Trip Rule\n\nThe WYSIWYG interface stores HTML. When a field loads, the editor parses the stored HTML with each `parseHTML` rule. When it saves, it writes the HTML that `renderHTML` returns.\n\nEvery node and mark must be symmetric. `parseHTML` must read back exactly the markup that `renderHTML` writes. If not, the saved HTML differs from the loaded HTML, and every save of a field that uses the extension warns the user that saving alters the content.\n\n- Match each attribute and data attribute that `renderHTML` writes.\n- Raise the extension's `priority` when a core rule matches the same markup first. For example, the core `textStyle` mark claims any `span` with a `data-*` attribute, so the `richtext` template sets `priority: 200` on its mark.\n\nWhen the Data Studio loads, Directus checks each node and mark once and logs a console warning on a mismatch:\n\n```\nRichtext extension \"callout\": node \"callout\" does not survive a round trip. renderHTML writes \u003Cdiv data-callout=\"\">...\u003C\u002Fdiv>, which parses back as ...\n```\n\nThe check is best effort. It uses default attribute values only, and skips nodes that cannot stand alone, such as a list item. It does not detect a clash between two extensions. Test your extension by saving a field, and by opening the source code view and the comparison view.\n\n## Names and Validation\n\nDirectus validates each extension when the Data Studio loads. An extension that breaks a rule does not load, and the browser console shows the reason:\n\n```\nRichtext extension \"callout\" was not loaded: \"paragraph\" is a core node, mark or extension name\n```\n\nOther extensions and the editor keep working. An extension is rejected when:\n\n- Its `id` is not unique, or contains characters other than lowercase letters, digits, and hyphens.\n- A node, mark, or extension uses a core name, such as `paragraph`, `heading`, `bold`, `link`, `table`, or `image`.\n- A name starts with `customFormat_`. This prefix is reserved for the field's [custom formats](\u002Fguides\u002Fdata-model\u002Frich-text#custom-formats).\n- A name is already used by another rich text extension. The extension whose `id` sorts first keeps the name.\n- An attribute uses a name the core editor keeps on every element: `class`, `id`, `title`, `role`, `lang`, `dir`, `dataAttributes`, or `ariaAttributes`.\n- A button, menu item, or bubble menu key is not unique in its list.\n- It throws while Directus validates it or builds the editor schema with it.\n\n## Error Handling\n\nA failing extension fails alone.\n\n- If the extension's code throws while it loads, Directus skips it.\n- If a `command`, `isActive`, `isDisabled`, or `shouldShow` callback throws, the editor disables that button or menu until the editor closes. The console shows the error. The core buttons keep working.\n\n## Node Views\n\nA node can render with a Vue component in the editor. Use `VueNodeViewRenderer`, `NodeViewWrapper`, and `NodeViewContent` from the shared `@tiptap\u002Fvue-3` package.\n\n```js\nimport { Node } from '@tiptap\u002Fcore';\nimport { VueNodeViewRenderer } from '@tiptap\u002Fvue-3';\nimport CardView from '.\u002Fcard-view.vue';\n\nconst Card = Node.create({\n\tname: 'card',\n\tgroup: 'block',\n\tcontent: 'block+',\n\tparseHTML: () => [{ tag: 'div[data-card]' }],\n\trenderHTML: () => ['div', { 'data-card': '' }, 0],\n\taddNodeView: () => VueNodeViewRenderer(CardView),\n});\n```\n\nThe field saves the `renderHTML` output, not the markup of the node view. Controls you add in the node view are never stored.\n\nTo hide edit controls when the field is not editable, use `useRichTextEditable()`. Do not use `editor.isEditable`. It does not update when the field later becomes read-only, disabled, or locked.\n\n```vue\n\u003Ctemplate>\n\t\u003CNodeViewWrapper class=\"card\">\n\t\t\u003Cbutton v-if=\"editable\" type=\"button\" @click=\"deleteNode()\">Remove\u003C\u002Fbutton>\n\t\t\u003CNodeViewContent \u002F>\n\t\u003C\u002FNodeViewWrapper>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { useRichTextEditable } from '@directus\u002Fextensions-sdk';\nimport { NodeViewContent, NodeViewWrapper, nodeViewProps } from '@tiptap\u002Fvue-3';\n\nconst { deleteNode } = defineProps(nodeViewProps);\nconst editable = useRichTextEditable();\n\u003C\u002Fscript>\n```\n\n`useRichTextEditable()` returns a read-only ref. Outside the WYSIWYG interface, its value is always `true`.\n\n## Style Your Nodes\n\nImport a CSS file in your entrypoint. The extensions SDK bundles it and adds it to the page when the extension loads.\n\nScope every rule under the `.richtext-content` class. The editor root has this class in edit mode, in read-only mode, and in the comparison view.\n\n```css\n.richtext-content div[data-callout] {\n\tpadding: 12px 16px;\n\tborder-inline-start: 4px solid var(--theme--primary);\n\tbackground-color: var(--theme--primary-background);\n}\n```\n\nThe core editor styles use low specificity, so your rules override them. The comparison view's change highlights always stay visible.\n\nThese styles apply in the Data Studio only. Your frontend renders the stored HTML, so add matching styles there. See [Rich Text](\u002Fguides\u002Fdata-model\u002Frich-text) for how to style the editor output on your frontend.\n\n## Remove an Extension\n\nWhen an admin removes an extension from a field, or uninstalls it, the field's schema no longer contains its nodes and marks. Content that still uses them follows the same flow as other markup the editor does not support:\n\n1. The field opens read-only and shows a notice.\n2. The user selects the field and can view the changes as a diff.\n3. The user chooses **Keep Read-only**, **Edit Anyway**, or **Edit Raw HTML**.\n\n**Edit Anyway** removes the extension's markup when the user saves. **Edit Raw HTML** edits the stored HTML as text and keeps it. Enable the extension again to edit the content in the editor without losing markup.\n\n::callout{icon=\"i-lucide-triangle-alert\" color=\"warning\"}\nSaved content keeps the extension's markup until a user saves the field without it. If a user saves without it by mistake, restore the earlier version from **Revisions**.\n::\n\n## Wrap an Existing Tiptap Package\n\nYou can add a published Tiptap extension package to Directus.\n\n1. Install the package as a dependency of your extension. Use a version from the same Tiptap major as Directus.\n2. Add it to `extensions`, with `.configure()` for its options.\n3. Add buttons that run its commands.\n\n```js\nimport { defineRichText } from '@directus\u002Fextensions-sdk';\nimport Youtube from '@tiptap\u002Fextension-youtube';\n\nexport default defineRichText({\n\tid: 'youtube',\n\tname: 'YouTube',\n\textensions: [Youtube.extend({ priority: 1000 }).configure({ nocookie: true })],\n\tbuttons: [\n\t\t{\n\t\t\tkey: 'embed',\n\t\t\ticon: 'smart_display',\n\t\t\tlabel: 'Embed YouTube video',\n\t\t\tcommand: (editor) => {\n\t\t\t\tconst src = window.prompt('YouTube URL');\n\t\t\t\tif (src) editor.commands.setYoutubeVideo({ src });\n\t\t\t},\n\t\t},\n\t],\n});\n```\n\nThe extensions SDK bundles the package code but keeps its Tiptap and ProseMirror imports on the shared copy. Before you publish, check the package against the rules on this page:\n\n- If its name is a core name, rename it with `.extend({ name: '...' })`.\n- If a core rule claims its markup first, raise its `priority` with `.extend()`, as in the example. The core editor parses `iframe`, `video`, and `audio` elements as media.\n- Save a field that uses it, and check the console for a round-trip warning.\n\n## Tiptap Version Policy\n\nA rich text extension uses the copy of Tiptap that ships with the Data Studio. The extensions SDK does not bundle the shared Tiptap packages, so the editor and your extension use the same ProseMirror classes. ProseMirror checks objects by class, so objects from a second copy of ProseMirror fail these checks and the editor behaves incorrectly.\n\nThis makes the Tiptap version part of the extension API. A new Tiptap major version can break every installed rich text extension. Directus shares `vue`, `vue-router`, `vue-i18n`, and `pinia` with app extensions in the same way.\n\n### Shared Tiptap Packages\n\nImport the following packages directly in your extension. The extensions SDK marks them as external when it builds, so your bundle uses the Data Studio's copy and does not include them.\n\n- `@tiptap\u002Fcore`\n- `@tiptap\u002Fvue-3`\n- These `@tiptap\u002Fpm` subpaths: `commands`, `dropcursor`, `gapcursor`, `history`, `keymap`, `model`, `schema-list`, `state`, `tables`, `transform`, and `view`. For example, `@tiptap\u002Fpm\u002Fkeymap`.\n\nEach `@tiptap\u002Fpm` subpath re-exports one ProseMirror package. For example, `@tiptap\u002Fpm\u002Fkeymap` re-exports `prosemirror-keymap`. When your code or a package you install imports a ProseMirror package behind a shared subpath by its own name, the extensions SDK changes the import to that subpath. So you can install Tiptap packages that use ProseMirror, such as `@tiptap\u002Fextension-table`. The SDK bundles the code of the package itself, but it uses the Data Studio's copy of ProseMirror.\n\nThe Data Studio does not use `@tiptap\u002Fpm\u002Fchangeset` or `@tiptap\u002Fpm\u002Finputrules`, so the extensions SDK bundles them into your extension. This is safe. They do not contain ProseMirror classes or plugin keys that the editor checks, and their own ProseMirror imports go to the shared subpaths.\n\nIf you install other Tiptap packages, use a version from the same Tiptap major as Directus.\n\n### Version Guarantees\n\n| Directus | Tiptap |\n| -------- | ------ |\n| 12.x     | 3.x    |\n\n- Directus pins the Tiptap major version. Tiptap minor and patch updates can ship in any Directus release.\n- A new Tiptap major version ships only in a new Directus major version.\n- The [breaking changes](\u002Freleases\u002Fbreaking-changes) page for that Directus version lists the Tiptap upgrade.\n\n### Set the Host Range\n\nThe `host` field in your extension's `package.json` declares the Directus versions it supports. Set it to a caret range on the Directus version you build against.\n\n```json\n\"directus:extension\": {\n\t\"type\": \"richtext\",\n\t\"path\": \"dist\u002Findex.js\",\n\t\"source\": \"src\u002Findex.js\",\n\t\"host\": \"^12.6.0\"\n}\n```\n\nA caret range stops at the next major version. When a Directus major version upgrades Tiptap, your range no longer matches it.\n\nThe Marketplace compares `host` with the project's Directus version. When the range does not match, the extension's page shows **Compatibility not guaranteed**.\n\n::callout{icon=\"i-lucide-triangle-alert\" color=\"warning\"}\nDirectus does not check `host` when it loads an extension. An extension that you install manually loads on any version. Read the breaking changes before you upgrade a project that uses rich text extensions.\n::\n\n### Upgrade After a Tiptap Major Version\n\nWhen a Directus major version upgrades Tiptap, update your extension before your users upgrade.\n\n1. Read the breaking changes for the new Directus version and Tiptap's upgrade notes.\n2. Update the Tiptap APIs your extension uses.\n3. Build the extension and test it on the new Directus version.\n4. Set `host` to the new major version, for example `^13.0.0`.\n5. Publish the update as a new major version of your extension.\n\n## Next Steps\n\nRead about [publishing to the Marketplace](\u002Fguides\u002Fextensions\u002Fmarketplace\u002Fpublishing), the [WYSIWYG interface options](\u002Fguides\u002Fdata-model\u002Finterfaces#wysiwyg), and [custom formats](\u002Fguides\u002Fdata-model\u002Frich-text) for the editor.\n",{"title":2052,"description":1237},"c00df192-7fcb-457e-8fc8-fc05b853f88a","YZ6K7jQjv3lksXoszUo5mhpT3PQZ5cbJUhjjLnAjXbE",[4384,4385],{"title":1230,"path":1231,"stem":1232,"description":1233,"children":-1},{"title":1239,"path":1240,"stem":1241,"description":1242,"children":-1},{"id":4387,"title":65,"authors":14,"body":4388,"description":24,"extension":4376,"headline":14,"icon":14,"links":14,"meta":4404,"navigation":2270,"path":66,"rawbody":4405,"section":14,"seo":4406,"stableId":14,"stem":67,"technologies":14,"__hash__":4407},"content\u002F_partials\u002Fextensions-uid.md",{"type":2054,"value":4389,"toc":4402},[4390],[3759,4391,4393],{"icon":4392},"i-lucide-info",[2057,4394,4395,4398,4401],{},[2074,4396,4397],{},"Unique Identifiers",[4399,4400],"br",{},"\nThe extension id must not conflict with other extensions, so consider prefixing with author name.",{"title":24,"searchDepth":2135,"depth":2242,"links":4403},[],{},"::callout{icon=\"i-lucide-info\"}\n**Unique Identifiers**  \nThe extension id must not conflict with other extensions, so consider prefixing with author name.\n::\n",{"description":24},"YL1qnaRkwb4an_YG5CDkdWSms5DiP7P06LFqlbmaUak",{"id":4409,"title":52,"authors":14,"body":4410,"description":55,"extension":4376,"headline":14,"icon":14,"links":14,"meta":4425,"navigation":2270,"path":53,"rawbody":4426,"section":14,"seo":4427,"stableId":14,"stem":54,"technologies":14,"__hash__":4428},"content\u002F_partials\u002Fextensions-app.md",{"type":2054,"value":4411,"toc":4423},[4412],[2057,4413,4414,4415,4418,4419,4422],{},"This extension type is loaded into the Directus Data Studio. They are are built with Vue 3, and can use the provided ",[2061,4416,4417],{"href":1245},"composables"," exported by the ",[2097,4420,4421],{},"@directus\u002Fextensions-sdk"," package. Extensions can be written in JavaScript or TypeScript.",{"title":24,"searchDepth":2135,"depth":2242,"links":4424},[],{},"This extension type is loaded into the Directus Data Studio. They are are built with Vue 3, and can use the provided [composables](\u002Fguides\u002Fextensions\u002Fapp-extensions\u002Fcomposables) exported by the `@directus\u002Fextensions-sdk` package. Extensions can be written in JavaScript or TypeScript.\n",{"description":55},"78AWQgfDuOSIjLQBnjmGfxSml4RTfVecDsDE5Qlifqg",1792416569011]