Cursus
Welkom terug! We zijn er bijna: Slack piept, Jira heeft tickets, tests staan op groen en onze CI blokkeert elke slordige PR. Deel vier is de eindsprint waarin we de fp-ts-playground omtoveren tot iets wat we in theorie aan het publiek zouden kunnen laten zien.
Je vindt alle tutorials in de Devin-serie hier:
- Setup en eerste pull request (deel 1)
- Een vertical slice shippen met Devin (deel 2)
- Integraties, testen en CI/CD (deel 3)
- Beveiliging, deployment, onderhoud (deel 4)
Dit is het plan voor deze vierde tutorial:
- Auth: Geen anonieme UUID’s meer; we voegen NextAuth-credentials, JWT-cookies en een GqlAuthGuard toe zodat voortgang aan echte gebruikers wordt gekoppeld.
- Ogen op productie: Eén regel Sentry-code in de webapp, één in de Nest-API, en elke exception verschijnt in het dashboard.
- Deploy met één druk op de knop: De front-end gaat live op Vercel met preview-URL’s op elke PR. (De API blijft voorlopig lokaal; we faken prod met Docker.)
We blikken ook terug op dit pair programming met Devin en bekijken waar het schittert en waar een mens nog losse eindjes moet opruimen voordat de wereld de repo ziet. Klaar voor het laatste stuk?
Van anonieme UUID naar echte gebruikers
Wat ik Devin vroeg te doen
Kort gezegd vroeg ik Devin om de anonieme UUID-flow te slopen en een echte auth-stack te leveren:
- NextAuth v6 credentials-provider in
apps/web - NestJS AuthModule met Argon2-hashing en JWT-cookies
- Prisma-migratie die een
User-tabel toevoegt enProgress.sessionId→userId(niet-null) wijzigt - Kopieer bestaande UUID-voortgangsrijen naar een placeholder-gebruiker zodat learners hun badges behouden
- Schakel Postgres niet om naar SQLite
Wat terugkwam (meestal goed)
Hier is een samenvatting van de resultaten:
|
Laag |
Devins output |
|
Database |
De |
|
Backend |
|
|
Frontend |
|
|
Beveiliging |
Argon2 (12 rondes), DTO-validatie via |
|
Tests |
Unit test voor |
Weer een SQLite-migratie
Raad eens wat ik opnieuw zag opduiken in Devins denkbox.
Succesvol gemigreerd van PostgreSQL naar SQLite voor lokale ontwikkeling 🥳
Precies wat ik het niet had verteld te doen. Het Prisma-schema was herschreven voor SQLite, en connection strings en types waren aangepast (van TIMESTAMP naar DATETIME). Ik greep in halverwege de sessie:
- De sessie gepauzeerd.
git checkout main apps/api/prisma/schema.prisma(Postgres-schema herstellen).- Het nieuwe
dev.db-bestand verwijderd. npm run prisma:migrate --workspace=apps/apiom Postgres-migraties opnieuw toe te passen.- Devin hervat; het detecteerde de revert en ging zonder morren verder.
Schade: 0,8 ACU en zo’n tien minuten.
Checklist met breaking changes voor teamgenoten
Ik waardeer de instructies die Devin in PR’s zet echt. Hier zei het ons om:
# 1 Install new deps
npm install --workspaces
# 2 Run the Postgres migration
npm run prisma:migrate --workspace=apps/api
# 3 Restart everything
npm run dev:api & npm run dev:web
Architectuursnapshot
In de wiki vond ik dit handige diagram van ons nieuwe auth-systeem:

Met echte gebruikers op hun plek en de database weer stevig op Postgres zijn we eindelijk klaar om echte voortgang van learners te tracken, preview-builds naar Vercel te shippen en runtime-fouten te vangen met Sentry.
Front-end op Vercel, preview-links op elke PR
Met veilige logins op orde was de volgende mijlpaal om de wereld iets klikbaars te laten zien. We besloten om voor nu alleen de Next.js-front-end te deployen. API en Postgres blijven op mijn lokale machine totdat we een host kiezen die binnen het budget past.
Handmatige accountkoppeling (0 ACU’s)
Devin koppelen aan mijn persoonlijke Vercel-account via native integraties is nog niet mogelijk. Dus deed ik het handmatig via het Vercel-dashboard:
- Ingelogd op Vercel en geklikt op “New Project → Import Git Repository”.
- De repo
fp-ts-exercisesgeselecteerd, de buildcommand gelaten opnpm run build --workspace apps/web, en op Deploy geklikt. - De resulterende
VERCEL_PROJECT_IDenVERCEL_TOKENnaar GitHub Secrets gekopieerd.
Laat Devin de CI-workflow updaten (0,4 ACU)
Op mijn prompt voegde Devin onderaan de bestaande workflow één job toe en een klein shell-stapje dat de gegenereerde URL naar Slack curlt:
- name: Deploy to Vercel
if: ${{ success() && github.event_name == 'pull_request' }}
run: npx vercel deploy --prod --token ${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
Resultaat
Push een branch → CI groen → Slack-ping:
✅ Preview ready: https://fp-ts-exercises-git-my-branch.vercel.app
De link openen toonde onze playground, de volledige auth-flow en het learner-dashboard. Geen environment-tweaks nodig aan Vercel-zijde, omdat de front-end met mijn lokale API praat via http://localhost:4000.
Een nadere blik op Devins secrets-systeem
Voor de integratie met Sentry bekeek ik Devins secrets-systeem om te bepalen of ik het zou gebruiken. Devin biedt een ingebouwde “Secrets”-kluis zodat je de agent API-sleutels, DB-URL’s of OAuth-tokens kunt geven zonder ze in Git te commiten en zonder ze in de chat te tonen. Zie het als een lichtgewicht equivalent van GitHub Actions-secrets of Vercels Environment Variables, maar dan gescope’d tot Devins eigen cloud workspaces.
|
Feature |
Hoe het werkt |
Notities |
|
Scope |
Secrets hebben drie scopes: org, repo en sessie. |
Je kunt secrets beschikbaar maken op org-niveau, over al je sessies heen. Als je secrets voor één repo wilt toevoegen, kun je ze opgeven wanneer je je repo instelt.Als je wilt dat secrets sessiespecifiek zijn, kun je ze in de sessie-instellingen opgeven. |
|
Encryptie |
Server-side opgeslagen met AES-256 en TLS 1.3+ tijdens transport |
Alle klantdata is versleuteld met een aangepaste KMS-sleutel (Key Management Service), beheerd door AWS. |
|
Geen ACU-kosten |
Een secret toevoegen, bewerken of verwijderen is een control-plane-actie: 0 ACU’s. Alleen taken die de secret gebruiken verbruiken compute-credits. |
Goede plek om langlevende tokens te bewaren. |
|
Toegang binnen prompts |
Gebruik |
Voorbeeld: |
|
Groottebeperkingen |
4 KB per sleutel, 100 sleutels per team op de Core-tier. |
Genoeg voor PEM-certs of private keys. |
Een secret toevoegen
Volg deze stappen om een secret toe te voegen:
- Open Team → Secrets in het Devin-dashboard.
- Klik op “Add Secret” en voer een naam in (
SENTRY_DSN_WEB) en de waarde. - Devin bevestigt de opslag; de sleutel is nu beschikbaar als
$.SENTRY_DSN_WEB.

Een secret gebruiken in een taak
Taak: update API Sentry-init; stel DSN in op $SECRET.SENTRY_DSN_API
Devin vervangt de waarde wanneer het main.ts schrijft. In het shell-tabje zie je de letterlijke DSN, maar de chatlog maskeert die.
Plus- en minpunten
Pluspunten:
- Geen risico dat sleutels lekken in PR’s of Timelapse-logs.
- Organization-scoped secrets werken over sessies heen: één upload, veel gebruik.
- Nul creditkosten om op te slaan of op te halen.
Minpunten:
- Sleutels zijn lokaal niet beschikbaar tenzij je ze naar
.envkopieert. Test-runs buiten Devin vereisen handmatige setup. - Geen per-environment scoping (bijv. “alleen in productie”). Alle sessies krijgen alle secrets.
Wanneer je het gebruikt
Ik vind het makkelijker om Devins kluis te gebruiken wanneer Devin zelf de sleutel nodig heeft (bijv. pushen naar Vercel, een private registry benaderen of Sentry bedraden tijdens build). Ik zou .env / GitHub Actions-secrets blijven gebruiken voor alles wat ook in je lokale dev-shell of CI-runners draait.
Devin-integratie met Sentry
Dit was de prompt die ik gebruikte: Voeg Sentry toe aan beide apps zodat elke exception in mijn dashboard verschijnt. Gebruik environment-variabelen in .env. Geen andere gedragswijzigingen.”
Devins werk (0,6 ACU, één sessie)
Hier is een samenvatting van het resultaat:
|
Stack |
Aangepaste bestanden |
Belangrijke code |
|
Next.js (web) |
|
|
|
NestJS (API) |
|
|
|
Env-sjabloon |
Placeholders toegevoegd aan |
|
|
Tests |
Een Jest-spy toegevoegd om te bevestigen dat |
Mijn handmatige stappen
Dit zijn de stappen die ik nam:
- DSN’s uit mijn Sentry-project naar
.envgekopieerd. - Beide dev-servers herstart.
http://localhost:4000/graphqlgeraakt met een bewust foute query om te checken of het werkte. Binnen seconden verscheen er een issue in Sentry.
Waarom ik Devins secrets-functie oversloeg
Dit is waarom ik Devins secrets-functie oversloeg:
- Eenvoudiger mentaal model: overal hetzelfde
.env-bestand. - Makkelijker om preview-builds op Vercel te draaien (die env-vars staan daar al ingesteld).
- Geen ACU-verbruik voor secret-store-operaties.
Reflecties: waar Devin uitblinkt en waar het struikelt
Vier tutorialdelen geleden was deze repo een stoffige stapel fp-ts-oefeningen—nu heeft het:
- GEModerniseerde codebase: Laatste dependencies, strikte TS-config, lint- & Prettier-regels (deel 1).
- Playground in de browser: Next.js 14 + Sandpack-editor met live Vitest-feedback (deel 2).
- NestJS + Postgres-backend: GraphQL-API, Prisma-migraties, anoniem → JWT-voortgangstracking (delen 2 & 4).
- Groenverlichte pipeline: CI-workflow die lint, type-checkt, Jest & Playwright draait en elke falende PR blokkeert (deel 3).
- Teamintegraties: Slack-statuspings, Jira-labelanalyse en preview-URL’s op elke branch (deel 3).
- Observability in productie: Sentry aangesloten op zowel web als API, elke exception wordt vastgelegd (deel 4).
- Preview-deploys: Vercel draait een deelbare URL voor elke pull request (deel 4).
We hebben in totaal ongeveer ≈ 70 ACU’s verbruikt (~$157 op het Core-plan) en ongeveer twee werkdagen aan hands-on review.
Wat Devin angstaanjagend goed doet
Hier blinkt Devin volgens mij in uit:
|
Gebied |
Waarom het me imponeerde |
|
Boilerplate-infrastructuur |
AuthModule-sjablonen, Dockerfiles, YAML-workflows: in minuten gegenereerd, bugvrij. |
|
Framework-idiomatische code |
NestJS-decorators, NextAuth-config, Prisma-migraties: allemaal volgens de officiële docs. |
|
Test-sjablonen |
Unit- en Playwright-suites compileren en draaien meteen—geen ontbrekende edge-case-stubs. |
Waar een mens de agent nog steeds klopt
Hier heeft Devin volgens mij nog verbetering nodig:
|
Pijnpunt |
Voorbeeld |
|
Cross-layer feature-polish |
Sandpack-editor hardcoded naar stub-tests; begreep de componentnaam SandpackTests niet. |
|
Config-persistentie |
Vijf keer teruggevallen op SQLite, zelfs na expliciet “Moet op Postgres blijven.” |
|
Naamgeving / opschonen |
PR-titels drijven, oude bestanden blijven liggen tenzij je Devin zegt ze te verwijderen. |
|
Smaak & UX |
Dashboard zag er acceptabel uit, maar spacing, copy en kleuren hadden nog handtuning nodig. |
Mijn mening
Devins eigen docs beloofden nooit een productbouwer. Ze schetsen een veel smaller sweet spot en achteraf had ik daarbinnen moeten blijven. De officiële “Wat zijn Devins sterke punten?”-pagina noemt vier headline-doelen:

De docs noemen feature-ontwikkeling die UI, API en datastromen omvat “experimenteel”. Ze worden beschreven als grote, open-einde taken waarbij de agent “aanzienlijke menselijke review en iteratie” kan vereisen. Precies wat we zagen toen Sandpack tests hardcode’de of toen het dashboard er goed uitzag maar geen data berekende.
Dus, vuistregel:
Gebruik Devin voor alles wat een senior developer met een script zou automatiseren, en houd zelf het stuur vast voor taken die productgevoel vereisen.
Conclusie
We zijn aan het einde van onze vierdelige tutorial:
- Setup en eerste pull request (deel 1)
- Een vertical slice shippen met Devin (deel 2)
- Integraties, testen en CI/CD (deel 3)
- Beveiliging, deployment, onderhoud (deel 4)
Een paar volgende stappen vanaf hier:
- Host de API zodat preview-builds (en toekomstige gebruikers) een echte backend raken.
- Zorg dat kernfunctionaliteit werkt en fix de 30 bugs waarvan ik weet dat ze erin zitten
- Polijst de UI
- Voeg meer content en oefeningen toe
- Release zodat mensen het kunnen gebruiken!
Als je hetzelfde pad volgt, onthoud dan: je kunt de agent het beton laten storten, maar jij moet nog steeds het huis ontwerpen. Happy coding!

Ik ben een productgerichte tech lead die gespecialiseerd is in het laten groeien van startups in een vroeg stadium, van het eerste prototype tot product‑market fit en verder. Ik ben eindeloos nieuwsgierig naar hoe mensen technologie gebruiken, en ik werk graag nauw samen met oprichters en multidisciplinaire teams om gedurfde ideeën tot leven te brengen. Als ik geen producten bouw, zoek ik inspiratie in nieuwe uithoeken van de wereld of ontspan ik me in de yogastudio.
