Wprowadzenie

Integracja z modelem językowym ChatGPT może dodać nowoczesnego charakteru aplikacjom webowym. W tym poradniku pokażę, jak bezpiecznie zintegrować API OpenAI z aplikacją opartą o Nuxt 3, przy zachowaniu zasad ochrony klucza API.

Wszystkie zapytania będą realizowane przez backend Nuxt, dzięki czemu klucz API nie trafi do kodu frontendowego ani nie będzie widoczny w narzędziach developerskich przeglądarki.

Założenia

  • Korzystamy z Nuxt 3 (zainicjalizowanego przez npx nuxi init).
  • Masz już konto i klucz API OpenAI ze strony platform.openai.com .

Krok 1: Dodaj klucz API do .env

W pliku .env dodaj swój klucz:


OPENAI\_API\_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

W pliku nuxt.config.ts dodaj obsługę runtimeConfig:

export default defineNuxtConfig({
  runtimeConfig: {
    openaiApiKey: '', // domyślna wartość dla serwera
    public: {},       // nic nie udostępniamy frontendowi
  },
})

Krok 2: Stwórz API route – /server/api/chat.ts

Utwórz plik server/api/chat.ts, który będzie pośredniczył w zapytaniu do OpenAI:

export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig()
  const body = await readBody<{ prompt: string }>(event)

  if (!body.prompt) {
    return createError({ statusCode: 400, message: 'Prompt jest wymagany.' })
  }

  const response = await $fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${config.openaiApiKey}`,
      'Content-Type': 'application/json',
    },
    body: {
      model: 'gpt-3.5-turbo',
      messages: [{ role: 'user', content: body.prompt }],
    },
  })

  return response
})

Krok 3: Stwórz komponent frontendowy ChatBox.vue

<template>
  <div>
    <textarea v-model="prompt" placeholder="Zadaj pytanie..."></textarea>
    <button @click="sendPrompt" :disabled="loading">Wyślij</button>
    <p v-if="loading">Oczekiwanie na odpowiedź...</p>
    <p v-if="response">{{ response }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const prompt = ref('')
const response = ref('')
const loading = ref(false)

const sendPrompt = async () => {
  if (!prompt.value) return
  loading.value = true

  try {
    const res = await $fetch('/api/chat', {
      method: 'POST',
      body: { prompt: prompt.value },
    })
    response.value = res.choices?.[0]?.message?.content || 'Brak odpowiedzi.'
  } catch (e) {
    response.value = 'Wystąpił błąd.'
  } finally {
    loading.value = false
  }
}
</script>

<style scoped>
textarea {
  width: 100%;
  min-height: 80px;
  margin-bottom: 10px;
}
</style>

Krok 4: Uruchomienie aplikacji

Po uruchomieniu:

npm install
npm run dev

Aplikacja będzie gotowa do obsługi zapytań do ChatGPT, z zachowaniem klucza API tylko po stronie serwera.


Bezpieczeństwo i produkcja

  • Klucz nigdy nie trafia na frontend – API działa w warstwie serwerowej Nuxt.
  • Można dodatkowo ograniczyć prompt długością i filtrować dane wejściowe.
  • W środowisku produkcyjnym upewnij się, że .env jest poprawnie załadowany (np. przez dotenv lub usługę hostingową).

Podsumowanie

Dzięki możliwościom Nuxt 3 i server/api/, integracja z OpenAI staje się prosta i bezpieczna. To rozwiązanie, które można szybko wdrożyć, zachowując dobre praktyki i pełną kontrolę nad kosztami i bezpieczeństwem zapytań.

Jeśli potrzebujesz wersji rozszerzonej z historią rozmów, rolami, buforowaniem odpowiedzi czy limitem znaków – daj znać.