Skip to main content
📝 AI-tools

Ik Bouwde een Premium AI-App Met Gemini Embeddings en RAG

Bouw een premium AI-app met Gemini-embeddings en RAG. Verwerkt PDF s met diagrammen, multimodale content en echt documentbegrip.

24 min

Leestijd

4,693

Woorden

Mar 21, 2026

Gepubliceerd

Engr Mejba Ahmed

Geschreven door

Engr Mejba Ahmed

Artikel delen

Ik Bouwde een Premium AI-App Met Gemini Embeddings en RAG

Ik Bouwde een Premium AI-App Met Gemini Embeddings en RAG

De PDF bevatte diagrammen. Geen tekstbeschrijvingen van diagrammen -- echte flowcharts, architectuurvisualisaties, geannoteerde screenshots. Elk embedding-model dat ik eerder had getest, zou ze volledig hebben genegeerd en alleen de omringende tekst hebben geïndexeerd, terwijl de visuele informatie verloren ging. Dus toen ik diezelfde PDF uploadde naar een Pinecone-index met Google's Gemini Embedding 2-model en een vraag stelde over een specifiek diagram drie pagina's diep, verwachtte ik de gebruikelijke gehallucineerde onzin.

In plaats daarvan haalde het precies de juiste context uit het diagram. Het verwees naar de pijlen. Het begreep de flow.

Ik leunde achterover en staarde een volle tien seconden naar mijn terminal. Dat was het moment waarop ik wist dat deze build anders zou worden dan elke RAG-app die ik eerder had opgeleverd. Niet stapsgewijs beter. Fundamenteel anders -- omdat het embedding-model eindelijk meer begreep dan alleen woorden.

Wat volgde was een vijfstappenproces om een premium, mobiel-responsieve AI-applicatie te bouwen met dynamische chat, kennisophaling met geheugen en multi-format content-inname. Het soort app dat je aan een klant kunt overhandigen en waar je echt geld voor kunt vragen. Ik ga elke stap doorlopen, inclusief de delen waar dingen kapotgingen en de beslissingen die ik de volgende keer anders zou nemen.

Maar eerst moet je begrijpen waarom Gemini Embedding 2 de rekensom verandert van wat mogelijk is met RAG -- en waarom het bouwen van dit soort apps vóór maart 2026 oprecht pijnlijk was.

Waarom Gemini Embedding 2 het RAG-Speelboek Herschrijft

RAG -- Retrieval Augmented Generation -- is het werkpaard-patroon geweest om AI-apps geheugen te geven. Het concept is eenvoudig: in plaats van een volledige kennisbank in een prompt te proppen (duur, traag en beperkt door contextvensters), verdeel je documenten in stukken, converteer je die stukken naar numerieke vectoren, sla je ze op in een vectordatabase en haal je alleen de relevante delen op wanneer een gebruiker een vraag stelt. De AI krijgt precies de context die het nodig heeft zonder alles te verwerken.

Het probleem zat altijd in de embedding-stap. Vóór Gemini Embedding 2 waren embedding-modellen alleen geschikt voor tekst. OpenAI's text-embedding-3-large, de modellen van Cohere, zelfs Google's eigen text-embedding-004 -- ze verwerkten allemaal woorden en negeerden al het andere. Als je kennisbank afbeeldingen, architectuurdiagrammen, video-walkthroughs of audio-opnames bevatte, had je twee opties: alles handmatig omzetten naar tekst (waarbij nuance en visuele context verloren gingen), of accepteren dat je RAG-systeem blind was voor de helft van je data.

Gemini Embedding 2 ging op 10 maart 2026 in public preview en elimineerde die afweging volledig. Gebouwd op de Gemini-architectuur mapt het tekst, afbeeldingen, video, audio en PDF's naar één enkele 3.072-dimensionale vectorruimte. Eén model. Eén embedding-ruimte. Alles samen doorzoekbaar.

De benchmarks bevestigen dit. Op MTEB English scoort het 68,32 -- de eerste plek met een marge van 5,09 punten boven de eerstvolgende concurrent. Maar benchmarks bouwen geen apps. Wat ertoe doet, is wat er gebeurt wanneer je er een producthandleiding van 40 pagina's met screenshots aan voert, het aan Pinecone koppelt en een gebruikersvraag stelt. Daar begint de echte test.

Zo ziet een multimodale RAG-pipeline eruit vergeleken met de oude tekst-only-aanpak:

Mogelijkheid Tekst-Only Embeddings Gemini Embedding 2
Tekstdocumenten Ja Ja
PDF met afbeeldingen/diagrammen Alleen tekst -- afbeeldingen genegeerd Volledig multimodaal begrip
Video-content Vereist eerst transcriptie-extractie Directe video-embedding
Audiobestanden Vereist speech-to-text voorverwerking Directe audio-embedding
Cross-modale zoekopdrachten Niet mogelijk Tekstquery haalt relevante afbeeldingen, audio en video op
Embedding-dimensies Varieert (1.536 - 3.072) 3.072 (uniforme ruimte)
Ondersteunde talen Modelafhankelijk 100+ talen standaard

Die rij met cross-modale zoekopdrachten is degene die alles verandert. Een tekstquery zoals "laat me de authenticatieflow zien" kan nu een diagram, een video-tijdstip of een codefragment ophalen -- wat het meest relevant is -- vanuit één uniforme index. Geen aparte pipelines. Geen resultaten van verschillende embedding-modellen aan elkaar plakken.

De techstack waar ik op uitkwam voor deze build vertelt het verhaal van hoe deze onderdelen in elkaar passen. En de volgorde doet ertoe -- elke toolkeuze beperkte de volgende op manieren die ik pas volledig begreep toen ik diep in de implementatie zat.

Het Vijfstappenraamwerk: Van Leeg Scherm tot Uitgerolde SaaS

Ik heb een framework aangepast van Jack Roberts dat AI-app-ontwikkeling opdeelt in vijf afzonderlijke fasen. Niet omdat ik dol ben op frameworks -- ik heb er te veel gezien die proces toevoegen zonder waarde toe te voegen -- maar omdat dit framework netjes aansluit bij de daadwerkelijke beslissingen waar je voor komt te staan. Elke stap levert een oplevering op die de volgende voedt.

Dit is de stack voordat we beginnen met bouwen:

Component Tool Waarom Deze
UI-ontwerp & Prototyping Lovable Genereert productiekwaliteit React + Tailwind vanuit natuurlijke taal, wordt geleverd met Supabase-integratie
Code-integratie & Debugging Anti-Gravity IDE + Claude Code Agent-first IDE met Claude Code's terminalniveau bestandstoegang voor API-koppelingen
Vectordatabase Pinecone Standaardondersteuning voor 3.072-dimensie vectoren, serverless schaling, metadata-filtering
Embedding-model Gemini Embedding 2 Multimodale embeddings voor tekst, afbeeldingen, video, audio en documenten
Automatisering & Planning Railway Cron jobs voor geautomatiseerde kennisinname, prijzen op basis van gebruik vanaf $5/maand
Gebruikersdata & Auth Supabase Postgres-gebaseerde auth, real-time abonnementen, row-level security
Testen Test UI (voorheen LambdaTest) + Kane AI Cross-browser geautomatiseerd testen met AI-gestuurde gebruikersflowsimulatie
Deployment Vercel Git-gekoppelde deploys, edge functions, aangepaste domeinen

Laat me nu elke stap doorlopen zoals het werkelijk is gegaan -- niet de opgepoetste versie, de echte.

Stap 1: Fundament en Architectuur -- De UI Bouwen Met Lovable

Ik begon met Lovable omdat ik de ontwerpkwaliteit vooraan wilde plaatsen. De meeste AI-app-tutorials produceren apps die eruitzien alsof ze om 2 uur 's nachts door een backend-engineer zijn gebouwd -- functioneel maar visueel pijnlijk. Voor een klantgericht SaaS-product moet de UI vanaf de eerste interactie premium aanvoelen.

Lovable genereert full-stack applicaties vanuit natuurlijke taal-prompts. Je beschrijft wat je wilt en het produceert React-componenten met Tailwind CSS, gekoppeld aan een Supabase-backend. De gratis laag geeft je 5 berichten per dag (maximaal 30 per maand), wat krap is maar werkbaar voor een eerste build. Het Starter-plan voor $25/maand met 100 credits is waar de meeste serieuze bouwers terechtkomen.

Mijn eerste prompt was specifiek -- niet "bouw me een chat-app" maar een gedetailleerde beschrijving van de dashboard-layout, inclusief een inlogscherm met geanimeerde overgangen, een hoofdchatinterface voor het bevragen van de kennisbank en een Kanban-achtige notitiessectie voor het opslaan en ordenen van inzichten. Ik specificeerde ondersteuning voor lichte en donkere modus, confetti-effecten bij de eerste login en specifieke kleurcontrasten voor toegankelijkheid.

De eerste generatie leverde me ruwweg 80% van wat ik wilde. De chatinterface was strak. Het Kanban-bord werkte. De loginflow had soepele overgangen. Maar de spacing klopte niet op mobiel, de donkere modus had contrastproblemen bij twee componenten en de confetti-animatie ging af bij elke paginalading in plaats van alleen bij de eerste login.

Dit heb ik geleerd over effectief prompten in Lovable: behandel elke verfijning als een gerichte instructie, niet als een herontwerpverzoek. In plaats van "repareer de mobiele layout" zei ik "verminder de padding van de chatberichtencontainer van 24px naar 16px op schermen onder 640px en stapel de Kanban-kolommen verticaal op mobiel met 12px tussenruimte." Specifieke prompts produceren specifieke fixes. Vage prompts produceren nieuwe problemen.

Na vier iteratierondes -- elk gericht op één enkel probleem -- had ik een UI die ik oprecht aan een klant zou laten zien. De export naar GitHub was één klik. Op dat moment was de visuele laag klaar en had ik geen code-editor aangeraakt.

Maar een mooie UI zonder brein erachter is slechts een mockup. De volgende stap -- het koppelen van Gemini embeddings en Pinecone aan de backend -- is waar deze build interessant wordt. En waar dingen begonnen te breken.

Stap 2: Embeddings Koppelen en het Kennisbrein Bouwen

Dit is de stap die een demo van een product scheidt. Ik kloonde de door Lovable gegenereerde repo vanuit GitHub naar Anti-Gravity IDE, de agent-first ontwikkelomgeving van Google die is gebouwd op het werk van het voormalige Windsurf-team. Anti-Gravity onderhoudt zestien gespecialiseerde agents -- frontend-specialisten, backend-architecten, security-auditors -- maar degene die hier belangrijk is, is Claude Code, die in de geïntegreerde terminal draait met volledige bestandssysteemtoegang.

Waarom Claude Code binnen Anti-Gravity in plaats van gewoon Claude Code standalone? Twee redenen. Ten eerste laat Anti-Gravity's ingebouwde browser je wijzigingen visueel in real-time verifiëren zonder van venster te wisselen. Ten tweede betekent het agent-skillsysteem dat Claude Code de backend-koppeling afhandelt terwijl Anti-Gravity's frontend-agent visuele regressies opvangt. Ze vullen elkaar aan in plaats van werk te dupliceren.

De eerste taak: Pinecone koppelen als vectordatabase. Pinecone's serverless laag ondersteunt de 3.072 dimensies die Gemini Embedding 2 produceert, en hun metadata-filtering laat je queries beperken tot specifieke documenttypen of uploaddatums -- cruciaal voor een kennisbank die in de loop van de tijd groeit.

Ik gaf Claude Code de opdracht om de Pinecone-client op te zetten, een index te maken met de juiste dimensies en cosinus-similariteitsmetriek, en deze te koppelen aan een API-route in de Next.js-app. De code die het genereerde, werkte bij de eerste poging. Dit is de kern van de embedding- en upsert-flow:

// lib/embeddings.ts
import { GoogleGenerativeAI } from "@google/generative-ai";
import { Pinecone } from "@pinecone-database/pinecone";

const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
const pinecone = new Pinecone({ apiKey: process.env.PINECONE_API_KEY! });

// Gemini Embedding 2 model - supports text, images, video, audio, PDFs
const embeddingModel = genAI.getGenerativeModel({
  model: "gemini-embedding-exp-03-07"
});

export async function embedAndStore(
  content: string,
  metadata: Record<string, any>,
  namespace: string = "default"
) {
  const index = pinecone.index(process.env.PINECONE_INDEX!);

  // Generate embedding - 3,072 dimensions
  const result = await embeddingModel.embedContent(content);
  const embedding = result.embedding.values;

  // Upsert to Pinecone with metadata for filtering
  await index.namespace(namespace).upsert([{
    id: `doc_${Date.now()}_${Math.random().toString(36).slice(2)}`,
    values: embedding,
    metadata: {
      ...metadata,
      timestamp: new Date().toISOString(),
      contentPreview: content.slice(0, 200)
    }
  }]);
}

export async function queryKnowledge(
  query: string,
  topK: number = 5,
  filter?: Record<string, any>
) {
  const index = pinecone.index(process.env.PINECONE_INDEX!);

  const queryEmbedding = await embeddingModel.embedContent(query);

  const results = await index.namespace("default").query({
    vector: queryEmbedding.embedding.values,
    topK,
    includeMetadata: true,
    filter
  });

  return results.matches?.map(match => ({
    score: match.score,
    content: match.metadata?.contentPreview,
    source: match.metadata?.source,
    type: match.metadata?.contentType
  }));
}

De chunkingstrategie is belangrijker dan de meeste tutorials erkennen. Ik splitste documenten in chunks van 512 tokens met 50 tokens overlap. Te klein en je verliest context. Te groot en je verspilt tokens aan irrelevante content tijdens het ophalen. De overlap van 50 tokens zorgt ervoor dat je niet per ongeluk een cruciale zin over twee chunks splitst en de betekenis volledig verliest.

Voor PDF's specifiek gebruikte ik een tweestapsaanpak. Eerste doorgang: tekst extraheren per pagina. Tweede doorgang: afbeeldingen en diagrammen extraheren, ze apart embedden met paginanummer-metadata en zowel tekst- als visuele chunks opslaan in dezelfde Pinecone-namespace. Hier betaalt de multimodale capaciteit van Gemini Embedding 2 zich uit -- de visuele chunks leven in dezelfde vectorruimte als de tekstchunks, zodat één enkele query beide kan opleveren.

De eerste echte test: ik uploadde een producthandleiding van 40 pagina's met architectuurdiagrammen, UI-screenshots en API-referentietabellen. Vervolgens vroeg ik aan de chatinterface: "Hoe werkt de authenticatieflow?" Het systeem haalde drie tekstchunks op die het OAuth-proces beschreven en -- dit is het deel dat me verraste -- één afbeeldingschunk met het daadwerkelijke auth-flowdiagram van pagina 12. De multimodale ophaling werkte bij de eerste poging.

Ik ga niet doen alsof alles vlekkeloos ging. Het YouTube-scrapingonderdeel kostte drie pogingen om goed te krijgen. Mijn eerste aanpak gebruikte youtube-transcript-api om transcripties op te halen, maar die faalde stilletjes bij video's die alleen automatisch gegenereerde ondertitels hadden in niet-Engelse talen. De tweede poging voegde taaldetectie en fallback-logica toe. De derde voegde een deduplicatiecontrole toe tegen Pinecone's metadata om te voorkomen dat video's opnieuw werden ge-embed die al in de kennisbank zaten.

// lib/youtube-ingestion.ts
async function ingestYouTubeVideo(videoUrl: string) {
  const videoId = extractVideoId(videoUrl);

  // Check if already ingested
  const existing = await queryKnowledge("", 1, {
    videoId: { $eq: videoId }
  });

  if (existing && existing.length > 0) {
    console.log(`Video ${videoId} already in knowledge base, skipping.`);
    return;
  }

  const transcript = await fetchTranscript(videoId);
  const chunks = chunkText(transcript, 512, 50);

  for (const chunk of chunks) {
    await embedAndStore(chunk.text, {
      source: videoUrl,
      videoId,
      contentType: "youtube_transcript",
      chunkIndex: chunk.index
    });
  }
}

Die deduplicatiecontrole -- Pinecone's metadata bevragen vóór het embedden -- behoedde me voor een probleem dat aanvankelijk onzichtbaar zou zijn en op schaal rampzalig: dubbele vectoren die de zoekkwaliteit verwateren. Elke keer dat de auto-updater draait, controleert hij wat er al is voordat er iets nieuws wordt toegevoegd. Eenvoudige logica, makkelijk te vergeten, duur om achteraf te repareren.

Op dit punt had de app een werkende UI, een gekoppelde kennisbank met multimodale RAG en de mogelijkheid om PDF's en YouTube-content in te nemen. Wat het niet had, was een manier om actueel te blijven zonder dat ik handmatig ingestiescripts moest draaien. Dat is wat Stap 3 oplost -- en het is de stap die de meeste tutorials volledig overslaan.

Stap 3: Het Automatische Updatesysteem dat de Kennisbank Vers Houdt

Een kennisbank die stopt met groeien op de dag dat je hem oplevert, is een risico, geen feature. Gebruikers verwachten actuele informatie. Als je RAG-app nog steeds resultaten retourneert van data die je twee maanden geleden hebt geüpload terwijl de wereld verder is gegaan, brokkelt het vertrouwen snel af.

Ik gebruikte Railway voor de automatiseringslaag. Railway ondersteunt drie soorten compute: persistente services, cron jobs en serverless functies. De cron job-mogelijkheid is wat hier telt -- het laat je een script volgens een schema draaien, alleen betalen voor de uitvoeringstijd en netjes afsluiten tussen de runs door.

De opzet: een Node.js-service op Railway die dagelijks om 3 uur 's ochtends UTC draait. Hij controleert een geconfigureerde lijst van YouTube-kanalen op nieuwe video's die sinds de laatste run zijn gepubliceerd, scrapt transcripties, chunked ze en upsert naar Pinecone. Het hele proces duurt ongeveer 90 seconden voor een typische dag aan nieuwe content, wat fracties van een cent kost op Railway's prijsmodel op basis van gebruik.

// workers/daily-ingestion.ts
import { CronJob } from "cron";

async function dailyIngestion() {
  const channels = process.env.YOUTUBE_CHANNELS!.split(",");
  let newVideos = 0;

  for (const channelId of channels) {
    const recentVideos = await fetchRecentVideos(channelId, {
      publishedAfter: getLastRunTimestamp()
    });

    for (const video of recentVideos) {
      await ingestYouTubeVideo(video.url);
      newVideos++;
    }
  }

  console.log(`Ingested ${newVideos} new videos.`);
  await updateLastRunTimestamp();

  // Railway cron jobs expect the process to exit cleanly
  process.exit(0);
}

dailyIngestion();

Railway's Hobby-plan bevat $5 aan gebruik per maand. Voor een dagelijkse cron job die 90 seconden draait, gebruik je ruwweg $0,50-$1,00/maand aan compute -- ruim binnen de inbegrepen tegoeden. Het kortste interval dat Railway ondersteunt is 5 minuten tussen uitvoeringen, en schema's draaien op UTC, dus plan je timing dienovereenkomstig.

Eén ontwerpbeslissing die ik anders zou nemen: ik sloeg de "laatste run"-tijdstempel aanvankelijk op in een lokaal bestand op de Railway-service. Dat is fragiel -- als de service opnieuw wordt gedeployed, verdwijnt het bestand en verwerkt de volgende run alles opnieuw. Ik verplaatste de tijdstempel naar een Supabase-tabel, die persistent is over deploys heen en me een opvraagbaar logboek geeft van elke ingestierun. Kleine wijziging, grote betrouwbaarheidsverbetering.

De achtergrondautomatisering opende ook een workflow die ik niet had gepland. Omdat de kennisbank zichzelf bijwerkt, kon ik de ingestiepipeline richten op kanalen van concurrenten, branchenieuws of documentatierepo's. De kennis van de app groeide terwijl ik sliep. Voor een klant die dit als SaaS-product levert, is die zelfupdatende mogelijkheid een echt onderscheidend vermogen -- de ervaring van hun gebruikers verbetert dagelijks zonder handmatige interventie.

Als je liever hebt dat iemand deze volledige automatiseringspipeline van scratch bouwt, neem ik AI-app-ontwikkelopdrachten en RAG-systeembouw aan. Je kunt zien wat ik heb gebouwd op fiverr.com/s/EgxYmWD.

Maar een app die werkt is niet hetzelfde als een app die klaar is voor gebruikers. De kloof tussen "het werkt op mijn machine" en "het werkt op elk apparaat, elke browser, elk schermformaat" is precies waar Stap 4 zich bevindt. En het is de stap die de meeste solo-ontwikkelaars overslaan -- op eigen risico.

Stap 4: Kwaliteitscontrole die Daadwerkelijk Problemen Opspoort

Ik testte projecten vroeger in Chrome op mijn laptop en noemde het klaar. Die aanpak ging vaak genoeg mis dat ik cross-device testen nu als niet-onderhandelbaar beschouw. De tool die dit praktisch maakte is Test UI (voorheen LambdaTest), specifiek hun Kane AI-feature.

Kane AI is een AI-agent die echt gebruikersgedrag simuleert op verschillende apparaten en browsers. Je beschrijft een gebruikersflow in natuurlijke taal -- "log in met testgegevens, stel een vraag in de chat, sla het antwoord op als Kanban-notitie, schakel naar donkere modus en controleer vervolgens de layout op iPhone 15 Pro" -- en Kane voert het uit, waarbij het visuele regressies, kapotte interacties en prestatieproblemen signaleert.

De drie problemen die Kane opving en die ik zonder had geleverd:

  1. De chat-scrollbug. Op Safari iOS scrollde de chatcontainer niet naar het laatste bericht nadat de AI had geantwoord. De chat werkte perfect op Chrome desktop en zelfs Chrome mobiel. Safari behandelde het scrollIntoView-gedrag anders en het bericht verscheen onder de vouw. Gebruikers zouden hebben gedacht dat de app kapot was.

  2. De donkere modus-contrastfout. Twee tekstelementen in het Kanban-kaartcomponent hadden een contrastverhouding van 3,2:1 in donkere modus -- onder het WCAG AA-minimum van 4,5:1. Onzichtbaar voor mij op mijn high-end monitor. Onleesbaar op een budget Android-telefoon in fel zonlicht.

  3. De authenticatie-race condition. Op tragere verbindingen (gesimuleerd 3G) renderde de app af en toe het dashboard voordat Supabase de auth-sessie had bevestigd, waardoor het inlogscherm 200ms flitste voordat het doorstuurde. Geen beveiligingsprobleem -- de data was niet toegankelijk -- maar het voelde kapot en onprofessioneel.

Elk van deze zou supporttickets hebben gegenereerd. Elk was onzichtbaar in mijn normale ontwikkelomgeving. Geautomatiseerd testen vond ze alle drie in minder dan tien minuten.

De beveiligingsreview was een aparte doorgang. Ik gebruikte de code-reviewmogelijkheid van Claude Code om te scannen op kwetsbaarheden -- specifiek controlerend op blootgestelde API-sleutels, SQL-injectievectoren in de Supabase-queries en onjuiste CORS-configuratie op de API-routes. Claude signaleerde één probleem: de Gemini API-sleutel werd naar de client-side bundle gestuurd omdat ik de omgevingsvariabele had benoemd zonder de NEXT_PUBLIC_-prefixconventie -- andersom, ik had hem per ongeluk opgenomen waar hij niet thuishoorde. Server-side API-calls moeten sleutels gebruiken die nooit de browser bereiken. Ontdekt vóór deployment. Had een kostbaar lek kunnen zijn.

Voor iedereen die een productie-app bouwt, hier is mijn testchecklist:

  1. Cross-browser testen op Chrome, Safari, Firefox en Edge (Kane AI of handmatig)
  2. Mobiel testen op ten minste één iOS- en één Android-apparaat met verschillende schermformaten
  3. Simulatie van traag netwerk om race conditions en ontbrekende laadstatussen op te vangen
  4. Toegankelijkheidsaudit voor contrastverhouding, toetsenbordnavigatie en schermlezerscompatibiliteit
  5. Beveiligingsscan voor blootgestelde inloggegevens, injectievectoren en verkeerd geconfigureerde CORS
  6. Belastingstest op de RAG-pipeline -- wat gebeurt er wanneer 50 gelijktijdige gebruikers de kennisbank bevragen?

Ik schat dat de testfase 3 uur aan de build heeft toegevoegd. Die 3 uur voorkwamen minstens 10 uur brandjes blussen na lancering. De rekensom is niet eens een wedstrijd.

Nu -- de app werkt, is getest en is beveiligd. Het enige dat tussen dit project en echte gebruikers staat, is deployment. En dankzij de Vercel + GitHub-pipeline is dat de makkelijkste stap in het hele proces.

Stap 5: Deployment -- Van Lokale Build naar Live Product

De deployment-pipeline is bijna anticlimactisch na de complexiteit van Stappen 2-4. Dat is bewust zo -- als je deployproces stressvol is, is er iets eerder in het proces mis.

Ik committede de laatste wijzigingen naar de GitHub-repository die Lovable oorspronkelijk had aangemaakt. Vervolgens koppelde ik de repo aan Vercel, wat ongeveer twee minuten duurde: autoriseer de GitHub-integratie, selecteer de repository, bevestig de frameworkdetectie (Next.js) en voeg de omgevingsvariabelen toe.

De omgevingsvariabelen zijn het enige onderdeel dat zorgvuldigheid vereist:

GEMINI_API_KEY=your-gemini-api-key
PINECONE_API_KEY=your-pinecone-api-key
PINECONE_INDEX=your-index-name
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

Let op het patroon: variabelen met het NEXT_PUBLIC_-prefix zijn veilig voor client-side blootstelling (Supabase URL en anon key zijn ontworpen om publiek te zijn). Al het andere -- Gemini API-sleutel, Pinecone API-sleutel, Supabase service role key -- blijft uitsluitend server-side. Dit door elkaar halen is een van de meest voorkomende beveiligingsfouten bij Next.js-deployments, en het is precies het probleem dat Claude Code opving tijdens de beveiligingsreview.

De eerste deploy van Vercel duurde 47 seconden. Volgende pushes naar de main-branch triggeren automatische herdeployments. Ik voegde een aangepast domein toe via het dashboard van Vercel -- richt de DNS, wacht op SSL-provisionering (meestal minder dan 5 minuten) en de app is live op een professionele URL.

De uiteindelijke architectuur ziet er zo uit:

Laag Service Maandelijkse Kosten (Hobby/Starter)
Frontend + API Vercel Gratis laag (hobby) of $20/maand (pro)
Auth + Database Supabase Gratis laag (tot 50K maandelijkse actieve gebruikers)
Vectoropslag Pinecone Gratis laag (100K vectoren) of $70/maand (Starter)
Embeddings Gemini API Gratis laag (1.500 verzoeken/dag)
Automatisering Railway $5/maand (Hobby, inclusief $5 gebruik)
Totaal (Gratis Lagen) $5/maand
Totaal (Betaalde Lagen) ~$95/maand

Voor een SaaS-app die je aan klanten kunt verkopen voor $50-200/maand per gebruiker is die kostenstructuur uiterst gezond. Zelfs het totaal van de betaalde laag van $95/maand laat significante marge over.

Wat Ik Fout Deed en Wat Ik Zou Veranderen

Ik wil eerlijk zijn over de delen van deze build die niet soepel verliepen, omdat de opgepoetste versie van elke tutorial de beslissingen verbergt die er echt toe doen.

De chunkingstrategie moet worden afgestemd per contenttype. Mijn chunks van 512 tokens met 50 tokens overlap werkten goed voor tekstdocumenten en transcripties. Voor PDF's met dichte technische content realiseerde ik me later dat chunks van 768 tokens completere concepten vastlegden. Voor videotranscripties -- die meestal meer conversationeel en minder informatiedicht zijn -- verminderden chunks van 384 tokens de ruis in ophaalresultaten. Er is geen universele chunkgrootte. Je moet testen met je daadwerkelijke data.

Gemini Embedding 2 is nog in preview. De model-identifier gemini-embedding-exp-03-07 bevat "exp" niet voor niets. Tijdens mijn build liep ik twee keer tegen rate limits aan tijdens bulkingestie die niet waren gedocumenteerd in de API-referentie. De workaround was het toevoegen van exponential backoff met maximaal 5 herhaalpogingen, wat Claude Code in ongeveer 30 seconden implementeerde toen ik het probleem beschreef. Maar vertrouwen op een experimenteel model voor productiewerklasten brengt risico's met zich mee. Houd de aankondiging voor algemene beschikbaarheid in de gaten voordat je opschaalt naar duizenden gebruikers.

De gratis laag van Lovable is te krap voor iteratie. Vijf dagelijkse berichten klinkt redelijk totdat je in je derde verfijningsronde zit en je tegoed om 10 uur 's ochtends al op is. Ik upgradede naar Starter ($25/maand) op de tweede dag. Als je serieus bent over deze workflow, budget dan vanaf het begin voor de betaalde laag.

De YouTube-scrapingpipeline is broos. YouTube heeft geen officiële transcript-API -- de tools die bestaan reverse-engineeren ongedocumenteerde endpoints. Google kan morgen iets veranderen en de hele ingestiepipeline breken. Voor een productie-app zou ik een fallback bouwen die Whisper of Gemini's audiomogelijkheden gebruikt om direct van de audiostream te transcriberen in plaats van te vertrouwen op YouTube's ondertitelingsdata.

Cross-modale ophaalkwaliteit varieert. Tekst-naar-tekst ophaling met Gemini Embedding 2 is uitstekend. Tekst-naar-afbeelding ophaling is goed maar niet perfect -- ongeveer 80% van de tijd toont het het juiste diagram. De overige 20% retourneert zijdelings gerelateerde afbeeldingen. Voor kritieke use cases voegde ik een relevantiescore-drempel (0,75) toe waaronder resultaten worden uitgefilterd. Dat bracht de nauwkeurigheid naar een niveau waarmee ik comfortabel kon leveren.

Dit zijn geen dealbreakers. Het is het soort fijnafstemming dat een weekendprototype onderscheidt van een productieproduct. En als je er van tevoren van weet, kun je erop plannen in plaats van ze te ontdekken om 23:00 de avond vóór een klantdemo.

Wat Deze Stack Mogelijk Maakt

De combinatie van Gemini Embedding 2, Pinecone en geautomatiseerde ingestie maakt een categorie applicaties mogelijk die zes maanden geleden niet praktisch was. Een paar concrete voorbeelden:

Interne bedrijfskennisbanken die je documentatie echt begrijpen. Geen trefwoordzoekopdrachten -- semantisch zoeken door tekst, diagrammen, trainingsvideo's en opgenomen vergaderingen. Een engineer vraagt "hoe werkt de logica voor betalingsherhalingen?" en krijgt het relevante codefragment, het architectuurdiagram EN het tijdstip uit de uitleg van de tech lead in de all-hands-video van vorige maand.

Klantgerichte onderzoeksassistenten die automatisch actueel blijven. Advocatenkantoren, adviesbureaus, onderzoeksorganisaties -- elk bedrijf waar professionals uren besteden aan het doorzoeken van documenten naar relevante precedenten of datapunten. De auto-update-pipeline betekent dat de kennisbank dagelijks groeit zonder handmatige curatie.

Educatieve platformen waar studenten cursusmateriaal kunnen bevragen over alle formaten heen. Upload collegevideo's, PDF-studieboeken en presentaties. Studenten stellen vragen in natuurlijke taal en krijgen antwoorden uit het meest relevante formaat -- soms een tekstpassage, soms een specifiek moment in een collegevideo.

Elk van deze was eerder in theorie mogelijk. In de praktijk maakte de integratiecomplexiteit -- aparte embedding-modellen voor tekst en afbeeldingen, aparte ophaalpipelines, handmatige transcriptiestappen -- ze onpraktisch voor kleine teams. Gemini Embedding 2 comprimeert die complexiteit tot één enkele API-call. Pinecone handelt de opslag en het ophalen af. Claude Code koppelt alles aan elkaar, sneller dan dat je de boilerplate handmatig zou schrijven.

De vraag is niet of deze techstack werkt. Ik heb bewezen dat het zo is. De vraag is wat jij ermee gaat bouwen.

Het Draaiboek, Beknopt

Voor de bouwers die de gestroomlijnde versie willen zonder de oorlogsverhalen:

  1. Ontwerp de UI in Lovable. Wees specifiek in je prompts. Itereer in gerichte rondes die telkens één probleem aanpakken. Exporteer naar GitHub wanneer je 80% kwaliteit bereikt.

  2. Koppel de backend in Anti-Gravity + Claude Code. Verbind Pinecone (3.072 dimensies, cosinus-similariteit). Integreer Gemini Embedding 2 voor multimodale chunking en embedding. Bouw het query-endpoint met metadata-filtering en relevantiescore-drempels.

  3. Automatiseer ingestie met Railway. Dagelijkse cron jobs voor nieuwe content. Deduplicatiecontroles tegen Pinecone-metadata. Sla run-tijdstempels op in Supabase, niet in lokale bestanden.

  4. Test op meerdere apparaten en scan op beveiligingsproblemen. Kane AI voor cross-browser en mobiel testen. Claude Code voor beveiligingsreview. Reken op 3 uur -- het bespaart er 10.

  5. Deploy naar Vercel. Koppel GitHub, stel omgevingsvariabelen in (server-side sleutels blijven server-side), configureer een aangepast domein. Eerste deploy in minder dan een minuut.

Totale bouwtijd voor iemand die deze gids volgt: 2-3 dagen voor de eerste iteratie. Volgende apps met hetzelfde patroon: 4-8 uur.

Als je RAG-apps hebt gebouwd met tekst-only embeddings en je afvraagt waarom de ophaalkwaliteit een plafond bereikt, is Gemini Embedding 2 de upgrade die door dat plafond heen breekt. Als je handmatig UI's hebt gecodeerd voor AI-apps in plaats van tools zoals Lovable te gebruiken, besteed je uren aan werk dat een prompt in minuten kan afhandelen. Als je handmatig kennisbanken hebt bijgewerkt in plaats van ingestie te automatiseren, loopt je app al achter.

De tools hebben de visie ingehaald. Het vijfstappenraamwerk werkt. De enige variabele die overblijft is wat jij besluit te bouwen -- en of je vandaag begint of wacht tot iemand anders het eerst bouwt.

Veelgestelde Vragen

Wat is Gemini Embedding 2 en hoe verschilt het van eerdere embedding-modellen?

Gemini Embedding 2 is het eerste standaard multimodale embedding-model van Google DeepMind, uitgebracht in public preview op 10 maart 2026. In tegenstelling tot tekst-only voorgangers mapt het tekst, afbeeldingen, video, audio en PDF's naar één enkele 3.072-dimensionale vectorruimte. Het scoort 68,32 op MTEB English, met een voorsprong van 5,09 punten. Zie voor een gedetailleerde uitleg van de architectuur het gedeelte hierboven over waarom Gemini Embedding 2 het RAG-speelboek herschrijft.

Hoeveel kost het om een RAG-app te bouwen en te draaien met deze stack?

Met de gratis lagen van Vercel, Supabase, Pinecone en de Gemini API is de enige vereiste kosten Railway voor $5/maand voor geautomatiseerde ingestie. Betaalde lagen voor alle services kosten in totaal ongeveer $95/maand. Zie voor de volledige kostenuitsplitsing per service het deployment-gedeelte hierboven.

Welke chunkgrootte moet ik gebruiken voor Gemini Embedding 2 met Pinecone?

Begin met chunks van 512 tokens en 50 tokens overlap voor algemene content. Pas aan op basis van contenttype: 768 tokens voor dichte technische PDF's, 384 tokens voor conversationele transcripties. Er is geen universeel optimale grootte -- test met je daadwerkelijke data en meet de ophaalnauwkeurigheid. Zie het gedeelte "Wat Ik Fout Deed" voor meer details over afstemming.

Kan Gemini Embedding 2 aparte tekst- en afbeeldings-embeddingpipelines vervangen?

Ja -- dat is het voornaamste voordeel. Eén enkele API-call embedt tekst, afbeeldingen, video, audio en documenten in één uniforme vectorruimte, waardoor de noodzaak voor aparte embedding-modellen en ophaalpipelines wegvalt. Cross-modale zoekopdrachten (tekstquery die relevante afbeeldingen ophaalt) werken met ongeveer 80% nauwkeurigheid met een relevantiedrempel van 0,75.

Is Gemini Embedding 2 klaar voor productie?

Per maart 2026 is het model in public preview met de identifier gemini-embedding-exp-03-07. Het werkt betrouwbaar voor applicaties op gemiddelde schaal, maar heeft ongedocumenteerde rate limits tijdens bulkingestie. Voeg exponential backoff toe aan je pipeline en houd de aankondiging voor algemene beschikbaarheid in de gaten voordat je opschaalt naar duizenden gelijktijdige gebruikers.

Laten We Samenwerken

Wil je AI-systemen bouwen, workflows automatiseren of je technische infrastructuur opschalen? Ik help je graag.

Coffee cup

Vond u dit artikel leuk?

Uw steun helpt mij meer diepgaande technische content, open-source tools en gratis bronnen voor de ontwikkelaarsgemeenschap te maken.

Gerelateerde onderwerpen

Engr Mejba Ahmed

Over de auteur

Engr Mejba Ahmed

Engr. Mejba Ahmed builds AI-powered applications and secure cloud systems for businesses worldwide. With 10+ years shipping production software in Laravel, Python, and AWS, he's helped companies automate workflows, reduce infrastructure costs, and scale without security headaches. He writes about practical AI integration, cloud architecture, and developer productivity.

Discussion

Comments

0

No comments yet

Be the first to share your thoughts

Leave a Comment

Your email won't be published

14  -  2  =  ?

Blijf leren

Gerelateerde artikelen

Alles bekijken

Comments

Leave a Comment

Comments are moderated before appearing.

Learning Resources

Expand Your Knowledge

Accelerate your growth with structured courses, verified certificates, interactive flashcards, and production-ready AI agent skills.

Sample Certificate of Completion

Sample certificate — complete any course to earn yours

Engr Mejba Ahmed

Engr Mejba Ahmed

Claude Code Expert · Online

👋

Hey there!

Quick Actions

WhatsApp Instant reply

Chat on WhatsApp

+880 1723 741224 · Instant reply

Popular Questions

Engr Mejba Ahmed is connected
Engr Mejba Ahmed is typing...
Engr Mejba Ahmed avatar

✉ Want me to follow up? Drop your email

Engr Mejba Ahmed avatar

📞 Connect Directly

Choose how you'd like to reach me

WhatsApp

+880 1723 741224

Email

[email protected]

✓ Details sent! I'll get back to you shortly.

Powered by OpenAI

335+

Blog Posts

25

AI Courses

63

Projects

Services & Expertise

Pricing & Process

Learning & Resources

Connect & Support