React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.
There is nothing to install from npm. @commentify/core, @commentify/react, and @commentify/vue travel inside usamamuneerchaudhary/commentify-pro, so one license covers PHP and JavaScript.
Your package manager links them into node_modules. Ordinary bare imports resolve in Vite, tsc, and test runners. No bundler alias.
Adds Tailwind v4 @source '../js/vendor/commentify'; so utility classes in the compiled SDK are not purged.
Scaffolds resources/js/components/CommentThread.tsx or .vueoutside vendor. That file is yours; the installer will not overwrite it unless you pass --force.
Treat resources/js/vendor/commentify as vendor code. The installer overwrites it on every run.
Do not add @commentify/* to optimizeDeps.include. That also silences React Refresh issues, but Vite keys the pre-bundle cache on the lockfile, not on a linked package’s contents. After every vendor:publish the browser keeps running a version you no longer have on disk. If you already hit this: remove the include, delete node_modules/.vite, restart Vite.
The SDK is symlinked from resources/js/vendor, which is inside your project, so Vite treats pre-built library code as source and may inject React Refresh into it. Exclude it in vite.config.js:
In the Blade layout that loads the React entry, @viteReactRefreshmust appear before @vite(...). Without it, dev throws @vitejs/plugin-react can't detect preamble. Often pointed at a vendor file, not the missing directive. Inertia starter kits already include it in app.blade.php.Vue needs no exclusion: the SDK ships compiled, so @vitejs/plugin-vue has nothing to transform.
The SDK declares react / react-dom or vue as peers. npm installs missing peers automatically; pnpm and yarn do not. The installer prints a follow-up if they are missing from package.json.
Class strings live once in @commentify/core. MarkupParityTest.php compares them to core Blade views. React and Vue render tests assert the components emit those same classes. ResourceParityTest.php does the same for avatars, relative timestamps, mention HTML, and report state.That is why you should keep using <CommentThread /> from the package rather than copying markup into the app. Blade and JS stay in step as Commentify updates.
Last modified on November 1, 2026
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Commentify Pro","description":"Self-hosted comments for Laravel. JSON API, React and Vue SDKs, reviews and Q\u0026A, BYO-key AI, spam pipeline, Filament moderation, and the same Livewire UI.","colors":{"primary":"#EC3013","light":"#FF6A52","dark":"#EC3013"},"logo":{"light":"https://mintcdn.com/commentify/O63iJiVjr-DWhaIG/logo/commentify-pro-lockup.png?fit=max\u0026auto=format\u0026n=O63iJiVjr-DWhaIG\u0026q=85\u0026s=e6d287c1a094e92bf096365289389212","dark":"https://mintcdn.com/commentify/O63iJiVjr-DWhaIG/logo/commentify-pro-lockup-dark.png?fit=max\u0026auto=format\u0026n=O63iJiVjr-DWhaIG\u0026q=85\u0026s=4de7e002f975e1c3afa74795abf07702"},"favicon":"https://mintcdn.com/commentify/O63iJiVjr-DWhaIG/favicon.svg?fit=max\u0026auto=format\u0026n=O63iJiVjr-DWhaIG\u0026q=85\u0026s=e20039356d7a3ed3c5be095304bbf85c","navbar":{"links":[{"href":"mailto:hello@usamamuneer.me","label":"Support"},{"icon":"play","href":"https://commentify.pro","label":"Demo"}],"primary":{"type":"button","label":"Purchase","href":"https://checkout.anystack.sh/commentify-pro"}},"footer":{"socials":{"website":"https://commentify.pro","github":"https://github.com/usamamuneerchaudhary/commentify"}},"search":{"prompt":"Search Commentify docs…"},"seo":{"metatags":{"og:site_name":"Commentify Pro Docs","twitter:card":"summary_large_image","og:image":"https://docs.commentify.pro/images/github-social-card.png","twitter:image":"https://docs.commentify.pro/images/github-social-card.png","keywords":"Laravel comments package, Commentify Pro, Laravel Livewire comments, Laravel comment API, Disqus alternative Laravel, Filament comment moderation, Laravel React comments, Laravel Vue comments, self-hosted comments Laravel, import Disqus comments Laravel"},"indexing":"navigable"},"integrations":{"ga4":{"measurementId":"G-GRSVJTPRSB"}},"banner":{"content":"Commentify Pro adds the API, React, Vue, and moderation. [Try the demo](https://commentify.pro) or [buy a license](https://checkout.anystack.sh/commentify-pro).","dismissible":true},"contextual":{"options":["copy","view","chatgpt","claude","perplexity","mcp","cursor","vscode"],"display":"header"},"metadata":{"timestamp":true},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"commentify","hasAudioNarration":false,"actualSubdomain":"commentify","customDomains":["docs.commentify.pro"],"gitSource":{"type":"github","owner":"usamamuneerchaudhary","repo":"docs-commentify-pro","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{},"buildId":"6ae69088ee23c3f33b1cb17c","clientVersion":"0.0.4087","searchFilterCounts":[{"language":"default","tag":"Commentify","count":11},{"language":"default","tag":"Features","count":9},{"language":"default","tag":"Frontends","count":6},{"language":"default","tag":"Commentify Pro","count":4},{"language":"default","tag":"API","count":2},{"language":"default","tag":"Moderation","count":2},{"language":"default","tag":"Help","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"#assistant-entry,#assistant-entry-mobile,.chat-assistant-floating-input,#chat-assistant-sheet{display:none!important}"}],"page":{"pagePath":"javascript","slug":"/javascript","pageMetadata":{"title":"How the JavaScript ships","description":"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.","href":"/javascript"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={code:`code`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,..._provideComponents(),...props.components},{CodeBlock,Heading,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`There is nothing to install from npm. `,_jsx(_components.code,{children:`@commentify/core`}),`, `,_jsx(_components.code,{children:`@commentify/react`}),`, and `,_jsx(_components.code,{children:`@commentify/vue`}),` travel inside `,_jsx(_components.code,{children:`usamamuneerchaudhary/commentify-pro`}),`, so one license covers PHP and JavaScript.`]}),`\n`,_jsx(Heading,{level:`2`,id:`what-the-installer-does`,children:`What the installer does`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[`Copies the `,_jsx(_components.strong,{children:`built`}),` packages from the Composer package’s `,_jsx(_components.code,{children:`resources/js/ship/`}),` into `,_jsx(_components.code,{children:`resources/js/vendor/commentify/{core,react,vue}`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Adds local paths to `,_jsx(_components.code,{children:`package.json`}),`:`]}),`\n`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`4`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`4`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"dependencies\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"@commentify/core\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"file:resources/js/vendor/commentify/core\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"@commentify/react\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"file:resources/js/vendor/commentify/react\"`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Your package manager links them into `,_jsx(_components.code,{children:`node_modules`}),`. Ordinary bare imports resolve in Vite, `,_jsx(_components.code,{children:`tsc`}),`, and test runners. No bundler alias.`]}),`\n`,_jsxs(_components.ol,{start:`3`,children:[`\n`,_jsxs(_components.li,{children:[`Adds Tailwind v4 `,_jsx(_components.code,{children:`@source '../js/vendor/commentify';`}),` so utility classes in the compiled SDK are not purged.`]}),`\n`,_jsxs(_components.li,{children:[`Scaffolds `,_jsx(_components.code,{children:`resources/js/components/CommentThread.tsx`}),` or `,_jsx(_components.code,{children:`.vue`}),` `,_jsx(_components.strong,{children:`outside`}),` vendor. That file is yours; the installer will not overwrite it unless you pass `,_jsx(_components.code,{children:`--force`}),`.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Treat `,_jsx(_components.code,{children:`resources/js/vendor/commentify`}),` as vendor code. The installer overwrites it on every run.`]}),`\n`,_jsxs(Heading,{level:`2`,id:`refresh-after-composer-update`,children:[`Refresh after `,_jsx(_components.code,{children:`composer update`})]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`php`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` artisan`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` vendor:publish`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --tag=commentify-pro-js`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` --force`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`tailwind`,children:`Tailwind`}),`\n`,_jsx(_components.p,{children:`Without scanning the SDK, the thread renders with no styling. If the installer could not patch CSS:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`css`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`css`,children:_jsxs(_components.code,{language:`css`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`@import`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"tailwindcss\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`@source`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` '../js/vendor/commentify';`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`vite-pitfalls`,children:`Vite pitfalls`}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Do `,_jsx(_components.strong,{children:`not`}),` add `,_jsx(_components.code,{children:`@commentify/*`}),` to `,_jsx(_components.code,{children:`optimizeDeps.include`}),`. That also silences React Refresh issues, but Vite keys the pre-bundle cache on the lockfile, not on a linked package’s contents. After every `,_jsx(_components.code,{children:`vendor:publish`}),` the browser keeps running a version you no longer have on disk. If you already hit this: remove the include, delete `,_jsx(_components.code,{children:`node_modules/.vite`}),`, restart Vite.`]})}),`\n`,_jsx(Heading,{level:`3`,id:`react-refresh`,children:`React Refresh`}),`\n`,_jsxs(_components.p,{children:[`The SDK is symlinked from `,_jsx(_components.code,{children:`resources/js/vendor`}),`, which is inside your project, so Vite treats pre-built library code as source and may inject React Refresh into it. Exclude it in `,_jsx(_components.code,{children:`vite.config.js`}),`:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`javascript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`javascript`,children:_jsxs(_components.code,{language:`javascript`,numberOfLines:`8`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`import`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` react`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` from`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` '@vitejs/plugin-react'`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`export`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` default`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` defineConfig`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#D4D4D4`},children:`({`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` plugins:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` laravel`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({ `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`/* … */`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }),`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` react`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({ `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`exclude:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#D16969`},children:`/resources`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-light-font-weight\":`bold`,\"--shiki-dark\":`#D7BA7D`,\"--shiki-dark-font-weight\":`inherit`},children:`\\\\/`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#D16969`},children:`js`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-light-font-weight\":`bold`,\"--shiki-dark\":`#D7BA7D`,\"--shiki-dark-font-weight\":`inherit`},children:`\\\\/`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#D16969`},children:`vendor`}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-light-font-weight\":`bold`,\"--shiki-dark\":`#D7BA7D`,\"--shiki-dark-font-weight\":`inherit`},children:`\\\\/`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#D16969`},children:`commentify/`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] }),`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#D4D4D4`},children:`})`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`In the Blade layout that loads the React entry, `,_jsx(_components.code,{children:`@viteReactRefresh`}),` `,_jsx(_components.strong,{children:`must`}),` appear before `,_jsx(_components.code,{children:`@vite(...)`}),`. Without it, dev throws `,_jsx(_components.code,{children:`@vitejs/plugin-react can't detect preamble`}),`. Often pointed at a vendor file, not the missing directive. Inertia starter kits already include it in `,_jsx(_components.code,{children:`app.blade.php`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Vue needs no exclusion: the SDK ships compiled, so `,_jsx(_components.code,{children:`@vitejs/plugin-vue`}),` has nothing to transform.`]}),`\n`,_jsx(Heading,{level:`2`,id:`peer-dependencies`,children:`Peer dependencies`}),`\n`,_jsxs(_components.p,{children:[`The SDK declares `,_jsx(_components.code,{children:`react`}),` / `,_jsx(_components.code,{children:`react-dom`}),` or `,_jsx(_components.code,{children:`vue`}),` as peers. npm installs missing peers automatically; pnpm and yarn do not. The installer prints a follow-up if they are missing from `,_jsx(_components.code,{children:`package.json`}),`.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`5`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` react`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` react-dom`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -D`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` @vitejs/plugin-react`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` vue`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` install`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:` -D`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` @vitejs/plugin-vue`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`one-ui-three-stacks`,children:`One UI, three stacks`}),`\n`,_jsxs(_components.p,{children:[`Class strings live once in `,_jsx(_components.code,{children:`@commentify/core`}),`. `,_jsx(_components.code,{children:`MarkupParityTest.php`}),` compares them to core Blade views. React and Vue render tests assert the components emit those same classes. `,_jsx(_components.code,{children:`ResourceParityTest.php`}),` does the same for avatars, relative timestamps, mention HTML, and report state.`]}),`\n`,_jsxs(_components.p,{children:[`That is why you should keep using `,_jsx(_components.code,{children:`\u003cCommentThread />`}),` from the package rather than copying markup into the app. Blade and JS stay in step as Commentify updates.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"How the JavaScript ships","description":"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.","href":"/javascript"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"What the installer does","slug":"what-the-installer-does","depth":2,"children":[]},{"title":"Refresh after composer update","slug":"refresh-after-composer-update","depth":2,"children":[]},{"title":"Tailwind","slug":"tailwind","depth":2,"children":[]},{"title":"Vite pitfalls","slug":"vite-pitfalls","depth":2,"children":[{"title":"React Refresh","slug":"react-refresh","depth":3,"children":[]}]},{"title":"Peer dependencies","slug":"peer-dependencies","depth":2,"children":[]},{"title":"One UI, three stacks","slug":"one-ui-three-stacks","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"commentify","siteName":"Commentify Pro","title":"How the JavaScript ships - Commentify Pro","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-01T00:02:22.468Z","gitLastModified":"2026-11-01T00:02:15.000Z","originalFileLocation":"javascript.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.\">\u003cmeta data-mint-head name=\"keywords\" content=\"Laravel comments package, Commentify Pro, Laravel Livewire comments, Laravel comment API, Disqus alternative Laravel, Filament comment moderation, Laravel React comments, Laravel Vue comments, self-hosted comments Laravel, import Disqus comments Laravel\">\u003cmeta data-mint-head name=\"application-name\" content=\"Commentify Pro\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"How the JavaScript ships - Commentify Pro\">\u003cmeta data-mint-head property=\"og:description\" content=\"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Commentify Pro Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.commentify.pro/javascript\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://docs.commentify.pro/images/github-social-card.png\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"How the JavaScript ships - Commentify Pro\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://docs.commentify.pro/images/github-social-card.png\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/commentify/EDJI4D5MmY9jtmId/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Commentify Pro\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#EC3013\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.commentify.pro/javascript\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/javascript.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.commentify.pro/#organization\",\"name\":\"Commentify Pro\",\"url\":\"https://docs.commentify.pro\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/commentify/O63iJiVjr-DWhaIG/logo/commentify-pro-lockup.png?fit=max\u0026auto=format\u0026n=O63iJiVjr-DWhaIG\u0026q=85\u0026s=e6d287c1a094e92bf096365289389212\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.commentify.pro#website\",\"name\":\"Commentify Pro\",\"url\":\"https://docs.commentify.pro\",\"publisher\":{\"@id\":\"https://docs.commentify.pro/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.commentify.pro/javascript#webpage\",\"url\":\"https://docs.commentify.pro/javascript\",\"name\":\"How the JavaScript ships\",\"description\":\"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.\",\"dateModified\":\"2026-11-01T00:02:15.000Z\",\"isPartOf\":{\"@id\":\"https://docs.commentify.pro#website\"},\"breadcrumb\":{\"@id\":\"https://docs.commentify.pro/javascript#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.commentify.pro/javascript#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Frontends\",\"item\":\"https://docs.commentify.pro/livewire\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How the JavaScript ships\",\"item\":\"https://docs.commentify.pro/javascript\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.commentify.pro/javascript#article\",\"headline\":\"How the JavaScript ships\",\"name\":\"How the JavaScript ships\",\"description\":\"React and Vue SDKs live inside the Composer package. Publish to resources/js/vendor/commentify and link them as file: dependencies.\",\"url\":\"https://docs.commentify.pro/javascript\",\"mainEntityOfPage\":{\"@id\":\"https://docs.commentify.pro/javascript#webpage\"},\"image\":\"https://docs.commentify.pro/images/github-social-card.png\",\"dateModified\":\"2026-11-01T00:02:15.000Z\",\"publisher\":{\"@id\":\"https://docs.commentify.pro/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.commentify.pro#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Commentify Pro\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Commentify Pro","nav":{"global":null,"pages":[{"group":"Commentify","expanded":true,"pages":[{"title":"Commentify Pro","href":"/index"},{"title":"Install Commentify","href":"/installation"},{"title":"Make a model commentable","href":"/usage"},{"title":"Threads","href":"/threads"},{"title":"Configuration","href":"/configuration"},{"title":"Guest commenting","href":"/guests"},{"title":"Customization","href":"/customization"},{"title":"Authorization","href":"/authorization"},{"title":"Email notifications and subscriptions","href":"/notifications"},{"title":"Filament","href":"/filament"},{"title":"Upgrade Commentify","href":"/upgrading-core"}]},{"group":"Commentify Pro","tag":"Pro","pages":[{"title":"Install Commentify Pro","href":"/quickstart"},{"title":"Licensing","href":"/licensing"},{"title":"Upgrade to Commentify Pro","href":"/upgrading"},{"title":"Commentify Pro","href":"/readme"}]},{"group":"Frontends","tag":"Pro","pages":[{"title":"Livewire","description":"Drop the comments component on any commentable model. Pro registers its own component and Blade overrides.","href":"/livewire"},{"title":"How the JavaScript ships","href":"/javascript"},{"title":"React","description":"Mount @commentify/react in Blade or Inertia. Same thread as Livewire, including markdown, reports, and dark mode.","href":"/react"},{"title":"Vue","href":"/vue"},{"title":"Hook reference","href":"/hooks"},{"title":"Bring your own markup","href":"/headless"}]},{"group":"API","tag":"Pro","pages":[{"title":"JSON API","href":"/api"},{"title":"Authentication","href":"/authentication"}]},{"group":"Moderation","tag":"Pro","pages":[{"title":"Spam pipeline","href":"/spam"},{"title":"Moderator webhooks","href":"/webhooks"}]},{"group":"Features","tag":"Pro","pages":[{"title":"Thread modes","href":"/modes"},{"title":"Bring-your-own-key AI","href":"/ai"},{"title":"Image uploads","href":"/media"},{"title":"Realtime threads","href":"/realtime"},{"title":"Badges and pinned comments","href":"/badges"},{"title":"Reactions","href":"/reactions"},{"title":"AI toxicity scoring","href":"/toxicity"},{"title":"Import Disqus and WordPress","href":"/import"},{"title":"GDPR","href":"/gdpr"}]},{"group":"Help","pages":[{"title":"Troubleshooting","href":"/troubleshooting"}]}]},"basePath":"","title":"How the JavaScript ships - Commentify Pro","buildId":"dpl_FWZhTb2vab28gFGFH4ojka6qEznQ","deploymentId":"dpl_FWZhTb2vab28gFGFH4ojka6qEznQ","dynamics":["10e4515597"],"chunks":["BannerMarkdown-C79IUEr8.js","dist-DE3EVdvd.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","clsx-DK3K4Z1S.js","html-void-elements-mCSPHezU.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js"]}