Les 2 Klas B — OpenCode Pro met AGENTS.md, worktrees & GSAP/Lenis

This commit is contained in:
2026-05-18 14:30:00 +02:00
parent 0393976b23
commit b053fc7206
10 changed files with 2506 additions and 0 deletions

View File

@@ -0,0 +1,619 @@
# Les 2 — OpenCode Pro
## Lesstof — Rules, Worktrees & Scroll Animations
**Vak:** AI-Assisted Development
**Opleiding:** NOVI Hogeschool Utrecht
**Onderwerp:** OpenCode Desktop professioneel inzetten met regels, config en parallel worktrees
---
## Inhoudsopgave
1. [OpenCode in 2026](#1-opencode-in-2026)
2. [TUI vs Desktop — welke kies je?](#2-tui-vs-desktop)
3. [Plan/Build/@explore + /init](#3-planbuildexplore--init)
4. [`AGENTS.md` — het officiële regelbestand](#4-agentsmd--het-officiele-regelbestand)
5. [`opencode.json` — config & permissies](#5-opencodejson--config--permissies)
6. [Plugins & `opencode-worktree`](#6-plugins--opencode-worktree)
7. [De scroll-animatie stack (Next.js 16)](#7-de-scroll-animatie-stack)
8. [Project setup van A tot Z](#8-project-setup-van-a-tot-z)
9. [Workflow patterns](#9-workflow-patterns)
10. [Bronnen](#10-bronnen)
---
## 1. OpenCode in 2026
OpenCode is een open-source AI coding-IDE. 60.000+ GitHub stars. Gemaakt door SST. Provider-agnostisch — werkt met OpenAI, Anthropic, Google, Groq, lokale modellen via Ollama, en meer.
Vergelijkbaar concept als Cursor of Claude Code, maar:
- **Open source** — geen vendor lock-in
- **Provider-keuze** — niet vast aan één AI-bedrijf
- **Script-vriendelijk** — perfect voor automation, CI/CD, plugins
- **Twee smaken:** Desktop (UI) en TUI (terminal)
### Desktop App (vandaag onze keuze)
Native app voor macOS, Windows, Linux. Download via https://opencode.ai/download.
Layout (globaal):
- **File tree** links — bestanden + folders, right-click voor acties
- **Diff viewer** midden — visueel groen/rood met klik-accept/reject
- **Chat panel** onder — prompts naar de agent
- **Sessions sidebar** links — meerdere parallelle sessies (voor worktrees!)
- **Ingebouwde terminal** — onderaan, optioneel
### TUI (terminal)
```bash
npm i -g opencode-ai@latest
opencode
```
Zelfde engine, zelfde commando's, zelfde plugins. Goed voor SSH, scripts, CI/CD.
---
## 2. TUI vs Desktop — Welke kies je?
| Aspect | TUI | Desktop |
|--------|-----|---------|
| Leercurve | Steiler — alles via keyboard | Vlakker — visueel |
| Diff review | Plain text inline | Visuele diff-viewer |
| Files browsen | Via @-references | File tree zichtbaar |
| Sessies parallel | Tmux / aparte terminals | Sessions sidebar |
| SSH / headless servers | ✅ | ❌ (X-server nodig) |
| Worktree plugin auto-spawn | ✅ (spawnt terminal) | ❌ (handmatige tab) |
| Snel typen / muscle memory | ✅ | Ok, maar trager |
| Scripted workflows | ✅ | Beperkt |
### Wanneer wel TUI?
- **SSH-only servers** — geen X11 nodig
- **CI/CD pipelines** — scripted invocaties
- **Tmux fans** — past in je tmux setup
- **Worktree power-users** — auto-terminal-spawn van de plugin
### Onze keuze voor deze les en eindopdracht: Desktop
Sneller te leren, visueler, beter voor parallel-werken via Sessions sidebar.
---
## 3. Plan/Build/@explore + /init
### Plan vs Build mode
OpenCode heeft twee modes — Tab om te wisselen.
**Plan mode** is read-only. Tools: `read`, `grep`, `glob`, `webfetch`. Geen edits, geen shell commands. Goed voor brainstorm / verkenning.
**Build mode** is default. Alle tools aan. Schrijft code, voert commands uit.
Best practice: begin **altijd** in plan-mode. Laat het uitleggen wat het van plan is. Geef feedback. Pas dan Tab → build.
### Sub-agents
Drie ingebouwde sub-agents:
| Naam | Wat | Wanneer |
|------|-----|---------|
| `@explore` | Read-only verkenning | "Waar staat X?" "Wat is dit?" |
| `@general` | Brede taak-agent | Default voor de meeste taken |
| `@scout` | Gerichte zoekopdracht | "Vind alle plaatsen waar..." |
Manuele aanroep: `@explore vind alle authenticatie code`. Primaire agent kan ze ook autonoom inschakelen.
### `/init` commando
In de chat: `/init`. OpenCode scant je repo, stelt vragen, en genereert/update je `AGENTS.md`.
Doe dit **als eerste actie** in elk nieuw project. Daarna kun je het bestand uitbreiden met jouw specifieke regels.
### Belangrijke keybinds (Desktop én TUI)
| Shortcut | Actie |
|----------|-------|
| `Tab` | Wissel plan ↔ build |
| `Enter` | Submit |
| `Esc` | Cancel |
| `Ctrl+X h` | Help (alle bindings) |
| `Ctrl+D` | Exit (TUI) |
Leader-key voor commando-specifieke bindings: `Ctrl+X`. Customizen via `~/.config/opencode/tui.json` of in Desktop settings.
---
## 4. `AGENTS.md` — Het officiële regelbestand
`AGENTS.md` is markdown in je project-root die OpenCode automatisch in elke context laadt. Officieel format. Expliciet vergeleken in de docs met Cursor's `.cursorrules`.
### Twee locaties
| Pad | Wanneer |
|-----|---------|
| `./AGENTS.md` | Per project (in repo, geversioneerd) |
| `~/.config/opencode/AGENTS.md` | Globaal voor alle projecten |
### Externe regels referencen
```markdown
# Stack rules
@rules/styling.md
@rules/security.md
```
OpenCode laadt deze lazy via z'n Read-tool — pas wanneer relevant.
### Voorbeeld voor scroll-animatie project
```markdown
# Project Rules
## Why this stack
High-end scroll storytelling site (Awwwards/FWA niveau).
GSAP + Lenis = pro standaard — Apple, Stripe, OpenAI, Active Theory,
Locomotive, Darkroom Engineering. Framer Motion is voor app UI, niet voor
scroll storytelling. Kies GSAP voor timing-precisie + GPU-perf.
## Stack
- Next.js 16 (App Router, TypeScript, Turbopack)
- TailwindCSS voor styling
- GSAP 3.15+ (incl. ScrollTrigger, SplitText) met `@gsap/react`
- Lenis 1.3+ (`lenis/react`) voor smooth scroll
## Hard rules
- Geen Framer Motion, react-spring, AOS
- Animaties altijd in Client Components (`"use client"`)
- ScrollTrigger registratie 1x per file
- Animatie-code altijd binnen `useGSAP(() => {}, { scope: ref })`
- Nooit `useEffect` voor GSAP code
- Lenis sync: `gsap.ticker.add` met `autoRaf: false`
- **Async params (Next 16):** altijd `await params` en `await searchParams`
## Patterns
- Eén `<SmoothScroll>` wrapper in `app/layout.tsx`
- Refs i.p.v. globale selectors; scope animaties
- Tailwind voor layout/typografie; GSAP voor transform/opacity
- Geen `transition-*` Tailwind classes op geanimeerde elementen
## Done =
- Geen hydration warnings
- Werkt in React Strict Mode
- `ScrollTrigger.refresh()` na dynamische content
```
**De `## Why this stack` sectie is cruciaal.** Hiermee snapt de agent *waarom*
we deze keuzes maken — niet alleen *wat*. Resultaat: hij stelt op eigen
initiatief geen Framer Motion meer voor, want hij begrijpt dat we voor scroll
storytelling werken.
### Tips voor goede AGENTS.md
- **Concreet, niet vaag.** "Gebruik clean code" werkt niet. "useGSAP alleen, geen useEffect" wel.
- **Versie-pinning** voor libraries die snel veranderen.
- **Definitie van klaar** — checkpoints die de agent zelf kan toetsen.
- **Anti-patterns expliciet noemen** — "Geen Framer Motion" voorkomt veel discussie.
---
## 5. `opencode.json` — Config & Permissies
### Locaties
| Pad | Scope |
|-----|-------|
| `./opencode.json` | Per project |
| `~/.config/opencode/opencode.json` | Globaal |
### Basis voorbeeld
```json
{
"$schema": "https://opencode.ai/config.json",
"model": "openai/gpt-4o-mini"
}
```
Model formaat: `provider/model-id`. Voorbeelden:
- `openai/gpt-4o-mini`
- `openai/gpt-4o`
- `anthropic/claude-sonnet-4`
- `groq/llama-3.3-70b-versatile`
### Permissies
```json
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"rm *": "deny"
},
"edit": {
"*": "deny",
"app/**/*.tsx": "allow",
"components/**": "allow"
}
}
}
```
Drie levels: `allow`, `ask`, `deny`. Glob patterns voor bash commands en file paths.
### Plugin syntax (npm)
```json
{
"plugin": [
"@anthropic/some-plugin@1.0.0"
]
}
```
OpenCode installeert plugins automatisch via Bun in `~/.cache/opencode/node_modules/` bij het opstarten.
### MCP servers (optioneel)
```json
{
"mcp": {
"context7": {
"type": "local",
"command": "npx",
"args": ["-y", "@upstash/context7-mcp"]
}
}
}
```
Voor up-to-date library docs binnen je AI-context. Niet vereist voor deze les.
---
## 6. Plugins & `opencode-worktree`
### Wat is `opencode-worktree`?
Plugin van **kdcokenny** (community maker, ook achter `ocx` en `opencode-workspace`).
**Wat doet het?**
Geeft de agent twee nieuwe tools:
- `worktree_create` — maakt nieuwe branch + worktree-folder
- `worktree_delete` — commit changes + cleanup
**Worktree-locatie:**
`~/.local/share/opencode/worktree/<project-id>/<branch>/`
### Installatie via `ocx`
```bash
# Eenmalig: ocx installeren
curl -fsSL https://kdco.dev/ocx/install.sh | sh
# Plugin toevoegen
ocx add kdco/worktree --from https://registry.kdco.dev
```
Restart OpenCode na install.
### Verschil Desktop vs TUI
| Actie | TUI | Desktop |
|-------|-----|---------|
| `worktree_create` aanroepen | ✅ | ✅ |
| `worktree_delete` aanroepen | ✅ | ✅ |
| **Auto nieuw terminal venster** | ✅ | ❌ |
| Nieuwe context openen | Auto | Handmatig (Sessions sidebar) |
In Desktop maakt de plugin de worktree, daarna open je hem zelf in een nieuwe Sessions tab.
### Workflow in Desktop
1. In je hoofd-Session: `Maak een worktree voor feature-hero.`
2. Plugin maakt worktree-folder
3. Klik **+ New Session** in sidebar
4. **Open Folder** → navigate naar de worktree-folder
5. Nu heb je 2 sessies parallel in sidebar — main + feature-hero
6. Klik tussen sessies om te wisselen
### Handmatig alternatief (zonder plugin)
```bash
git worktree add ../mijn-repo-hero -b feature-hero
```
Dan handmatig nieuwe Session openen op die folder.
### Best practices
- Eén opencode-instance per worktree-directory (gouden regel)
- Niet wisselen tussen sessies van verschillende worktrees binnen één session-context (cwd-bug)
- Branch name = folder name (makkelijker zoeken in `git worktree list`)
- Cleanup na merge — niet stapelen
---
## 7. De scroll-animatie stack
### Next.js 16 (mei 2026)
Uitgekomen oktober 2025. **Breaking changes ten opzichte van 15:**
- **Async API's verplicht:** `cookies()`, `headers()`, `params`, `searchParams` zijn nu allemaal async. Altijd `await`:
```tsx
// app/products/[id]/page.tsx
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params; // VERPLICHT in 16
return <div>{id}</div>;
}
```
- **Turbopack is default** voor `dev` en `build`. Webpack alleen via opt-in.
- **`middleware.ts` → `proxy.ts`** met nieuwe Node.js runtime.
- **`revalidateTag` vereist 2e argument** (cacheLife profile).
- **Node.js 20.9+** vereist (18 is dropped).
### Waarom GSAP + Lenis?
Dit is **dé** stack voor scroll storytelling op pro-niveau. Niet "een" optie — de standaard.
**Wie gebruikt dit?**
- **Apple** — product pages met scroll-revealed content
- **Stripe** — homepage en product pages
- **OpenAI** marketing pages
- **Awwwards / FWA winnaars** — vrijwel altijd GSAP
- Pro studios: **Active Theory**, **Locomotive**, **Resn**, **Darkroom Engineering** (makers van Lenis)
**Waarom niet Framer Motion?**
- Framer Motion is uitstekend voor **app UI** — modals, page transitions, micro-interacties
- Maar voor **scroll storytelling** (jouw eindopdracht): GSAP heeft betere timing-precisie en GPU-optimalisaties
- Daarom: Framer Motion voor app-werk, GSAP voor scroll-werk
**Andere voordelen:**
- **GSAP sinds januari 2025: 100% gratis** onder de "no charge" license — incl. ScrollTrigger, SplitText, MorphSVG (vroeger premium)
- **Lenis** integreert naadloos met ScrollTrigger via één RAF sync
- Beide zijn **populair op v0 en Cursor** — AI's kennen de patterns goed
Schrijf dit op in je `AGENTS.md` (sectie `## Why this stack`). Dan kiest je AI agent dezelfde keuzes om dezelfde redenen.
### Packages
```bash
npm install gsap @gsap/react lenis
```
**Belangrijk:**
- Pakket heet **`lenis`** (niet meer `@studio-freight/lenis`)
- `@gsap/react` geeft je de officiele `useGSAP` hook
### De `useGSAP` hook
Drop-in vervanger voor `useEffect`/`useLayoutEffect` voor GSAP code. Doet automatisch cleanup via `gsap.context()`. Werkt veilig met React Strict Mode en SSR.
```tsx
"use client";
import { useRef } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(useGSAP, ScrollTrigger);
export default function FadeIn() {
const ref = useRef<HTMLDivElement>(null);
useGSAP(() => {
gsap.from(".fade-item", {
opacity: 0,
y: 60,
duration: 1,
stagger: 0.15,
scrollTrigger: {
trigger: ref.current,
start: "top 80%",
},
});
}, { scope: ref });
return (
<section ref={ref}>
<h2 className="fade-item text-5xl font-bold">Hello scroll</h2>
<p className="fade-item">Ik fade in.</p>
</section>
);
}
```
### Lenis sync met ScrollTrigger
Zonder sync lopen GSAP en Lenis hun eigen requestAnimationFrame — animaties haperen. Officieel patroon: `autoRaf: false` op Lenis, GSAP's ticker drijft Lenis aan.
```tsx
// components/SmoothScroll.tsx
"use client";
import { ReactLenis, type LenisRef } from "lenis/react";
import { useEffect, useRef } from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
export default function SmoothScroll({ children }: { children: React.ReactNode }) {
const lenisRef = useRef<LenisRef>(null);
useEffect(() => {
function update(time: number) {
lenisRef.current?.lenis?.raf(time * 1000);
}
gsap.ticker.add(update);
gsap.ticker.lagSmoothing(0);
return () => gsap.ticker.remove(update);
}, []);
return (
<ReactLenis root ref={lenisRef} options={{ autoRaf: false, lerp: 0.1 }}>
{children}
</ReactLenis>
);
}
```
In `app/layout.tsx`:
```tsx
import SmoothScroll from "@/components/SmoothScroll";
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="nl">
<body>
<SmoothScroll>{children}</SmoothScroll>
</body>
</html>
);
}
```
---
## 8. Project setup van A tot Z
### Stap 1 — Next.js 16 project aanmaken
```bash
npx create-next-app@latest scroll-site \
--typescript --tailwind --app --eslint --no-src-dir --turbopack
cd scroll-site
```
### Stap 2 — Animation dependencies
```bash
npm install gsap @gsap/react lenis
```
### Stap 3 — Git init + first commit
```bash
git init
git add .
git commit -m "init: next 16 + gsap + lenis"
```
### Stap 4 — `AGENTS.md` toevoegen
Plak het voorbeeld uit sectie 4 in `AGENTS.md` in root. Pas aan op jouw project.
### Stap 5 — `opencode.json` toevoegen
```json
{
"$schema": "https://opencode.ai/config.json",
"model": "openai/gpt-4o-mini",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny"
}
}
}
```
### Stap 6 — OpenCode Desktop starten
Open OpenCode Desktop → File → Open Folder → `scroll-site`.
In chat: `/init` om je AGENTS.md te valideren.
### Stap 7 — SmoothScroll wrapper bouwen
Vraag in chat:
> Bouw een SmoothScroll wrapper component volgens onze AGENTS.md. Plaats hem in `components/SmoothScroll.tsx` en wrap children in `app/layout.tsx`.
Plan-mode → review → Tab → Build-mode.
### Stap 8 — Eerste worktree
> Maak een worktree voor feature-hero en bouw daar een hero-sectie met een SplitText-reveal op scroll.
Plugin maakt worktree → open nieuwe Sessions tab op die folder → agent bouwt.
---
## 9. Workflow patterns
### Pattern 1 — Plan eerst, dan Build
Begin altijd in **plan-mode**. Laat de agent uitleggen wat het van plan is. Geef feedback. Pas dan Tab → build.
### Pattern 2 — Eén worktree per feature
Werk niet alles in main. Een feature = een worktree = een branch. Makkelijk parallel + makkelijk reviewen via PR.
### Pattern 3 — `AGENTS.md` evolueert
Loop je tegen iets aan dat steeds verkeerd gaat? Voeg toe aan AGENTS.md. Het is een levend document.
### Pattern 4 — `@explore` voor verkenning
Nieuwe codebase of vergeten waar iets staat? `@explore` eerst, dan pas hoofd-agent inzetten. Spaart tokens en geeft jou betere context.
### Pattern 5 — Permissions matchen je risico
Beginnersproject: `bash.*` op `ask`. Productie-werk: alleen specifieke folders editable. Schrijf permissions naar het werk dat je doet.
### Pattern 6 — Sessions sidebar = jouw parallel werk
Eén Session = orchestrator (in main). Worktrees met aparte Sessions = workers. Orchestrator stuurt, workers bouwen. Klik tussen tabs.
---
## 10. Bronnen
### OpenCode officieel
- Hoofdsite: https://opencode.ai
- Download (Desktop): https://opencode.ai/download
- Docs: https://opencode.ai/docs/
- Rules (`AGENTS.md`): https://opencode.ai/docs/rules/
- Config: https://opencode.ai/docs/config/
- Plugins: https://opencode.ai/docs/plugins/
- Agents (sub-agents): https://opencode.ai/docs/agents/
- Modes: https://opencode.ai/docs/modes/
- Commands: https://opencode.ai/docs/commands/
- Permissions: https://opencode.ai/docs/permissions/
- GitHub: https://github.com/sst/opencode
- DeepWiki Desktop apps: https://deepwiki.com/sst/opencode/6.7-desktop-applications
### Plugin ecosystem
- `opencode-worktree`: https://github.com/kdcokenny/opencode-worktree
- `ocx` extension manager: https://github.com/kdcokenny/ocx
- `opencode-workspace` (uitgebreidere variant): https://github.com/kdcokenny/opencode-workspace
### Next.js 16
- Blog post: https://nextjs.org/blog/next-16
- Upgrade guide: https://nextjs.org/docs/app/guides/upgrading/version-16
- create-next-app CLI: https://nextjs.org/docs/app/api-reference/cli/create-next-app
### GSAP
- Docs v3: https://gsap.com/docs/v3/
- React guide (`useGSAP`): https://gsap.com/resources/React/
- License (sinds 2025 gratis): https://gsap.com/standard-license
- ScrollTrigger: https://gsap.com/docs/v3/Plugins/ScrollTrigger/
- SplitText: https://gsap.com/docs/v3/Plugins/SplitText/
### Lenis
- GitHub: https://github.com/darkroomengineering/lenis
- React README: https://github.com/darkroomengineering/lenis/blob/main/packages/react/README.md
- Homepage: https://lenis.darkroom.engineering/
### Combinaties / patterns
- GSAP forum: Next 15/16 best practices: https://gsap.com/community/forums/topic/43831-what-are-the-best-practices-for-using-gsap-with-next-15-clientserver-components/
- Tutorial: Next.js + Lenis + GSAP: https://devdreaming.com/blogs/nextjs-smooth-scrolling-with-lenis-gsap
### Volgende les preview
Les 3: **Introductie Cursor**. De commerciele tegenhanger van OpenCode. Cursor rules vs AGENTS.md, Composer mode, Tab-completion, @-references. Wanneer kies je welke tool?