Nuxt.js Integration
Integrate BotHarbor chat widget into your Nuxt.js applications with support for both Nuxt 2 and Nuxt 3.
Nuxt 3 Integration
For Nuxt 3 applications using the modern composition API and auto-imports.
Plugin Setup
// plugins/botharbor.client.ts
export default defineNuxtPlugin(() => {
// Only run on client side
if (process.server) return
const config = useRuntimeConfig()
const loadBotHarbor = () => {
return new Promise((resolve, reject) => {
if (window.BotHarbor) {
resolve(window.BotHarbor)
return
}
const script = document.createElement('script')
script.src = 'https://botharbor.ai/embed.js'
script.async = true
script.onload = () => resolve(window.BotHarbor)
script.onerror = reject
document.head.appendChild(script)
})
}
const initializeBotHarbor = async () => {
try {
const BotHarbor = await loadBotHarbor()
BotHarbor.init({
botId: config.public.botharborBotId,
theme: 'light',
position: 'bottom-right',
onReady: () => {
console.log('BotHarbor is ready')
}
})
} catch (error) {
console.error('Failed to load BotHarbor:', error)
}
}
// Initialize when the plugin loads
initializeBotHarbor()
})Composable Approach
// composables/useBotHarbor.ts
export const useBotHarbor = () => {
const isReady = ref(false)
const isOpen = ref(false)
const config = useRuntimeConfig()
const loadScript = () => {
return new Promise((resolve, reject) => {
if (window.BotHarbor) {
resolve(window.BotHarbor)
return
}
const script = document.createElement('script')
script.src = 'https://botharbor.ai/embed.js'
script.async = true
script.onload = () => resolve(window.BotHarbor)
script.onerror = () => reject(new Error('Failed to load BotHarbor script'))
document.head.appendChild(script)
})
}
const initialize = async () => {
if (process.server) return
try {
const BotHarbor = await loadScript()
BotHarbor.init({
botId: config.public.botharborBotId,
theme: 'light',
position: 'bottom-right',
onReady: () => {
isReady.value = true
},
onOpen: () => {
isOpen.value = true
},
onClose: () => {
isOpen.value = false
}
})
} catch (error) {
console.error('BotHarbor initialization failed:', error)
}
}
const open = () => {
if (window.BotHarbor && isReady.value) {
window.BotHarbor.open()
}
}
const close = () => {
if (window.BotHarbor) {
window.BotHarbor.close()
}
}
onMounted(() => {
initialize()
})
return {
isReady: readonly(isReady),
isOpen: readonly(isOpen),
open,
close
}
}Using in Components
<template>
<div>
<h1>My Nuxt 3 App</h1>
<button @click="open" :disabled="!isReady" class="btn">
{{ isReady ? 'Open Chat' : 'Loading...' }}
</button>
<p>Chat is {{ isOpen ? 'open' : 'closed' }}</p>
</div>
</template>
<script setup>
const { isReady, isOpen, open, close } = useBotHarbor()
</script>Nuxt 2 Integration
For Nuxt 2 applications using the traditional plugin system.
Plugin Setup
// plugins/botharbor.client.js
export default ({ $config }, inject) => {
// Only run on client side
if (process.server) return
const loadBotHarbor = () => {
return new Promise((resolve, reject) => {
if (window.BotHarbor) {
resolve(window.BotHarbor)
return
}
const script = document.createElement('script')
script.src = 'https://botharbor.ai/embed.js'
script.async = true
script.onload = () => resolve(window.BotHarbor)
script.onerror = reject
document.head.appendChild(script)
})
}
const botHarbor = {
async init() {
try {
const BotHarbor = await loadBotHarbor()
BotHarbor.init({
botId: $config.botharborBotId,
theme: 'light',
position: 'bottom-right',
onReady: () => {
console.log('BotHarbor is ready')
}
})
} catch (error) {
console.error('Failed to load BotHarbor:', error)
}
},
open() {
if (window.BotHarbor) {
window.BotHarbor.open()
}
},
close() {
if (window.BotHarbor) {
window.BotHarbor.close()
}
}
}
inject('botHarbor', botHarbor)
}Nuxt Config
// nuxt.config.js
export default {
plugins: [
{ src: '~/plugins/botharbor.client.js', mode: 'client' }
],
publicRuntimeConfig: {
botharborBotId: process.env.BOTHARBOR_BOT_ID
},
privateRuntimeConfig: {
// Private keys (only available on server-side)
}
}Using in Pages/Components
<template>
<div>
<h1>My Nuxt 2 App</h1>
<button @click="openChat" class="btn">
Open Chat
</button>
</div>
</template>
<script>
export default {
async mounted() {
// Initialize BotHarbor when component mounts
await this.$botHarbor.init()
},
methods: {
openChat() {
this.$botHarbor.open()
},
closeChat() {
this.$botHarbor.close()
}
}
}
</script>Environment Configuration
Configure your Nuxt application with environment variables.
Nuxt 3 Configuration
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
// Private keys (only available on server-side)
apiSecret: '123',
// Public keys (exposed to client-side)
public: {
botharborBotId: process.env.BOTHARBOR_BOT_ID,
botharborTheme: process.env.BOTHARBOR_THEME || 'light',
botharborPosition: process.env.BOTHARBOR_POSITION || 'bottom-right'
}
}
})
// .env
BOTHARBOR_BOT_ID=your-bot-id-here
BOTHARBOR_THEME=light
BOTHARBOR_POSITION=bottom-rightNuxt 2 Configuration
// nuxt.config.js
export default {
publicRuntimeConfig: {
botharborBotId: process.env.BOTHARBOR_BOT_ID,
botharborTheme: process.env.BOTHARBOR_THEME || 'light',
botharborPosition: process.env.BOTHARBOR_POSITION || 'bottom-right'
}
}
// .env
BOTHARBOR_BOT_ID=your-bot-id-here
BOTHARBOR_THEME=light
BOTHARBOR_POSITION=bottom-rightSSR Considerations
Handle server-side rendering properly to avoid hydration issues.
Client-Only Components
<template>
<div>
<h1>My Page</h1>
<client-only>
<BotHarborWidget />
<template #fallback>
<div>Loading chat widget...</div>
</template>
</client-only>
</div>
</template>
<script>
import BotHarborWidget from '~/components/BotHarborWidget.vue'
export default {
components: {
BotHarborWidget
}
}
</script>Process Check
// Always check for client-side before accessing window
if (process.client) {
// Client-side only code
window.BotHarbor.open()
}
// Or use mounted/onMounted lifecycle hooks
mounted() {
// This only runs on client-side
this.initializeBotHarbor()
}Best Practices
Nuxt-Specific Tips
- ✓Use client-only plugins for browser-specific code
- ✓Leverage Nuxt's runtime config for environment variables
- ✓Use process.client checks for client-side only code
- ✓Wrap widgets in client-only components for SSR
