[{"data":1,"prerenderedAt":881},["ShallowReactive",2],{"navigation":3,"-blog-how-to-build-an-ai-chat":355,"$fSfqI7U3ONlViJxxu0LCJSTAsCIOHwP-GVZtZSGsZVII":859},[4],{"title":5,"path":6,"stem":7,"children":8,"page":354},"Docs","/docs","docs",[9,32],{"title":10,"path":11,"stem":12,"children":13,"category":16,"description":16,"icon":31},"Getting Started","/docs/getting-started","docs/1.getting-started/1.index",[14,19,25],{"title":15,"path":11,"stem":12,"category":16,"description":17,"icon":18},"Introduction",null,"Welcome to the sse-hooks documentation.","i-lucide-house",{"title":20,"path":21,"stem":22,"category":16,"description":23,"icon":24},"Installation","/docs/getting-started/installation","docs/1.getting-started/2.installation","Get started with sse-hooks in your React or Next.js project.","i-lucide-download",{"title":26,"path":27,"stem":28,"category":16,"description":29,"icon":30},"Usage","/docs/getting-started/usage","docs/1.getting-started/3.usage","Learn how to integrate and configure sse-hooks in your application.","i-lucide-sliders","i-lucide-square-play",{"title":33,"category":16,"description":16,"icon":34,"path":35,"stem":36,"children":37,"page":354},"Hooks","i-lucide-square-function","/docs/hooks","docs/2.hooks",[38,44,50,56,62,68,73,78,84,89,94,99,105,110,116,121,126,131,136,141,146,153,158,163,168,174,179,184,189,194,199,204,209,214,219,224,229,234,239,244,249,254,259,264,269,274,279,284,289,294,299,304,309,314,319,324,329,334,339,344,349],{"title":39,"path":40,"stem":41,"category":42,"description":43},"useAudioRecorder","/docs/hooks/use-audio-recorder","docs/2.hooks/1.use-audio-recorder","sensors","A comprehensive hook for audio recording with real-time analysis using getUserMedia, MediaRecorder, and Web Audio APIs",{"title":45,"path":46,"stem":47,"category":48,"description":49},"useCopyToClipboard","/docs/hooks/use-copy-to-clipboard","docs/2.hooks/10.use-copy-to-clipboard","utilities","Custom hook that copies text to the clipboard using the `Clipboard API`.",{"title":51,"path":52,"stem":53,"category":54,"description":55},"useCountdown","/docs/hooks/use-countdown","docs/2.hooks/11.use-countdown","effect","Custom hook that manages countdown.",{"title":57,"path":58,"stem":59,"category":60,"description":61},"useCounter","/docs/hooks/use-counter","docs/2.hooks/12.use-counter","state","Custom hook that manages a counter with increment, decrement, reset, and setCount functionalities.",{"title":63,"path":64,"stem":65,"category":66,"description":67},"useDarkMode","/docs/hooks/use-dark-mode","docs/2.hooks/13.use-dark-mode","dom","Custom hook that returns the current state of the dark mode.",{"title":69,"path":70,"stem":71,"category":54,"description":72},"useDebounceCallback","/docs/hooks/use-debounce-callback","docs/2.hooks/14.use-debounce-callback","Custom hook that creates a debounced version of a callback function.",{"title":74,"path":75,"stem":76,"category":54,"description":77},"useDebounceValue","/docs/hooks/use-debounce-value","docs/2.hooks/15.use-debounce-value","Custom hook that returns a debounced version of the provided value, along with a function to update it.",{"title":79,"path":80,"stem":81,"category":54,"description":82,"badge":83},"useDeepCompareEffect","/docs/hooks/use-deep-compare-effect","docs/2.hooks/16.use-deep-compare-effect","Custom hook that serves as a drop-in replacement for `useEffect`, but uses deep comparison on its dependencies instead of reference equality.","NEW",{"title":85,"path":86,"stem":87,"category":66,"description":88},"useDocumentTitle","/docs/hooks/use-document-title","docs/2.hooks/17.use-document-title","Custom hook that sets the document title.",{"title":90,"path":91,"stem":92,"category":48,"description":93},"useEventCallback","/docs/hooks/use-event-callback","docs/2.hooks/18.use-event-callback","Custom hook that creates a memoized event callback.",{"title":95,"path":96,"stem":97,"category":54,"description":98},"useEventListener","/docs/hooks/use-event-listener","docs/2.hooks/19.use-event-listener","Custom hook that attaches event listeners to DOM elements, the window, or media query lists.",{"title":100,"path":101,"stem":102,"category":103,"description":104},"useAutoSave","/docs/hooks/use-auto-save","docs/2.hooks/2.use-auto-save","storage","A robust hook for auto-saving form data with debouncing, race-condition handling, and lifecycle safety.\nIt monitors the `data` state and triggers the `onSave` callback after a specified `delay` of inactivity. It also provides a smart `onChange` handler that adapts to both React Events and direct values.",{"title":106,"path":107,"stem":108,"category":66,"description":109},"useFavicon","/docs/hooks/use-favicon","docs/2.hooks/20.use-favicon","Custom hook that sets the document favicon.",{"title":111,"path":112,"stem":113,"category":114,"description":115},"useFetch","/docs/hooks/use-fetch","docs/2.hooks/21.use-fetch","network","Custom hook that provides a wrapper around the native `fetch API` to handle HTTP requests with state management, abort capability, and TypeScript support.",{"title":117,"path":118,"stem":119,"category":66,"description":120,"badge":83},"useFocus","/docs/hooks/use-focus","docs/2.hooks/22.use-focus","Custom hook that tracks the focus state of a DOM element.",{"title":122,"path":123,"stem":124,"category":66,"description":125},"useForkRef","/docs/hooks/use-fork-ref","docs/2.hooks/23.use-fork-ref","Merges refs into a single memoized callback ref or `null`.",{"title":127,"path":128,"stem":129,"category":42,"description":130,"badge":83},"useGeolocation","/docs/hooks/use-geolocation","docs/2.hooks/24.use-geolocation","Custom hook that tracks the user's geographic location using the Geolocation API.",{"title":132,"path":133,"stem":134,"category":60,"description":135,"badge":83},"useHistoryState","/docs/hooks/use-history-state","docs/2.hooks/25.use-history-state","Custom hook for managing state history, providing undo, redo, and clear functionality.",{"title":137,"path":138,"stem":139,"category":42,"description":140},"useHover","/docs/hooks/use-hover","docs/2.hooks/26.use-hover","Custom hook that tracks whether a DOM element is being hovered over.",{"title":142,"path":143,"stem":144,"category":42,"description":145,"badge":83},"useIdle","/docs/hooks/use-idle","docs/2.hooks/27.use-idle","Custom hook that tracks whether the user is idle based on activity events.",{"title":147,"path":148,"stem":149,"children":150,"category":103,"description":152},"useIndexedDB","/docs/hooks/use-indexed-db","docs/2.hooks/28.use-indexed-db",[151],{"title":147,"path":148,"stem":149,"category":103,"description":152},"Custom hook that provides an interface to the `IndexedDB API` for client-side storage of significant amounts of structured data.",{"title":154,"path":155,"stem":156,"category":66,"description":157},"useIntersectionObserver","/docs/hooks/use-intersection-observer","docs/2.hooks/29.use-intersection-observer","Custom hook that tracks the intersection of a DOM element with its containing element or the viewport using the `Intersection Observer API`.",{"title":159,"path":160,"stem":161,"category":60,"description":162},"useBoolean","/docs/hooks/use-boolean","docs/2.hooks/3.use-boolean","Custom hook that handles boolean state with useful utility functions.",{"title":164,"path":165,"stem":166,"category":54,"description":167},"useInterval","/docs/hooks/use-interval","docs/2.hooks/30.use-interval","Custom hook that creates an interval that invokes a callback function at a specified delay using the `setInterval API`.",{"title":169,"path":170,"stem":171,"category":172,"description":173},"useIsClient","/docs/hooks/use-is-client","docs/2.hooks/31.use-is-client","lifecycle","Custom hook that determines if the code is running on the client side (in the browser).",{"title":175,"path":176,"stem":177,"category":172,"description":178},"useIsMounted","/docs/hooks/use-is-mounted","docs/2.hooks/32.use-is-mounted","Custom hook that determines if the component is currently mounted.",{"title":180,"path":181,"stem":182,"category":48,"description":183,"badge":83},"useKbd","/docs/hooks/use-kbd","docs/2.hooks/33.use-kbd","Custom hook that detects the operating system (Mac vs. Windows/Linux) and provides a normalized map of keyboard keys (e.g., mapping \"Meta\" to \"Command\" on Mac and \"Ctrl\" on Windows).",{"title":185,"path":186,"stem":187,"category":42,"description":188},"useKey","/docs/hooks/use-key","docs/2.hooks/34.use-key","A powerful sensor hook for handling keyboard shortcuts, sequences, and modifiers.\nIt supports complex key combinations (`Ctrl+Shift+S`), Gmail-style sequences (`g then i`), and provides metadata for generating \"Keyboard Shortcut\" UI help modals.",{"title":190,"path":191,"stem":192,"category":103,"description":193},"useLocalStorage","/docs/hooks/use-local-storage","docs/2.hooks/35.use-local-storage","Custom hook that uses the `localStorage API` to persist state across page reloads.",{"title":195,"path":196,"stem":197,"category":60,"description":198},"useMap","/docs/hooks/use-map","docs/2.hooks/36.use-map","Custom hook that manages a key-value `Map` state with setter actions.",{"title":200,"path":201,"stem":202,"category":48,"description":203},"useMediaQuality","/docs/hooks/use-media-quality","docs/2.hooks/37.use-media-quality","Custom hook to manage video stream quality by applying constraints (resolution and frame rate) to a MediaStream track.",{"title":205,"path":206,"stem":207,"category":42,"description":208},"useMediaQuery","/docs/hooks/use-media-query","docs/2.hooks/38.use-media-query","Custom hook that tracks the state of a media query using the `Match Media API`.",{"title":210,"path":211,"stem":212,"category":42,"description":213},"useMediaSession","/docs/hooks/use-media-session","docs/2.hooks/39.use-media-session","Custom hook that interacts with the Media Session API. It allows you to customize media notifications and handle media control events (like play, pause, next track) from the system's notification area or lock screen.",{"title":215,"path":216,"stem":217,"category":42,"description":218},"BreakPointHooks","/docs/hooks/use-breakpoint","docs/2.hooks/4.use-breakpoint","Reactive hooks and utilities to be used with user provided breakpoints.",{"title":220,"path":221,"stem":222,"category":48,"description":223},"useMemoizedFn","/docs/hooks/use-memoized-fn","docs/2.hooks/40.use-memoized-fn","A hook that returns a memoized version of a function. Unlike `useCallback`, the function identity remains stable across re-renders, but it always has access to the latest props and state without needing a dependency array. This is particularly useful for passing callbacks to optimized child components to prevent unnecessary re-renders while avoiding closure staleness.",{"title":225,"path":226,"stem":227,"category":114,"description":228},"useNetworkInformation","/docs/hooks/use-network-information","docs/2.hooks/41.use-network-information","Custom hook that tracks the device's network connection status and details (speed, type) using the Network Information API.",{"title":230,"path":231,"stem":232,"category":66,"description":233},"usePortal","/docs/hooks/use-portal","docs/2.hooks/42.use-portal","Custom hook to manage the creation and state of DOM Portals. Handles mounting, unmounting, outside clicks, and \"Escape\" key closure.",{"title":235,"path":236,"stem":237,"category":103,"description":238},"useReadLocalStorage","/docs/hooks/use-read-local-storage","docs/2.hooks/43.use-read-local-storage","Custom hook that reads a value from `localStorage`, closely related to `useLocalStorage()`.",{"title":240,"path":241,"stem":242,"category":42,"description":243},"useResizeObserver","/docs/hooks/use-resize-observer","docs/2.hooks/44.use-resize-observer","Custom hook that observes the size of an element using the `ResizeObserver API`.",{"title":245,"path":246,"stem":247,"category":60,"description":248},"useRoleGuard","/docs/hooks/use-role-guard","docs/2.hooks/45.use-role-guard","Custom hook for Role-Based Access Control (RBAC). Checks if a user has specific permissions and handles redirection for unauthorized access.",{"title":250,"path":251,"stem":252,"category":42,"description":253},"useScreen","/docs/hooks/use-screen","docs/2.hooks/46.use-screen","Custom hook that tracks the `screen` dimensions and properties.",{"title":255,"path":256,"stem":257,"category":42,"description":258},"useScreenShare","/docs/hooks/use-screen-share","docs/2.hooks/47.use-screen-share","Custom hook that captures the user's screen or specific application window. It handles permission errors, stream management, native stop events, and cleanup.",{"title":260,"path":261,"stem":262,"category":66,"description":263},"useScript","/docs/hooks/use-script","docs/2.hooks/48.use-script","Custom hook that dynamically loads scripts and tracking their loading status.",{"title":265,"path":266,"stem":267,"category":66,"description":268},"useScrollLock","/docs/hooks/use-scroll-lock","docs/2.hooks/49.use-scroll-lock","A custom hook that locks and unlocks scroll.",{"title":270,"path":271,"stem":272,"category":48,"description":273},"useCallbackRef","/docs/hooks/use-callback-ref","docs/2.hooks/5.use-callback-ref","A custom hook that converts a callback to a ref to avoid triggering re-renders when passed as a prop or avoid re-executing effects when passed as a dependency",{"title":275,"path":276,"stem":277,"category":48,"description":278},"useSearchWithSuggestions","/docs/hooks/use-search-with-suggestions","docs/2.hooks/50.use-search-with-suggestions","A comprehensive hook for building \"Command Palette\" or \"Omnibar\" style search interfaces. * It provides \"Ghost Text\" autocomplete (like Google search), command scoping (like Slack's `/` commands), and keyboard support. It handles the complex logic of parsing input strings to separate commands from queries.",{"title":280,"path":281,"stem":282,"category":103,"description":283},"useSessionStorage","/docs/hooks/use-session-storage","docs/2.hooks/51.use-session-storage","Custom hook that uses the `sessionStorage API` to persist state across page reloads.",{"title":285,"path":286,"stem":287,"category":48,"description":288},"useSSR","/docs/hooks/use-ssr","docs/2.hooks/52.use-ssr","Custom hook that detects the current environment (Browser, Server, or Native) and capability support (Workers, EventListeners). useful for avoiding hydration mismatches.",{"title":290,"path":291,"stem":292,"category":60,"description":293},"useStep","/docs/hooks/use-step","docs/2.hooks/53.use-step","Custom hook that manages and navigates between steps in a multi-step process.",{"title":295,"path":296,"stem":297,"category":48,"description":298,"badge":83},"useSupported","/docs/hooks/use-supported","docs/2.hooks/54.use-supported","Custom hook that safely checks if a specific feature or browser API is supported.",{"title":300,"path":301,"stem":302,"category":48,"description":303},"useSymbol","/docs/hooks/use-symbol","docs/2.hooks/55.use-symbol","Custom hook for managing ES6 Symbols. Provides utilities to create unique symbols, manage a registry of symbols, and access well-known symbols.",{"title":305,"path":306,"stem":307,"category":66,"description":308},"useTernaryDarkMode","/docs/hooks/use-ternary-dark-mode","docs/2.hooks/56.use-ternary-dark-mode","Custom hook that manages ternary (system, dark, light) dark mode with local storage support.",{"title":310,"path":311,"stem":312,"category":54,"description":313},"useTimeout","/docs/hooks/use-timeout","docs/2.hooks/57.use-timeout","Custom hook that handles timeouts in React components using the `setTimeout API`.",{"title":315,"path":316,"stem":317,"category":60,"description":318},"useToggle","/docs/hooks/use-toggle","docs/2.hooks/58.use-toggle","Custom hook that manages a boolean toggle state in React components.",{"title":320,"path":321,"stem":322,"category":172,"description":323},"useUnmount","/docs/hooks/use-unmount","docs/2.hooks/59.use-unmount","Custom hook that runs a cleanup function when the component is unmounted.",{"title":325,"path":326,"stem":327,"category":66,"description":328},"useClickAnyWhere","/docs/hooks/use-click-any-where","docs/2.hooks/6.use-click-any-where","Custom hook that handles click events anywhere on the document.",{"title":330,"path":331,"stem":332,"category":42,"description":333},"useUserMedia","/docs/hooks/use-user-media","docs/2.hooks/60.use-user-media","Custom hook that captures audio and video from the user's device. It handles permission errors, stream management, and cleanup automatically.",{"title":335,"path":336,"stem":337,"category":42,"description":338},"useWindowSize","/docs/hooks/use-window-size","docs/2.hooks/61.use-window-size","Custom hook that tracks the size of the window.",{"title":340,"path":341,"stem":342,"category":66,"description":343},"useClickAway","/docs/hooks/use-click-away","docs/2.hooks/7.use-click-away","Custom hook that triggers a callback when a user clicks outside the referenced element. It handles portal elements, scrollbar clicks, and touch interactions intelligently.",{"title":345,"path":346,"stem":347,"category":42,"description":348},"useConferenceSystem","/docs/hooks/use-conference-system","docs/2.hooks/8.use-conference-system","A comprehensive hook for managing video conferencing state, including camera access, screen sharing, network monitoring, and automatic media quality adjustment.",{"title":350,"path":351,"stem":352,"category":103,"description":353},"useCookie","/docs/hooks/use-cookie","docs/2.hooks/9.use-cookie","Custom hook that manages state synchronized with a browser `cookie`. It handles serialization, prefixes, updates across tabs, and custom event synchronization.",false,{"id":356,"title":357,"authors":358,"body":369,"date":849,"description":850,"extension":851,"image":852,"meta":853,"navigation":354,"path":855,"seo":856,"stem":857,"__hash__":858},"posts/blog/how-to-build-an-ai-chat.md","Build an AI Chatbot with Nuxt, Nuxt UI, and AI SDK",[359,364],{"name":360,"avatar":361,"to":363},"Hugo Richard",{"src":362},"https://github.com/hugorcd.png","https://x.com/hugorcd",{"name":365,"avatar":366,"to":368},"Benjamin Canac",{"src":367},"https://github.com/benjamincanac.png","https://x.com/benjamincanac",{"type":370,"value":371,"toc":841},"minimark",[372,376,381,384,419,445,449,452,466,470,473,510,515,518,671,675,682,837],[373,374,375],"p",{},"Building AI-powered applications has never been more accessible. This guide walks through creating a full-featured AI chatbot using Nuxt, Nuxt UI, and the Vercel AI SDK. Each step is explained in detail so you understand how every piece works together.",[377,378,380],"h2",{"id":379},"what-were-building","What we're building",[373,382,383],{},"By the end of this tutorial, you'll have a fully functional AI chatbot with:",[385,386,387,395,401,407,413],"ul",{},[388,389,390,394],"li",{},[391,392,393],"strong",{},"Streaming responses"," that appear in real-time as the AI generates them",[388,396,397,400],{},[391,398,399],{},"A beautiful chat interface"," built with Nuxt UI's purpose-built chat components",[388,402,403,406],{},[391,404,405],{},"Markdown rendering"," for rich AI responses with code highlighting",[388,408,409,412],{},[391,410,411],{},"Multi-model support"," allowing users to switch between OpenAI, Anthropic, and Google models",[388,414,415,418],{},[391,416,417],{},"Server-side AI integration"," using Nitro API routes and the AI SDK",[420,421,423],"callout",{"icon":422},"i-simple-icons-github",[373,424,425,426,436,437,444],{},"Check out the ",[427,428,432],"a",{"href":429,"rel":430},"https://github.com/nuxt-ui-templates/chat",[431],"nofollow",[433,434,435],"code",{},"Nuxt"," and ",[427,438,441],{"href":439,"rel":440},"https://github.com/nuxt-ui-templates/chat-vue",[431],[433,442,443],{},"Vue"," AI Chat templates on GitHub for production-ready implementations with authentication, database persistence, and more.",[377,446,448],{"id":447},"prerequisites","Prerequisites",[373,450,451],{},"Before we start, make sure you have:",[385,453,454,457],{},[388,455,456],{},"Node.js 20+ installed",[388,458,459,460,465],{},"A ",[427,461,464],{"href":462,"rel":463},"https://vercel.com/docs/ai-gateway",[431],"Vercel AI Gateway"," API key (provides access to multiple AI providers through a single endpoint)",[377,467,469],{"id":468},"project-setup","Project setup",[373,471,472],{},"Start by creating a new Nuxt project:",[474,475,480],"pre",{"className":476,"code":477,"language":478,"meta":479,"style":479},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npx nuxi@latest init nuxt-ai-chat\ncd nuxt-ai-chat\n","bash","",[433,481,482,501],{"__ignoreMap":479},[483,484,487,491,495,498],"span",{"class":485,"line":486},"line",1,[483,488,490],{"class":489},"sBMFI","npx",[483,492,494],{"class":493},"sfazB"," nuxi@latest",[483,496,497],{"class":493}," init",[483,499,500],{"class":493}," nuxt-ai-chat\n",[483,502,504,508],{"class":485,"line":503},2,[483,505,507],{"class":506},"s2Zo4","cd",[483,509,500],{"class":493},[511,512,514],"h3",{"id":513},"installing-dependencies","Installing dependencies",[373,516,517],{},"Install Nuxt UI and the AI-specific dependencies:",[519,520,522,568,602,637],"code-group",{"sync":521},"pm",[474,523,526],{"className":476,"code":524,"filename":525,"language":478,"meta":479,"style":479},"pnpm add @nuxt/ui tailwindcss @comark/nuxt @shikijs/langs @nuxthub/core drizzle-orm drizzle-kit @libsql/client ai @ai-sdk/vue zod\n","pnpm",[433,527,528],{"__ignoreMap":479},[483,529,530,532,535,538,541,544,547,550,553,556,559,562,565],{"class":485,"line":486},[483,531,525],{"class":489},[483,533,534],{"class":493}," add",[483,536,537],{"class":493}," @nuxt/ui",[483,539,540],{"class":493}," tailwindcss",[483,542,543],{"class":493}," @comark/nuxt",[483,545,546],{"class":493}," @shikijs/langs",[483,548,549],{"class":493}," @nuxthub/core",[483,551,552],{"class":493}," drizzle-orm",[483,554,555],{"class":493}," drizzle-kit",[483,557,558],{"class":493}," @libsql/client",[483,560,561],{"class":493}," ai",[483,563,564],{"class":493}," @ai-sdk/vue",[483,566,567],{"class":493}," zod\n",[474,569,572],{"className":476,"code":570,"filename":571,"language":478,"meta":479,"style":479},"yarn add @nuxt/ui tailwindcss @comark/nuxt @shikijs/langs @nuxthub/core drizzle-orm drizzle-kit @libsql/client ai @ai-sdk/vue zod\n","yarn",[433,573,574],{"__ignoreMap":479},[483,575,576,578,580,582,584,586,588,590,592,594,596,598,600],{"class":485,"line":486},[483,577,571],{"class":489},[483,579,534],{"class":493},[483,581,537],{"class":493},[483,583,540],{"class":493},[483,585,543],{"class":493},[483,587,546],{"class":493},[483,589,549],{"class":493},[483,591,552],{"class":493},[483,593,555],{"class":493},[483,595,558],{"class":493},[483,597,561],{"class":493},[483,599,564],{"class":493},[483,601,567],{"class":493},[474,603,606],{"className":476,"code":604,"filename":605,"language":478,"meta":479,"style":479},"npm install @nuxt/ui tailwindcss @comark/nuxt @shikijs/langs @nuxthub/core drizzle-orm drizzle-kit @libsql/client ai @ai-sdk/vue zod\n","npm",[433,607,608],{"__ignoreMap":479},[483,609,610,612,615,617,619,621,623,625,627,629,631,633,635],{"class":485,"line":486},[483,611,605],{"class":489},[483,613,614],{"class":493}," install",[483,616,537],{"class":493},[483,618,540],{"class":493},[483,620,543],{"class":493},[483,622,546],{"class":493},[483,624,549],{"class":493},[483,626,552],{"class":493},[483,628,555],{"class":493},[483,630,558],{"class":493},[483,632,561],{"class":493},[483,634,564],{"class":493},[483,636,567],{"class":493},[474,638,641],{"className":476,"code":639,"filename":640,"language":478,"meta":479,"style":479},"bun add @nuxt/ui tailwindcss @comark/nuxt @shikijs/langs @nuxthub/core drizzle-orm drizzle-kit @libsql/client ai @ai-sdk/vue zod\n","bun",[433,642,643],{"__ignoreMap":479},[483,644,645,647,649,651,653,655,657,659,661,663,665,667,669],{"class":485,"line":486},[483,646,640],{"class":489},[483,648,534],{"class":493},[483,650,537],{"class":493},[483,652,540],{"class":493},[483,654,543],{"class":493},[483,656,546],{"class":493},[483,658,549],{"class":493},[483,660,552],{"class":493},[483,662,555],{"class":493},[483,664,558],{"class":493},[483,666,561],{"class":493},[483,668,564],{"class":493},[483,670,567],{"class":493},[511,672,674],{"id":673},"configuration","Configuration",[373,676,677,678,681],{},"Update your ",[433,679,680],{},"nuxt.config.ts"," to register the modules:",[683,684,685],"code-tree-intersection",{},[474,686,690],{"className":687,"code":688,"filename":680,"language":689,"meta":479,"style":479},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: [\"@nuxt/ui\", \"@comark/nuxt\", \"@nuxthub/core\"],\n\n  hub: {\n    db: \"sqlite\",\n  },\n\n  css: [\"~/assets/css/main.css\"],\n});\n","ts",[433,691,692,712,758,765,776,793,799,804,825],{"__ignoreMap":479},[483,693,694,698,701,704,708],{"class":485,"line":486},[483,695,697],{"class":696},"s7zQu","export",[483,699,700],{"class":696}," default",[483,702,703],{"class":506}," defineNuxtConfig",[483,705,707],{"class":706},"sTEyZ","(",[483,709,711],{"class":710},"sMK4o","{\n",[483,713,714,718,721,724,727,730,732,735,738,741,743,745,747,750,752,755],{"class":485,"line":503},[483,715,717],{"class":716},"swJcz","  modules",[483,719,720],{"class":710},":",[483,722,723],{"class":706}," [",[483,725,726],{"class":710},"\"",[483,728,729],{"class":493},"@nuxt/ui",[483,731,726],{"class":710},[483,733,734],{"class":710},",",[483,736,737],{"class":710}," \"",[483,739,740],{"class":493},"@comark/nuxt",[483,742,726],{"class":710},[483,744,734],{"class":710},[483,746,737],{"class":710},[483,748,749],{"class":493},"@nuxthub/core",[483,751,726],{"class":710},[483,753,754],{"class":706},"]",[483,756,757],{"class":710},",\n",[483,759,761],{"class":485,"line":760},3,[483,762,764],{"emptyLinePlaceholder":763},true,"\n",[483,766,768,771,773],{"class":485,"line":767},4,[483,769,770],{"class":716},"  hub",[483,772,720],{"class":710},[483,774,775],{"class":710}," {\n",[483,777,779,782,784,786,789,791],{"class":485,"line":778},5,[483,780,781],{"class":716},"    db",[483,783,720],{"class":710},[483,785,737],{"class":710},[483,787,788],{"class":493},"sqlite",[483,790,726],{"class":710},[483,792,757],{"class":710},[483,794,796],{"class":485,"line":795},6,[483,797,798],{"class":710},"  },\n",[483,800,802],{"class":485,"line":801},7,[483,803,764],{"emptyLinePlaceholder":763},[483,805,807,810,812,814,816,819,821,823],{"class":485,"line":806},8,[483,808,809],{"class":716},"  css",[483,811,720],{"class":710},[483,813,723],{"class":706},[483,815,726],{"class":710},[483,817,818],{"class":493},"~/assets/css/main.css",[483,820,726],{"class":710},[483,822,754],{"class":706},[483,824,757],{"class":710},[483,826,828,831,834],{"class":485,"line":827},9,[483,829,830],{"class":710},"}",[483,832,833],{"class":706},")",[483,835,836],{"class":710},";\n",[838,839,840],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":479,"searchDepth":486,"depth":503,"links":842},[843,844,845],{"id":379,"depth":503,"text":380},{"id":447,"depth":503,"text":448},{"id":468,"depth":503,"text":469,"children":846},[847,848],{"id":513,"depth":760,"text":514},{"id":673,"depth":760,"text":674},"2025-12-16T10:00:00.000Z","Learn how to build a full-featured AI chatbot with streaming responses, multiple models support, and a beautiful UI using Nuxt, Nuxt UI, and Vercel AI SDK.","md","/assets/blog/building-nuxt-ai-chatbot.png",{"category":854},"Tutorial","/blog/how-to-build-an-ai-chat",{"title":357,"description":850},"blog/how-to-build-an-ai-chat","kY-VNK9PPm_z-5KqsPWO7madrV-Z8FJ3o11E3EMCu5s",{"team":860,"latest_release":872},[861,867],{"name":862,"login":863,"avatarUrl":479,"pronouns":479,"location":864,"websiteUrl":16,"sponsorsListing":865,"socialAccounts":866},"SSE World","sseworld","India","https://github.com/sponsors/sseworld",{},{"name":868,"login":869,"avatarUrl":479,"pronouns":479,"location":864,"websiteUrl":16,"sponsorsListing":870,"socialAccounts":871},"SSE Official","ssewofficial","https://github.com/sponsors/ssewofficial",{},{"tag":873,"name":873,"created_at":874,"updated_at":875,"published_at":876,"assets":877,"tarball_url":878,"zipball_url":879,"body":880},"v1.4.0","2026-02-18T09:08:57Z","2026-02-21T07:10:12Z","2026-02-18T09:18:00Z",[],"https://api.github.com/repos/sseuniverse/sse-hooks/tarball/v1.4.0","https://api.github.com/repos/sseuniverse/sse-hooks/zipball/v1.4.0","This release marks a major milestone in the development of the @sse-ui ecosystem. We have completely overhauled how hook metadata and types are generated, providing a much richer experience for developers and a more maintainable codebase for contributors.\r\n\r\n## 💎 Key Highlights\r\n\r\n* **Intelligent Type Generation**: The generate-nuxt-types.js engine has been rebuilt to track type usage. It now intelligently inlines simple type aliases (like AudioMimeType) into schemas while preserving complex standalone interfaces (like AudioAnalysisData) for better visibility.\r\n* **Cleaner Metadata**: We’ve implemented redundancy filtering. Top-level Options and Return interfaces are now automatically omitted from the types array to avoid clutter, as they are already fully described in the props and returns schemas.\r\n* **Refactored Documentation Engine**: generate-doc.js has been updated to handle the new metadata format, including improved descriptions, links, and schema visualization. We have also deprecated the old generate-md.js script in favor of this unified approach.\r\n* **Framework Integration**: Added @ssets/scule and @vueuse/nuxt to our dependency stack to enhance camelCase conversion and framework-specific utility support.\r\n\r\n## 🛠️ Internal Refactors\r\n* **Standalone Types Support**: Added a dedicated types array to hook definitions to accommodate standalone interfaces, enums, and complex aliases.\r\n* **TypeDoc Integration**: Enhanced the extraction of metadata from TypeDoc JSON to ensure better handling of optional flags and default values.\r\n* **Hook Cleanup**: Removed unused interfaces and legacy types from useFetch, useIndexedDB, useMediaSession, and useUserMedia to streamline the library footprint.\r\n\r\n## 📦 Versioning & Dependencies\r\n* Bumped sse-hooks-directory to 1.4.0.\r\n* Added support for TypeMeta in schema definitions for more robust type management.\r\n\r\n---\r\n\r\n**Full Changelog**: https://github.com/sseuniverse/sse-hooks/compare/v1.3.1...v1.4.0",1777352840908]