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-right

Nuxt 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-right

SSR 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