Claude Opus 5 Review: Is het nieuwe model van Anthropic de moeite waard?
Olivia Carter
Laatst bijgewerkt op 29 juli 2026
Claude Opus 5 Review: Is het nieuwe model van Anthropic de moeite waard?
Feiten gecontroleerd op 28 juli 2026.
Kort oordeel: Deze beoordeling van de Claude Opus 5 laat zien dat dit een aantrekkelijk high-end model is voor programmeurs, complexe bedrijfsworkflows en kopers die prestaties op het randje van de mogelijkheden willen zonder altijd voor de Fable 5 te hoeven betalen. Anthropic rekent $5 per miljoen invoertokens en $25 per miljoen uitvoertokens, terwijl het model een contextvenster van 1 miljoen tokens en maximaal 128.000 uitvoertokens ondersteunt in de synchrone Messages API. Het is niet automatisch de beste keuze voor eenvoudige chats, korte samenvattingen of verzoeken met een hoog volume en lage waarde.
Het sterkste argument is eerder praktisch dan theatraal: Opus 5 combineert ruime ruimte voor serieuze redeneringen met een beter beheersbare kostenstructuur dan het topsegment van Anthropic. In onze enige debugging-test vond het de exacte bug met prefix-matching, stelde het de kleinste patch voor, voegde het een gerichte regressietest toe en gaf het een verificatiecommando dat lokaal slaagde. Dat is nuttig bewijs voor deze taak – geen bewijs dat het model elke programmeertaak zal winnen.
Geschikt voor: codeermedewerkers, analyse van lange contexten, bedrijfsautomatisering en teams waarvan de kostbare mislukkingen een premiummodel rechtvaardigen. Sla dit over als: snelheid en kosten per eenheid zijn belangrijker dan de kwaliteit van de laatste redenering.
De Claude Opus 5 is het hoogwaardige model van Anthropic voor dagelijks gebruik, bedoeld voor complexe agentische codering en zakelijke toepassingen. Anthropic heeft dit op 24 juli 2026 bekendgemaakt, waarbij het werd omschreven als doordacht, proactief en efficiënter dan andere modellen. Het verving Claude Opus 4.8, werd het standaardmodel op de Claude Max en groeide uit tot het krachtigste model dat beschikbaar was op de Claude Pro.
Anthropic kondigde op 24 juli 2026 Claude Opus 5 aan en liet weten dat het product diezelfde dag nog verkrijgbaar was.
De productpresentatie is ongebruikelijk voor een Opus-release: dit model wordt niet uitsluitend gepresenteerd als een model met maximale intelligentie. Anthropic wil dat het dagelijks wordt gebruikt, met een aanpasbare inspanningsgraad en een gematigd latentieprofiel. Dat maakt het gemakkelijker te rechtvaardigen voor langlopende agents en veeleisende productietaken, terwijl eenvoudigere workloads nog steeds naar een sneller, goedkoper model kunnen worden doorgestuurd.
De toegang hangt af van de manier waarop je er gebruik van maakt. Particuliere gebruikers hebben toegang tot Opus 5 via in aanmerking komende Claude-abonnementen; ontwikkelaars kunnen er gebruik van maken via de Claude-API en ondersteunde cloudplatforms. GlobalGPT heeft ook een eigen productpagina. Lezers die de abonnementsniveaus van Anthropic willen vergelijken, kunnen gebruikmaken van de Vergelijking van de abonnementen Claude Free, Pro en Max voordat u een factureringsmethode kiest.
Claude Opus 5: Prijs, API en belangrijkste specificaties
De officiële Claude API-prijs is $5 per miljoen ingevoerde tokens en $25 per miljoen uitgegeven tokens. Dit zijn de basistarieven voor de API, niet de prijs van een Claude-abonnement voor consumenten of een platformabonnement van een derde partij. Voor het cachen van prompts en batchverwerking gelden aparte tarieven, dus vergelijk het volledige verzoekpatroon in plaats van alleen de vermelde inputprijs te vermenigvuldigen.
Veld
Claude Opus 5
Wat dit betekent
Claude API-ID
claude-opus-5
Gebruik precies deze modelwaarde in officiële Claude API-verzoeken.
Basisinkoopprijs
$5 / MTok
Standaardtarief per invoertoken vóór caching of batchkortingen.
Basisverkoopprijs
$25 / MTok
Agenten die veel output genereren, kunnen al snel duur worden.
Contextvenster
1 miljoen tokens
Geschikt voor grote archieven en documentverzamelingen, afhankelijk van de kwaliteit van de zoekopdrachten en de zoekstrategie.
Maximaal vermogen
128K lopers
Dit geldt voor de synchrone Messages API; voor Message Batches geldt een apart bètaprogramma tot 300.000.
Betrouwbare kennisgrens
mei 2026
Volgens de huidige normen is dit een recente ontwikkeling, maar het is geen vervanging voor het ophalen van gegevens ter plaatse.
Vergelijkende latentie
Matig
Dit is niet het snelste model van Anthropic; de latentie varieert nog steeds afhankelijk van de inspanning, de tools en de werklast.
Het Claude-platform identificeert claude-opus-5 als de huidige Opus 5 API-ID en alias.Het Claude-platform noteert Opus 5 op $5/$25 per miljoen input-/output-tokens, met een contextvenster van 1 miljoen tokens, een maximale output van 128.000 tokens en afsluitingsdata in mei 2026.Het Claude-platform vermeldt een contextvenster van 1M, een maximale output van 128k en een afsluitdatum in mei 2026.
Wat de toegang voor consumenten betreft, Anthropic-lijsten Claude Pro bij $20 per maand of $17 per maand wanneer $200 jaarlijks wordt gefactureerd; Claude Max begint bij $100 per maand. Volgens Anthropic is Opus 5 het krachtigste model op Pro en de standaardinstelling op Max, maar de inclusies van het abonnement en de productfuncties staan los van het gemeten API-gebruik.
Als je een uitgebreider kostenoverzicht nodig hebt, dan is de Claude AI-abonnementen en prijsgids voor API’s maakt een onderscheid tussen consumentenabonnementen, API-facturering en gebruikslimieten. Dat onderscheid is belangrijk: “inbegrepen in een abonnement” betekent niet dat je onbeperkt API-aanroepen kunt doen, en een API-tarief zegt niets over hoeveel toegang je krijgt tot de consumentenchat.
Claude Opus 5 Benchmarkresultaten
Belangrijke grens: de onderstaande cijfers zijn door Anthropic gepubliceerde benchmarks, geen onafhankelijke metingen die speciaal voor deze beoordeling zijn uitgevoerd. Ze zijn nuttig om inzicht te krijgen in de beoogde prestatie- en kostenpositie van Anthropic, maar ze garanderen niet dat u hetzelfde resultaat zult behalen met uw eigen prompts, tools, repository of latentiebudget.
Evaluatie
De door Anthropic gepubliceerde bewering
Hoe moet je dit lezen?
Frontier-Bench v0.1
Opus 5 presteert meer dan twee keer zo goed als Opus 4.8, tegen lagere kosten per taak.
Een algemeen signaal voor de prestaties van agenten, geen universele verdubbeling van de prestaties.
CursorBench 3.2
Bij maximale inzet ligt Opus 5 binnen 0,51 TP40T van de topscore van Fable 5, tegen de helft van de kosten per taak.
Sterke economische resultaten voor de coderingsagent binnen de geteste inspanningsinstelling van Anthropic.
Zapier AutomationBench
Ongeveer 1,5 keer zo hoog als het op één na beste slagingspercentage, bij dezelfde kosten per taak.
Veelbelovend voor end-to-end bedrijfsautomatisering; het ontwerpen van workflows blijft belangrijk.
OSWorld 2.0
Overtreft het beste resultaat van Fable 5 tegen iets meer dan een derde van de kosten.
Dit wijst in deze benchmark op een aantrekkelijke efficiëntie bij het computergebruik.
Volgens Anthropic komt Opus 5 tot op 0,5% van de hoogste CursorBench 3.2-score van Fable 5, tegen de helft van de kosten per taak.Anthropic meldt een 1,5-voudig voordeel qua slagingspercentage op Zapier AutomationBench en een kostenvoordeel op OSWorld 2.0.
De inspanning maakt deel uit van het resultaat. Anthropic geeft aan dat Opus 5 standaard op een hoge inspanning is ingesteld in de Claude-API en de Claude-code, terwijl bij de vergelijkingen ook de instellingen ‘high’, ‘xhigh’ of ‘max’ worden gebruikt. Een hogere inspanning kan het succes bij moeilijke taken verbeteren, maar leidt tegelijkertijd tot een toename van het aantal tokens, de latentie of beide. De benchmarkkosten per taak zijn daarom informatiever dan alleen de prijs per token – maar geen van beide maatstaven vervangt een pilot op uw eigen werklast.
Hoe we de Claude Opus 5 hebben getest
We hebben één compacte foutopsporingsopdracht uitgevoerd om de hoofdoorzaak te achterhalen in een CommonJS-testomgeving met drie bestanden. De opdracht vereiste dat het model de hoofdoorzaak identificeerde vóór het aanbrengen van wijzigingen, de kleinst mogelijke patch voorstelde, een gerichte regressietest toevoegde, niet-gerelateerde wijzigingen vermeed en het exacte verificatiecommando opgaf.
Vervolgens hebben we de patch zelfstandig gecontroleerd, in plaats van het antwoord als juist te beschouwen alleen omdat het zo overtuigend klonk. Het `local`-commando was node --test test/account-summary.test.cjs. Vóór de correctie leverde de testsuite één geslaagde test en één mislukte test op. Na het toepassen van de patch voor exacte gelijkheid leverde deze twee geslaagde tests en geen mislukte tests op.
Deze methode geeft ons nuttige informatie over één bepaald debugging-proces: diagnose, discipline bij het aanbrengen van patches, de kwaliteit van regressietests en verifieerbaarheid. De methode meet echter geen algemene leiderschapskwaliteiten op het gebied van coderen, de betrouwbaarheid van agenten op de lange termijn, snelheid of prestaties in verschillende programmeertalen.
Claude Opus 5 Praktische beoordeling
Foutopsporing op basis van de onderliggende oorzaak: correct, minimaal en verifieerbaar
In onze test heeft de Claude Opus 5 de storing correct geïsoleerd tot normalizedQuery.startsWith(account.id.toLowerCase()). Met de zoekopdracht ACCT-10, de controle van het voorvoegsel leverde een treffer op acct-1 ten eerste, dus Array.prototype.find heeft het verkeerde account geretourneerd voordat het exacte ID werd bereikt.
De voorgestelde oplossing zorgde ervoor dat het vergelijken van voorvoegsels voortaan op exacte overeenstemming werd gebaseerd en voegde één regressiegeval toe voor de aangevulde, gemengde hoofdletters en kleine letters ACCT-10 input. Er werd geen code herschreven die hier geen verband mee hield. Die terughoudendheid is van belang in echte repositories, waar een te uitgebreide “opruimactie” meer revisiewerk kan opleveren dan de oorspronkelijke bug.
Het sterkste onderdeel was de volledige cyclus: de hoofdoorzaak benoemen, uitleggen waarom de bestaande test deze over het hoofd heeft gezien, de kleinste wijziging aanbrengen, de juiste regressietest toevoegen en het commando vermelden om dit te controleren. Het resultaat sluit aan bij de positionering van Opus 5 als ’coding-agent’, maar het blijft bij één fixture. Zie voor een uitgebreidere inleiding tot de workflow hoe Claude AI gebruiken voor codering.
Volledige T1–T4-opgaven, antwoorden en kopieerbare code
T1: Foutopsporing naar de onderliggende oorzaak
Goedgekeurd — de fout in de prefix-match ontdekt, de kleinste patch voorgesteld en een gerichte regressietest toegevoegd.
Het probleem werd vastgesteld als een niet-overeenkomend voorvoegsel; er werd uitgelegd waarom de oude test dit over het hoofd had gezien; er werd een regressietest voorgesteld waarbij exact overeenkomen plus één werd getest.
Bekijk de volledige T1-opdracht en het antwoord
Volledige opdracht
Je bent bezig met het opsporen van fouten in een opzettelijk kleine CommonJS-fixture. Werk uitsluitend op basis van de drie onderstaande bestanden en de aangegeven manier om de fout te reproduceren.
Vereisten:
1. Geef de hoofdoorzaak aan voordat je een wijziging voorstelt.
2. Stel de kleinst mogelijke patch voor die de bug verhelpt.
3. Voeg één gerichte regressietest toe die vóór de fix faalt en erna slaagt.
4. Geef het exacte verificatiecommando op dat vanuit de root van de fixture moet worden uitgevoerd.
5. Herschrijf geen code die geen verband houdt met het probleem. Hernoem geen bestanden, voeg geen afhankelijkheden toe en wijzig de openbare API niet.
6. Geef precies deze secties in deze volgorde weer: `ROOT CAUSE`, `PATCH`, `VERIFICATION`, `LIMITATIONS`.
7. Geef in `PATCH` één unified diff in een omkaderd `diff`-blok. Geef in `VERIFICATION` één commando in een omkaderd `text`-blok.
Reproductie: `summarizeAccount(accounts, ' ACCT-10 ')` zou `{ id: 'acct-10', name: 'Nimbus', seats: 24 }` moeten retourneren, maar het retourneert het `acct-1`-account.
Bestand: `src/find-account.cjs`
```js
function findAccount(accounts, query) {
const normalizedQuery = query.trim().toLowerCase();
return accounts.find((account) =>
normalizedQuery.startsWith(account.id.toLowerCase()),
);
}
module.exports = { findAccount };
```
Bestand: `src/account-summary.cjs`
```js
const { findAccount } = require('./find-account.cjs');
function summarizeAccount(accounts, requestedId) {
const account = findAccount(accounts, requestedId);
if (!account) return null;
return { id: account.id, name: account.name, seats: account.seats };
}
module.exports = { summarizeAccount };
```
Bestand: `test/account-summary.test.cjs`
```js
const test = require('node:test');
const assert = require('node:assert/strict');
const { summarizeAccount } = require('../src/account-summary.cjs');
const accounts = [
{ id: 'acct-1', name: 'Atlas', seats: 5 },
{ id: 'acct-10', name: 'Nimbus', seats: 24 },
];
test('geeft een samenvatting van een exacte account-ID', () => {
assert.deepEqual(summarizeAccount(accounts, 'acct-1'), {
id: 'acct-1',
name: 'Atlas',
seats: 5,
});
});
```
Claude Opus 5
HOOFDORZAAK
findAccount zoekt op voorvoegsel, niet op exacte overeenkomst:
Array.prototype.find geeft het eerste element terug dat aan het predikaat voldoet. Voor ‘ACCT-10‘ is de genormaliseerde zoekopdracht ‘acct-10’, en de ID van de eerste rekening ‘acct-1’ is een voorvoegsel daarvan, dus startsWith is waar en acct-1 beëindigt de zoekopdracht voordat acct-10 überhaupt wordt getest. De normalisatie via `trim().toLowerCase()` is correct — witruimte en hoofdletters/kleine letters vormen geen probleem. `summarizeAccount` is een doorgeeffunctie en is niet de oorzaak van het probleem. De huidige test kan dit niet opsporen: ‘acct-1’ is een voorvoegsel van zichzelf en vormt het eerste element, waardoor bij die invoer geen onderscheid kan worden gemaakt tussen voorvoegselvergelijking en exacte vergelijking.
PATCH
diff
1--- a/src/find-account.cjs2+++ b/src/find-account.cjs3@@ -1,8 +1,8 @@4 function findAccount(accounts, query) {5 const normalizedQuery = query.trim().toLowerCase();6- return accounts.find((account) =>7- normalizedQuery.startsWith(account.id.toLowerCase()),8- );9+ return accounts.find(10+ (account) => account.id.toLowerCase() === normalizedQuery,11+ );12 }1314 module.exports = { findAccount };15--- a/test/account-summary.test.cjs16+++ b/test/account-summary.test.cjs17@@ -14,3 +14,11 @@18 test('summarizes an exact account ID', () => {19 seats: 5,20 });21 });22+23+test('matches the full ID rather than a prefix, with padding and mixed case', () => {24+ assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {25+ id: 'acct-10',26+ name: 'Nimbus',27+ seats: 24,28+ });29+});
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
function findAccount(accounts, query) {
const normalizedQuery = query.trim().toLowerCase();
- return accounts.find((account) =>
- normalizedQuery.startsWith(account.id.toLowerCase()),
- );
+ return accounts.find(
+ (account) => account.id.toLowerCase() === normalizedQuery,
+ );
}
module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
test('vat een exacte account-ID samen', () => {
seats: 5,
});
});
+
+test('komt overeen met de volledige ID in plaats van een voorvoegsel, inclusief opvulling en gemengde hoofdletters en kleine letters', () => {
+ assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+ id: 'acct-10',
+ name: 'Nimbus',
+ seats: 24,
+ });
+});
Vóór de correctie mislukt de nieuwe test met het object acct-1 / Atlas / 5; na de correctie slaagt de test.
CONTROLE
tekst
1node --test test/account-summary.test.cjs
node --test test/account-summary.test.cjs
BEPERKINGEN
• Omvang: één operator is gewijzigd. Er zijn geen naamswijzigingen, geen nieuwe afhankelijkheden, en de signaturen en retourwaarden van `findAccount` en `summarizeAccount` zijn ongewijzigd. • Reeds bestaand gedrag dat ongewijzigd blijft (valt buiten het bereik van deze bug): • Een requestedId die geen tekenreeks is (null, een getal) leidt nog steeds tot een uitzondering bij .trim(). • Account-ID’s zelf worden niet ingekort, dus een opgeslagen ‘acct-10’ zal nog steeds niet overeenkomen — alleen de zoekopdracht wordt genormaliseerd. • Casing maakt gebruik van de standaardfunctie toLowerCase(); er vindt geen Unicode-normalisatie of locaalafhankelijke aanpassing plaats. • Dubbele ID’s worden nog steeds gekoppeld aan de eerste overeenkomst, en de opzoekactie blijft O(n). • Testdekking: de enkele regressietest richt zich uitsluitend op de gemelde reproductie. Het niet-gevonden (nul)pad en de onjuist opgebouwde invoer blijven ongetest.
ROOT CAUSE
findAccount matches by prefix, not by equality:
```js
normalizedQuery.startsWith(account.id.toLowerCase())
```
Array.prototype.find returns the first element satisfying the predicate. For ' ACCT-10 ' the normalized query is 'acct-10', and the first account's ID 'acct-1' is a prefix of it, so startsWith is true and acct-1 short-circuits the search before acct-10 is ever tested.
The trim().toLowerCase() normalization is correct — whitespace and casing are not the problem. summarizeAccount is a pass-through and is not at fault.
The existing test cannot catch this: 'acct-1' is a prefix of itself and is the first element, so prefix matching and exact matching are indistinguishable for that input.
PATCH
```diff
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
function findAccount(accounts, query) {
const normalizedQuery = query.trim().toLowerCase();
- return accounts.find((account) =>
- normalizedQuery.startsWith(account.id.toLowerCase()),
- );
+ return accounts.find(
+ (account) => account.id.toLowerCase() === normalizedQuery,
+ );
}
module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
test('summarizes an exact account ID', () => {
seats: 5,
});
});
+
+test('matches the full ID rather than a prefix, with padding and mixed case', () => {
+ assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+ id: 'acct-10',
+ name: 'Nimbus',
+ seats: 24,
+ });
+});
```
Before the fix the new test fails with the acct-1 / Atlas / 5 object; after the fix it passes.
VERIFICATION
```text
node --test test/account-summary.test.cjs
```
LIMITATIONS
• Scope: one operator changed. No renames, no new dependencies, and findAccount / summarizeAccount signatures and return shapes are unchanged.
• Pre-existing behavior left alone (out of scope for this bug):
• A non-string requestedId (null, a number) still throws on .trim().
• Account IDs themselves are not trimmed, so a stored ' acct-10' still will not match — only the query is normalized.
• Casing uses plain toLowerCase(); no Unicode normalization or locale-aware folding.
• Duplicate IDs still resolve to the first match, and lookup remains O(n).
• Test coverage: the single regression test targets exactly the reported reproduction. The not-found (null) path and malformed input remain untested.
T2: Analyse van de status van het account
Gedeeltelijk — de belangrijkste statistieken zijn berekend en er is een prioriteitenlijst voor acties opgesteld, maar het vastgelegde antwoord eindigde zonder de gevraagde ‘Recheck’-markering.
Berekende $34.800 MRR met risico (94,31%); E-505 geëscaleerd en vervolgacties gerangschikt; Antwoord beëindigd zonder de gevraagde Recheck-markering.
Bekijk de volledige T2-opdracht en het antwoord
Volledige opdracht
Analyseer het meegeleverde bestand `account-health.csv` als een gesloten dataset. Gebruik geen externe gegevens en verzin geen ontbrekende waarden.
Risicoregels (beoordeel elke regel afzonderlijk):
- `inactiviteit`: `days_since_login >= 30`
- `payment`: `failed_payments >= 2`
- `low_utilization`: `seats_used / seats_purchased = 80` terwijl het account `at-risk` is.
- `weak_health_without_risk`: `health_score = 9` en `open_tickets >= 3`.
Vereisten:
1. Bereken voor elk account de geactiveerde risico-indicatoren en tegenstrijdigheidsindicatoren.
2. Rapporteer de totalen van de dataset voor accounts, MRR, risicovolle accounts, risicovolle MRR, te escaleren accounts, rijen met tegenstrijdigheden, aangeschafte licenties en gebruikte licenties.
3. Stel een actietabel op met precies vijf kolommen: `Account | Risico-triggers | Tegenstrijdigheden | Prioriteit | Aanbevolen actie`.
4. Plaats direct berekende waarden onder de kop `Gemeten feiten` en beoordelingen onder de kop `Conclusie`.
5. Geef onder `Opnieuw controleren` voldoende rekenwerk weer om elk totaal en elke drempelwaarde onafhankelijk te kunnen controleren, inclusief het geval waarbij de waarde gelijk is aan 0,50.
6. Pas de regels niet stilzwijgend aan of herinterpreteer ze niet. Als een signaal contra-intuïtief lijkt, registreer het dan als een tegenstrijdigheid in plaats van de classificatie ervan te wijzigen.
`account-health.csv`:
```csv
account_id,account_name,plan,mrr_usd,days_since_login,failed_payments,seats_purchased,seats_used,health_score,nps,open_tickets
A-101,Aster,Enterprise,12000,45,0,100,82,92,9,1
B-202,Beacon,Pro,4200,4,2,20,18,70,7,0
C-303,Cinder,Pro,3600,12,0,20,8,65,10,4
D-404,Dahlia,Starter,900,5,0,5,4,42,6,0
E-505,Ember,Enterprise,15000,65,3,200,70,35,3,6
F-606,Fjord,Starter,1200,29,1,4,2,85,9,3
```
Claude Opus 5
Gemeasde feiten
Bron: account-health.csv, 6 rijen, behandeld als afgesloten. Er zijn geen waarden ingevuld.
Beoordeling van regels per account
Account dagen ≥ 30 mislukt ≥ 2 util < 0,50 Aantal risico’s Status A-101 Aster ✅ 45 ❌ 0 ❌ 0,82 1 risicogroep B-202 Baken ❌ 4 ✅ 2 ❌ 0,90 1 risicogroep C-303 As ❌ 12 ❌ 0 ✅ 0,40 1 risicogroep D-404 Dahlia ❌ 5 ❌ 0 ❌ 0,80 0 geen risico E-505 Ember ✅ 65 ✅ 3 ✅ 0,35 3 risicogroep + escaleren F-606 Fjord ❌ 29 ❌ 1 ❌ 0,50 0 geen risico Waarschuwingsvlaggen per account Account sterke_gezondheid_met_risico zwakke_gezondheid_zonder_risico promotor_met_kaartjes A-101 Aster ✅ (92 ≥ 80, risicogroep) ❌ ❌ (NPS 9 ✓, tickets 1 ✗) B-202 Baken ❌ (70 < 80) ❌ (70 ≥ 50) ❌ (NPS 7) C-303 As ❌ (65 < 80) ❌ (65 ≥ 50) ✅ (NPS 10, tickets 4) D-404 Dahlia ❌ ✅ (42 < 50, geen risico) ❌ (NPS 6) E-505 Ember ❌ (35 < 80) ❌ (35 < 50, maar behoort tot de risicogroep) ❌ (NPS 3) F-606 Fjord ❌ (85 ≥ 80, maar geen risicogroep) ❌ (85 ≥ 50) ✅ (NPS 9, tickets 3) Totale cijfers van de dataset Metrisch Waarde Rekeningen 6 Totale MRR $36,900 Risicovolle rekeningen 4 (A-101, B-202, C-303, E-505) MRR met verhoogd risico $34.800 (94,31% van het totaal) Accounts escaleren 1 (E-505) Rijen met tegenstrijdigheden 4 (A-101, C-303, D-404, F-606) Waarschuwingen voor tegenstrijdigheden 4 (1 sterke_gezondheid_met_risico, 1 zwakke_gezondheid_zonder_risico, 2 promotor_met_kaartverkoop) Gekochte zitplaatsen 349 Gebruikte zitplaatsen 184 Conclusie De prioriteitsvolgorde en de aanbevolen acties hieronder zijn op mijn eigen inschatting gebaseerd en geen vaste regels. Bij mijn rangschikking geef ik eerst voorrang aan de status, vervolgens aan de MRR die risico loopt, en daarna aan signalen die op tegenstrijdigheden wijzen. Account Risicofactoren Tegenstrijdigheden Prioriteit Aanbevolen actie E-505 Ember inactiviteit, betaling, lage_benutting - P0 Alle drie de regels worden geactiveerd voor de grootste klant ($15.000 MRR). Behandel dit als actief verloop: herstel de betaalmethode en voer vervolgens een beoordeling door het management uit met betrekking tot de 130 ongebruikte licenties. A-101 Aster inactiviteit sterke_gezondheid_met_risico P1 $12.000 MRR met 45 dagen inactiviteit, ondanks een score van 92 en een gezond 82%-gebruik. Controleer of de inlogpauze het gevolg is van daadwerkelijke afhaking of een artefact in de tracking (SSO, uitsluitend API-gebruik) voordat u op basis van de score actie onderneemt. C-303 As lage_bezettingsgraad promotor_met_kaartjes P1 Promotor (nps 10) met 4 open tickets bij een bezettingsgraad van 40%. De ticketbelasting vormt waarschijnlijk de belemmering voor de invoering; maak de wachtrij leeg en zorg vervolgens voor de activering van de zitplaatsen. B-202 Baken betaling - P2 Duidelijk geval met één oorzaak: 2 mislukte betalingen, waarbij de laatste inlogdatum 4 dagen geleden was en er gebruik is gemaakt van 90%. Alleen opvolging van de facturering, geen actie van de klantenservice nodig. F-606 Fjord - promotor_met_kaartjes P3 Valt net binnen alle limieten (29 dagen, 1 mislukte betaling, precies 0,50 benuttingsgraad). Volgens de regels is er geen risico, maar nog één dag zonder activiteit of nog één mislukte betaling zorgt ervoor dat de situatie omslaat. Houd dit in de gaten en los de 3 tickets op. D-404 Dahlia - zwakke_gezondheid_zonder_risico P3 Score 42 zonder dat er een regel is geactiveerd en een bezettingsgraad van 80% op $900 MRR. Ofwel
Gemeten gegevens
Bron: account-health.csv, 6 rijen, behandeld als gesloten. Geen waarden geïmputeerd.
Regelbeoordeling per account
Account
dagen≥30
mislukt≥2
gebruik <0,50
Risicoscore
Status
A-101 Aster
✅ 45
❌ 0
❌ 0,82
1
risicovol
B-202 Beacon
❌ 4
✅ 2
❌ 0,90
1
risicovol
C-303 Cinder
❌ 12
❌ 0
✅ 0,40
1
risicovol
D-404 Dahlia
❌ 5
❌ 0
❌ 0,80
0
geen risico
E-505 Ember
✅ 65
✅ 3
✅ 0,35
3
risicovol + escaleren
F-606 Fjord
❌ 29
❌ 1
❌ 0,50
0
geen risico
Vlaggen voor tegenstrijdigheden per account
Account
sterke_status_met_risico
zwakke_status_zonder_risico
promotor_met_ticketbelasting
A-101 Aster
✅ (92 ≥ 80, risico)
❌
❌ (nps 9 ✓, tickets 1 ✗)
B-202 Beacon
❌ (70 < 80)
❌ (70 ≥ 50)
❌ (NPS 7)
C-303 Cinder
❌ (65 < 80)
❌ (65 ≥ 50)
✅ (NPS 10, tickets 4)
D-404 Dahlia
❌
✅ (42 < 50, geen risico)
❌ (nps 6)
E-505 Ember
❌ (35 < 80)
❌ (35 < 50, maar wel risico)
❌ (NPS 3)
F-606 Fjord
❌ (85 ≥ 80, maar geen risico)
❌ (85 ≥ 50)
✅ (NPS 9, tickets 3)
Totalen dataset
Metriek
Waarde
Accounts
6
Totale MRR
$36.900
Accounts met risico
4 (A-101, B-202, C-303, E-505)
MRR met risico
$34.800 (94,31% van het totaal)
Accounts escaleren
1 (E-505)
Rijen met tegenstrijdigheden
4 (A-101, C-303, D-404, F-606)
Vlaggen voor tegenstrijdigheden
4 (1 strong_health_with_risk, 1 weak_health_without_risk, 2 promoter_with_ticket_load)
Gekochte zitplaatsen
349
Gebruikte zitplaatsen
184
Conclusie
De onderstaande prioriteitsvolgorde en aanbevolen acties zijn beoordelingsbeslissingen, geen uitkomsten van regels. Mijn rangschikkingsgewichten geven eerst prioriteit aan de status, vervolgens aan de MRR in gevaar en daarna aan tegenstrijdigheidssignalen.
Account
Risico-triggers
Tegenstrijdigheden
Prioriteit
Aanbevolen actie
E-505 Ember
inactiviteit, betaling, low_utilization
—
P0
Alle drie de regels worden geactiveerd voor het grootste account ($15.000 MRR). Behandel dit als actieve churn: herstel de betaalmethode en voer vervolgens een uitvoerende beoordeling uit voor de 130 ongebruikte licenties.
A-101 Aster
inactiviteit
sterke_gezondheid_met_risico
P1
$12.000 MRR met 45 dagen inactiviteit ondanks een score van 92 en een gezond gebruik van 82%. Controleer of de inlogpauze duidt op daadwerkelijke afhaking of een artefact in de tracking (SSO, uitsluitend API-gebruik) alvorens actie te ondernemen op basis van de score.
C-303 Cinder
low_utilization
promoter_with_ticket_load
P1
Promotor (NPS 10) met 4 openstaande tickets bij een 40%-gebruik. De ticketbelasting is waarschijnlijk de belemmering voor acceptatie; ruim de wachtrij op en stimuleer vervolgens de activering van de licentie.
B-202 Beacon
betaling
—
P2
Duidelijk geval met één oorzaak: 2 mislukte betalingen met een inlogfrequentie van 4 dagen en een gebruik van 90%. Alleen opvolging van de facturering, geen actie van de klantenservice nodig.
F-606 Fjord
—
promoter_with_ticket_load
P3
Valt net binnen alle grenzen (29 dagen, 1 mislukte betaling, precies 0,50-gebruik). Volgens de regels geen risico, maar nog één dag inactiviteit of nog één mislukte betaling zorgt voor een ommekeer. Houd in de gaten en verwijder de 3 tickets.
D-404 Dahlia
—
weak_health_without_risk
P3
Score 42 zonder dat er een regel is geactiveerd en 80%-gebruik op $900 MRR. Ofwel
T3: Genereren van responsieve gebruikersinterfaces
Gedeeltelijk — leverde een uitgebreide, op zichzelf staande implementatie en zelfcontrole op, waarbij expliciet werd toegegeven dat de pagina werd geïnspecteerd in plaats van tijdens de uitvoering te worden weergegeven.
Een op zichzelf staand antwoord van 21.907 tekens opgesteld; Aandacht besteed aan desktop, mobiel, overflow en toegankelijkheid; Uitdrukkelijk vermeld dat de lay-out was gecontroleerd en niet tijdens de uitvoering werd weergegeven.
Bekijk de volledige T3-opdracht en het antwoord
Volledige opdracht
Maak een verzorgde interface voor productvergelijking in de vorm van één uitvoerbaar HTML-bestand, waarbij je uitsluitend de onderstaande productgegevens gebruikt.
Vereisten:
1. Lever precies één omkaderd `html`-codeblok in, gevolgd door een `SELF-CHECK`-sectie. Splits de HTML, CSS of JavaScript niet op in afzonderlijke bestanden.
2. Gebruik uitsluitend semantische HTML, ingebedde CSS en ingebedde "vanilla" JavaScript: geen externe frameworks, pakketten, lettertypen, afbeeldingen, netwerkverzoeken of bouwstappen.
3. Zorg voor drie via het toetsenbord toegankelijke tabbladen (`Overzicht`, `Prijzen`, `Limieten`) met de juiste `tablist`-, `tab`- en `tabpanel`-semantiek. ArrowLeft/ArrowRight moeten tabbladen verplaatsen en activeren; Home/End moeten naar het eerste/laatste tabblad springen en dit activeren. De focus moet zichtbaar blijven.
4. Het geselecteerde tabblad moet worden weergegeven door `aria-selected`, `tabindex` en het zichtbare paneel; inactieve panelen moeten worden verborgen.
5. Doel voor desktop: 1440px breed. Doel voor mobiel: 390px breed zonder horizontale pagina-overloop, zonder afgeknotte bedieningselementen, tikdoelen van minimaal 44px hoog en vergelijkingskaarten gestapeld in één kolom.
6. Neem een beknopte koptekst, een duidelijke aanbeveling, drie productkaarten en één compacte vergelijkingstabel op. Zorg voor een goed leesbaar contrast en vermijd decoratieve bewegingen.
7. Gebruik precies deze productgegevens en voeg geen beweringen toe:
- Atlas: `$19/mo`, `20 projecten`, `10 GB`, `E-mailondersteuning`, het meest geschikt voor zelfstandig werken.
- Beacon: `$49/maand`, `Onbeperkt aantal projecten`, `100 GB`, `Prioritaire ondersteuning`, beste keuze voor groeiende teams.
- Cove: `$99/maand`, `Onbeperkt aantal projecten`, `1 TB`, `Toegewijde ondersteuning`, het meest geschikt voor gereguleerde activiteiten.
8. Geef Beacon een zichtbaar label `Beste overall` zonder dat de andere kaarten eruitzien alsof ze zijn uitgeschakeld.
9. Vermeld in `SELF-CHECK` expliciet je controles op semantische tabbladen, toetsenbordgedrag, 1440px-lay-out, 390px-lay-out, horizontale overflow en externe afhankelijkheden. Beweer niet dat je daadwerkelijk een viewport hebt weergegeven, tenzij je dat ook daadwerkelijk hebt gedaan; maak onderscheid tussen code-inspectie en verificatie tijdens de uitvoering.
Productfixture (ook opgeslagen als `fixtures/T3-responsive-ui/product-data.json`):
```json
{
"products": [
{"name":"Atlas","price":"$19/mo","projects":"20 projects","storage":"10 GB","support":"E-mailondersteuning","bestFor":"solowerk"},
{"name":"Beacon","price":"$49/mo","projects":"Onbeperkt aantal projecten","storage":"100 GB","support":"Prioritaire ondersteuning","bestFor":"groeiende teams","badge":"Beste overall"},
{"name":"Cove","price":"$99/mo","projects":"Onbeperkt aantal projecten","opslag":"1 TB","ondersteuning":"Toegewijde ondersteuning","bestFor":"gereguleerde activiteiten"}
]
}
```
Alle onderstaande uitspraken zijn uitsluitend gebaseerd op code-inspectie. Ik heb geen browser geopend, geen viewport weergegeven, geen schermlezer gebruikt en geen toetsenbordcommando’s uitgevoerd, dus niets hiervan is tijdens de uitvoering geverifieerd. Wanneer een bewering afhankelijk is van het gedrag van de lay-outengine, vermeld ik dat. Semantische tabbladen — gecontroleerd, consistent Eén div[role="tablist"] met aria-label="Vergelijkingsweergaven van plannen" bevat drie button[type="button"][role="tab"]. Elk tabblad heeft een unieke id en een aria-controls die verwijst naar een section[role="tabpanel"]; elk paneel heeft een aria-labelledby die terugverwijst naar het bijbehorende tabblad. Ik heb alle drie de paren met de hand in kaart gebracht: tab-overview/panel-overview, tab-pricing/panel-pricing, tab-limits/panel-limits. Geen dubbele ID’s, geen losse verwijzingen. Panelen gebruiken `tabindex="0"`, zodat de inhoud van het paneel bereikbaar is na het tabblad. Toetsenbordgedrag — gecontroleerd, niet uitgevoerd Eén enkele keydown-listener op de tablist verwerkt de toetsen Pijl-rechts, Pijl-links, Home en End, roept event.preventDefault() alleen voor die vier toetsen aan en keert anders vroegtijdig terug. De pijltjestoetsen lopen aan beide uiteinden door. Omdat activate() zowel aria-selected/tabindex/hidden bijwerkt als de focus verplaatst, zorgen de pijltjestoetsen en de Home/End-toetsen in één stap voor verplaatsing en activering; dit is het patroon van automatische activering waar de vereiste om vraagt. Het doorlopen met Tab/Shift+Tab is gebaseerd op een variabele tabindex: precies één tab heeft tabindex="0", de rest -1, wat door activate() wordt bijgehouden. De zichtbaarheid van de focus wordt geregeld door een globale :focus-visible-regel met een omtrek van 3px en een offset van 2px; ik heb de standaardomtrek niet overschreven of verwijderd. Ik heb de toetsafhandeling nog niet in een echte browser getest. Reflectie in geselecteerde toestand — gecontroleerd activate() stelt alle drie de signalen in dezelfde lus in, zodat aria-selected="true", tabindex="0" en de afwezigheid van hidden niet uit elkaar kunnen raken. Inactieve panelen krijgen het hidden-attribuut, en [hidden] { display: none !important; } voorkomt dat de weergaveregels dit tenietdoen — die bescherming is belangrijk omdat de panelen display: grid-kindelementen bevatten. activate(currentIndex(), false) wordt bij het laden uitgevoerd om de status op basis van de opmaak te normaliseren zonder de focus te stelen. Als JavaScript niet wordt uitgevoerd, wordt de opmaak geleverd met ‘Overview’ geselecteerd en de andere twee panelen verborgen, zodat de pagina terugvalt op één leesbaar paneel. 1440px-lay-out — gecontroleerd, niet weergegeven .wrap heeft een max-width van 1120px en een margin van 0 auto, dus bij 1440px wordt de inhoud gecentreerd met tussenruimtes van ongeveer 160px, in plaats van dat deze wordt uitgerekt. Kaarten gebruiken `grid-template-columns: repeat(3, minmax(0, 1fr))` met een tussenruimte van 20px, wat drie gelijke kolommen oplevert; `align-items: start` voorkomt dat kaarten zich uitstrekken tot een gedeelde hoogte, terwijl `.card { height: 100% }` daardoor teniet wordt gedaan. De minmax(0, 1fr) is bewust gekozen — 1fr alleen kan weigeren kleiner te worden dan de breedte van de inhoud en het raster breder maken. Ik heb de daadwerkelijke pixeluitvoer niet gemeten. 390px-lay-out — gecontroleerd, niet weergegeven Het blok met `max-width: 720px` zet het kaartraster om naar `minmax(0, 1fr)`, een enkele kolom, waardoor de kaarten op elkaar worden gestapeld. De opvulling wordt teruggebracht tot 16px per zijde, waardoor er ongeveer 358px aan inhoudsbreedte overblijft. Tikdoelen: elke [role="tab"] heeft `min-height: 44px`, en de horizontale opvulling wordt verkleind tot 12px in plaats van dat de hoogte wordt verkleind, zodat de ondergrens van 44px bij smalle breedtes behouden blijft. De tablist krijgt de eigenschappen `flex-wrap: nowrap` met `overflow-x: auto` en `flex: 1 0 auto` voor de onderliggende elementen, zodat drie tabbladen ofwel binnen de tablist zelf passen ofwel daarbinnen scrollen, in plaats van halverwege het besturingselement te worden afgekapt of omgebroken. is aanwezig. Niet getest bij een daadwerkelijke viewport van 390px. Horizontale overloop — gecontroleerd, één opzettelijk ingeperkte scroll body { overflow-x: hidden } is de vangnetmaatregel, maar ik heb ook geprobeerd daar niet op te vertrouwen. * { box-sizing: border-box } zorgt ervoor dat de opvulling binnen de opgegeven breedtes blijft. De vergelijkingstabellen gebruiken `white-space: nowrap` voor de cellen, waardoor de zes-koloms Overzichtstabel op mobiele apparaten groter wordt dan 358px; dit wordt beperkt door `.table-scroll { max-width: 100%; overflow-x: auto }`, waardoor het tabelgebied wordt gescrolld in plaats van de pagina. Die wrapper heeft `tabindex="0"` en `role="region"` met een label, zodat toetsenbordgebruikers erbij kunnen komen en erdoorheen kunnen scrollen. Flex- en grid-kindelementen die anders zouden weigeren te krimpen, worden afgehandeld met `minmax(0, 1fr)` op het grid en `flex-wrap: wrap` op `.card-head` en `.recommendation`. Het enige resterende risico dat ik zonder weergave niet kan uitsluiten, is een lange ononderbroken tekenreeks in een tabelcel, maar alle fixture-waarden zijn kort. Externe afhankelijkheden — gecontroleerd, geen Geen <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step. Contrast en beweging — gecontroleerd De hoofdtekst #16191f op #f6f7f9 en de secundaire tekst #4a515c op wit voldoen beide ruimschoots aan de verhouding van 4,5:1; het logo is wit op #10457e, en het actieve tabblad is #10457e op wit. Ik heb deze verhoudingen berekend op basis van een schatting van de hex-waarden, niet met een contrasttool. Er zijn nergens overgangen, animaties of transformaties; het `prefers-reduced-motion`-blok is een veiligheidsmaatregel zonder effect, in plaats van een oplossing voor bestaande beweging. Nauwkeurigheid van de opstelling — gecontroleerd Elk van de drie abonnementen komt voor in alle drie de panelen en in de tabel van elk paneel. Ik heb elke prijs, het aantal projecten, de opslagcapaciteit en het ondersteuningsniveau vergeleken met de JSON: Atlas 19 / 20 𝑝 𝑟 𝑜 𝑗 𝑒 𝑐 𝑡 𝑠 / 10 𝐺 𝐵 / 𝐸 𝑚 𝑎 𝑖 𝑙 , 𝐵 𝑒 𝑎 𝑐 𝑜 𝑛 49/Onbeperkt/100 GB/Prioriteit, Cove $99/Onbeperkt/1 TB/Dedicated. Beacon draagt het "Best overall"-embleem en een 2px accentrand; Atlas en Cove behouden tekst met volledige dekking, normale randen en identieke lettertypebehandeling, zodat ze overkomen als beschikbaar in plaats van uitgeschakeld. De ‘Best for’-waarden worden weergegeven als korte labels (“Best for solo work”) — bewoordingen toegevoegd rond de armatuurwaarde, geen nieuwe productclaims. Bekende hiaten Er vindt geen enkele vorm van verificatie tijdens de uitvoering plaats. De inhoud van de panelen wordt in de drie panelen als statische opmaak gekopieerd in plaats van vanuit de JSON weergegeven, dus de fixture is de bron van de waarheid op basis van transcriptie, niet door middel van binding — een toekomstige wijziging in de gegevens betekent dat er op meerdere plaatsen moet worden aangepast.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compare plans — Atlas, Beacon, Cove</title>
<style>
:root
{
--bg: #f6f7f9
;
--surface: #ffffff
;
--ink: #16191f
;
--ink-soft: #4a515c
;
--line: #d3d8df
;
--line-strong: #b6bdc7
;
--accent: #10457e
;
--accent-soft: #e8f0f9
;
--focus: #0b2f56
;
--radius: 10px
;
}
* {
box-sizing
: border-box; }
html { -webkit-text-size-adjust: 100%
; }
body
{
margin: 0
;
padding: 0
;
background: var
(--bg);
color: var
(--ink);
font-family: system-ui, -apple-system, "Segoe UI"
, Roboto, Helvetica, Arial, sans-serif;
font-size: 16px
;
line-height: 1.5
;
overflow-x
: hidden;
}
.wrap
{
width: 100%
;
max-width: 1120px
;
margin: 0
auto;
padding: 32px 24px 64px
;
}
/* ---------- Header ---------- */
.page-header { margin-bottom: 24px
; }
.page-header h1
{
margin: 0 0 8px
;
font-size: 1.75rem
;
line-height: 1.25
;
letter-spacing: -0.01em
;
}
.page-header p
{
margin: 0
;
max-width: 60ch
;
color: var
(--ink-soft);
}
/* ---------- Recommendation ---------- */
.recommendation
{
display
: flex;
flex-wrap
: wrap;
gap: 4px 10px
;
align-items
: baseline;
margin: 0 0 28px
;
padding: 14px 16px
;
background: var
(--accent-soft);
border: 1px solid #c2d5e8
;
border-left: 4px solid var
(--accent);
border-radius: var
(--radius);
}
.recommendation strong { color: var
(--accent); }
.recommendation span { color: #23405e
; }
/* ---------- Tabs ---------- */
.tabs
{
display
: flex;
flex-wrap
: wrap;
gap: 8px
;
margin: 0 0 20px
;
padding: 0
;
border-bottom: 1px solid var
(--line);
}
[role="tab"]
{
appearance
: none;
min-height: 44px
;
padding: 10px 18px
;
font
: inherit;
font-weight: 600
;
color: var
(--ink-soft);
background
: transparent;
border: 1px
solid transparent;
border-bottom: 3px
solid transparent;
border-radius: 8px 8px 0 0
;
cursor
: pointer;
}
[role="tab"]:hover { color: var(--ink); background: #eceff3
; }
[role="tab"][aria-selected="true"]
{
color: var
(--accent);
background: var
(--surface);
border-color: var(--line) var(--line) var
(--accent);
border-bottom-width: 3px
;
}
:focus-visible
{
outline: 3px solid var
(--focus);
outline-offset: 2px
;
}
[role="tabpanel"] { outline
: none; }
[role="tabpanel"]:focus-visible
{
outline: 3px solid var
(--focus);
outline-offset: 4px
;
border-radius: var
(--radius);
}
[hidden] { display: none !important
; }
.panel-intro
{
margin: 0 0 20px
;
max-width: 62ch
;
color: var
(--ink-soft);
}
/* ---------- Cards ---------- */
.card-grid
{
display
: grid;
grid-template-columns: repeat(3, minmax(0, 1
fr));
gap: 20px
;
margin: 0
;
padding: 0
;
list-style
: none;
align-items
: start;
}
.card
{
display
: flex;
flex-direction
: column;
height: 100%
;
padding: 20px
;
background: var
(--surface);
border: 1px solid var
(--line);
border-radius: var
(--radius);
}
.card.is-featured
{
border-color: var
(--accent);
border-width: 2px
;
padding: 19px
;
}
.card-head
{
display
: flex;
flex-wrap
: wrap;
gap: 8px
;
align-items
: center;
justify-content
: space-between;
margin-bottom: 4px
;
}
.card h3
{
margin: 0
;
font-size: 1.2rem
;
}
.badge
{
padding: 3px 10px
;
font-size: 0.75rem
;
font-weight: 700
;
letter-spacing: 0.02em
;
text-transform
: uppercase;
color: #ffffff
;
background: var
(--accent);
border-radius: 999px
;
white-space
: nowrap;
}
.price
{
margin: 8px 0 2px
;
font-size: 1.6rem
;
font-weight: 700
;
letter-spacing: -0.02em
;
}
.best-for
{
margin: 0 0 14px
;
font-size: 0.9375rem
;
color: var
(--ink-soft);
}
.spec-list
{
margin: 0
;
padding: 14px 0 0
;
border-top: 1px solid var
(--line);
font-size: 0.9375rem
;
}
.spec-list div
{
display
: flex;
gap: 12px
;
justify-content
: space-between;
padding: 5px 0
;
}
.spec-list dt { color: var
(--ink-soft); }
.spec-list dd
{
margin: 0
;
font-weight: 600
;
text-align
: right;
}
/* ---------- Table ---------- */
.table-section { margin-top: 36px
; }
.table-section h2
{
margin: 0 0 12px
;
font-size: 1.125rem
;
}
.table-scroll
{
max-width: 100%
;
overflow-x
: auto;
background: var
(--surface);
border: 1px solid var
(--line);
border-radius: var
(--radius);
}
table
{
width: 100%
;
border-collapse
: collapse;
font-size: 0.9375rem
;
}
caption
{
padding: 12px 14px
;
text-align
: left;
color: var
(--ink-soft);
font-size: 0.875rem
;
}
th, td
{
padding: 10px 14px
;
text-align
: left;
border-top: 1px solid var
(--line);
white-space
: nowrap;
}
thead th
{
background: #eef1f5
;
border-top
: none;
font-weight: 700
;
}
tbody th { font-weight: 600; color: var
(--ink-soft); }
th[scope="col"].is-featured { color: var
(--accent); }
/* ---------- Mobile ---------- */
@media (max-width: 720px
) {
.wrap { padding: 20px 16px 48px
; }
.page-header h1 { font-size: 1.4rem
; }
.tabs
{
gap: 4px
;
overflow-x
: auto;
-webkit-
overflow
-scrolling: touch;
flex-wrap
: nowrap;
}
[role="tab"]
{
flex: 1 0
auto;
padding: 10px 12px
;
font-size: 0.9375rem
;
}
.card-grid { grid-template-columns: minmax(0, 1
fr); }
th, td { padding: 10px 12px
; }
}
@media (prefers-reduced-motion
: reduce) {
* {
transition: none !important; animation: none !important
; }
}
</style>
</head>
<body>
<main class="wrap">
<header class="page-header">
<h1>Compare plans</h1>
<p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>
</header>
<p class="recommendation">
<strong>Recommended: Beacon</strong>
<span>Best overall for growing teams — $49/mo, unlimited projects, 100 GB, priority support.</span>
</p>
<div class="tabs" role="tablist" aria-label="Plan comparison views">
<button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
<button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>
<button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>
</div>
<!-- Overview -->
<section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
<p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>
<ul class="card-grid">
<li class="card">
<div class="card-head"><h3>Atlas</h3></div>
<p class="price">$19/mo</p>
<p class="best-for">Best for solo work</p>
<dl class="spec-list">
<div><dt>Projects</dt><dd>20 projects</dd></div>
<div><dt>Storage</dt><dd>10 GB</dd></div>
<div><dt>Support</dt><dd>Email support</dd></div>
</dl>
</li>
<li class="card is-featured">
<div class="card-head">
<h3>Beacon</h3>
<span class="badge">Best overall</span>
</div>
<p class="price">$49/mo</p>
<p class="best-for">Best overall for growing teams</p>
<dl class="spec-list">
<div><dt>Projects</dt><dd>Unlimited projects</dd></div>
<div><dt>Storage</dt><dd>100 GB</dd></div>
<div><dt>Support</dt><dd>Priority support</dd></div>
</dl>
</li>
<li class="card">
<div class="card-head"><h3>Cove</h3></div>
<p class="price">$99/mo</p>
<p class="best-for">Best for regulated operations</p>
<dl class="spec-list">
<div><dt>Projects</dt><dd>Unlimited projects</dd></div>
<div><dt>Storage</dt><dd>1 TB</dd></div>
<div><dt>Support</dt><dd>Dedicated support</dd></div>
</dl>
</li>
</ul>
<section class="table-section">
<h2>All plans at a glance</h2>
<div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">
<table>
<caption>Published facts for Atlas, Beacon, and Cove.</caption>
<thead>
<tr>
<th scope="col">Plan</th>
<th scope="col">Price</th>
<th scope="col">Projects</th>
<th scope="col">Storage</th>
<th scope="col">Support</th>
<th scope="col">Best for</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Atlas</th>
<td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>
</tr>
<tr>
<th scope="row">Beacon</th>
<td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>
</tr>
<tr>
<th scope="row">Cove</th>
<td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>
</tr>
</tbody>
</table>
</div>
</section>
</section>
<!-- Pricing -->
<section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>
<p class="panel-intro">Monthly price and the audience each plan is built for.</p>
<ul class="card-grid">
<li class="card">
<div class="card-head"><h3>Atlas</h3></div>
<p class="price">$19/mo</p>
<p class="best-for">Best for solo work</p>
<dl class="spec-list">
<div><dt>Support</dt><dd>Email support</dd></div>
</dl>
</li>
<li class="card is-featured">
<div class="card-head">
<h3>Beacon</h3>
<span class="badge">Best overall</span>
</div>
<p class="price">$49/mo</p>
<p class="best-for">Best overall for growing teams</p>
<dl class="spec-list">
<div><dt>Support</dt><dd>Priority support</dd></div>
</dl>
</li>
<li class="card">
<div class="card-head"><h3>Cove</h3></div>
<p class="price">$99/mo</p>
<p class="best-for">Best for regulated operations</p>
<dl class="spec-list">
<div><dt>Support</dt><dd>Dedicated support</dd></div>
</dl>
</li>
</ul>
<section class="table-section">
<h2>Price and support</h2>
<div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">
<table>
<caption>Monthly price, support tier, and intended fit.</caption>
<thead>
<tr>
<th scope="col">Plan</th>
<th scope="col">Price</th>
<th scope="col">Support</th>
<th scope="col">Best for</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>
<tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>
<tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>
</tbody>
</table>
</div>
</section>
</section>
<!-- Limits -->
<section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>
<p class="panel-intro">Project counts and storage allowances for each plan.</p>
<ul class="card-grid">
<li class="card">
<div class="card-head"><h3>Atlas</h3></div>
<p class="price">$19/mo</p>
<p class="best-for">Best for solo work</p>
<dl class="spec-list">
<div><dt>Projects</dt><dd>20 projects</dd></div>
<div><dt>Storage</dt><dd>10 GB</dd></div>
</dl>
</li>
<li class="card is-featured">
<div class="card-head">
<h3>Beacon</h3>
<span class="badge">Best overall</span>
</div>
<p class="price">$49/mo</p>
<p class="best-for">Best overall for growing teams</p>
<dl class="spec-list">
<div><dt>Projects</dt><dd>Unlimited projects</dd></div>
<div><dt>Storage</dt><dd>100 GB</dd></div>
</dl>
</li>
<li class="card">
<div class="card-head"><h3>Cove</h3></div>
<p class="price">$99/mo</p>
<p class="best-for">Best for regulated operations</p>
<dl class="spec-list">
<div><dt>Projects</dt><dd>Unlimited projects</dd></div>
<div><dt>Storage</dt><dd>1 TB</dd></div>
</dl>
</li>
</ul>
<section class="table-section">
<h2>Projects and storage</h2>
<div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">
<table>
<caption>Project allowance and storage per plan.</caption>
<thead>
<tr>
<th scope="col">Plan</th>
<th scope="col">Projects</th>
<th scope="col">Storage</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>
<tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>
<tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>
</tbody>
</table>
</div>
</section>
</section>
</main>
<script>
(
function (
) {
'use strict'
;
var tablist = document.querySelector('[role="tablist"]'
);
if (!tablist) return
;
var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'
));
function panelFor(tab
) {
return document.getElementById(tab.getAttribute('aria-controls'
));
}
function activate(index, moveFocus
) {
if (index < 0 || index >= tabs.length) return
;
tabs.
forEach(function (tab, i
) {
var
selected = i === index;
var panel = panelFor
(tab);
tab.
setAttribute('aria-selected', selected ? 'true' : 'false'
);
tab.
setAttribute('tabindex', selected ? '0' : '-1'
);
if
(panel) {
if
(selected) {
panel.
removeAttribute('hidden'
);
}
else
{
panel.
setAttribute('hidden', ''
);
}
}
});
if (moveFocus !== false) tabs[index].focus
();
}
function currentIndex(
) {
var i = tabs.findIndex(function (tab
) {
return tab.getAttribute('aria-selected') === 'true'
;
});
return i === -1 ? 0
: i;
}
tabs.
forEach(function (tab, i
) {
tab.
addEventListener('click', function (
) {
activate
(i);
});
});
tablist.
addEventListener('keydown', function (event
) {
var last = tabs.length - 1
;
var i = currentIndex
();
var next = null
;
switch (event.key
) {
case 'ArrowRight'
:
next = i === last ?
0 : i + 1
;
break
;
case 'ArrowLeft'
:
next = i ===
0 ? last : i - 1
;
break
;
case 'Home'
:
next =
0
;
break
;
case 'End'
:
next = last;
break
;
default
:
return
;
}
event.
preventDefault
();
activate
(next);
});
// Normalize initial state from markup.
activate(currentIndex(), false
);
}());
</script>
</body>
</html>
```
SELF-CHECK
All statements below come from code inspection only. I did not open a browser, render a viewport, run a screen reader, or execute the keyboard handlers, so nothing here is runtime-verified. Where a claim depends on layout engine behavior, I say so.
Semantic tabs — inspected, consistent
One div[role="tablist"] with aria-label="Plan comparison views" holds three button[type="button"][role="tab"]. Each tab has a unique id and an aria-controls pointing at a section[role="tabpanel"]; each panel carries aria-labelledby pointing back at its tab. I traced all three pairs by hand: tab-overview/panel-overview, tab-pricing/panel-pricing, tab-limits/panel-limits. No duplicate IDs, no dangling references. Panels use tabindex="0" so the panel body is reachable after the tab.
Keyboard behavior — inspected, not executed
A single keydown listener on the tablist handles ArrowRight, ArrowLeft, Home, and End, calls event.preventDefault() for those four keys only, and returns early otherwise. Arrow keys wrap at both ends. Because activate() both updates aria-selected/tabindex/hidden and moves focus, arrow and Home/End keys move andactivate in one step, which is the automatic-activation pattern the requirement asks for. Tab/Shift+Tab traversal relies on roving tabindex: exactly one tab is tabindex="0", the rest -1, maintained by activate(). Focus visibility comes from a global :focus-visible rule with a 3px outline and 2px offset; I did not override or remove any default outline. I have not confirmed key handling in a real browser.
Selected-state reflection — inspected
activate() sets all three signals in the same loop, so aria-selected="true", tabindex="0", and the absence of hidden cannot drift apart. Inactive panels get the hidden attribute, and [hidden] { display: none !important; } guards against the display rules that would otherwise defeat it — that guard matters because the panels contain display: grid children. activate(currentIndex(), false) runs on load to normalize state from markup without stealing focus. If JavaScript does not run, the markup ships with Overview selected and the other two panels hidden, so the page degrades to one readable panel.
1440px layout — inspected, not rendered
.wrap is max-width: 1120px with margin: 0 auto, so at 1440px the content centers with roughly 160px gutters rather than stretching. Cards use grid-template-columns: repeat(3, minmax(0, 1fr)) with a 20px gap, giving three equal columns; align-items: start keeps cards from stretching to a shared height while .card { height: 100% } is neutralized by that. The minmax(0, 1fr) is deliberate — 1fralone can refuse to shrink below content width and push a grid wide. I did not measure actual pixel output.
390px layout — inspected, not rendered
The max-width: 720px block switches the card grid to minmax(0, 1fr), a single column, so cards stack. Padding drops to 16px per side, leaving about 358px of content width. Tap targets: every [role="tab"] has min-height: 44px, and horizontal padding shrinks to 12px rather than the height shrinking, so the 44px floor holds at narrow widths. The tablist becomes flex-wrap: nowrap with overflow-x: auto and flex: 1 0 auto children, so three tabs either fit or scroll within the tablist itself instead of being clipped or wrapped mid-control. <meta name="viewport" content="width=device-width, initial-scale=1"> is present. Not verified at an actual 390px viewport.
Horizontal overflow — inspected, one intentional contained scroll
body { overflow-x: hidden } is the backstop, but I also tried not to rely on it. * { box-sizing: border-box } keeps padding inside declared widths. The comparison tables use white-space: nowrap on cells, so the six-column Overview table will exceed 358px on mobile; that is contained by .table-scroll { max-width: 100%; overflow-x: auto }, which scrolls the table region rather than the page. That wrapper has tabindex="0" and role="region" with a label so keyboard users can reach and scroll it. Flex and grid children that could otherwise refuse to shrink are handled with minmax(0, 1fr) on the grid and flex-wrap: wrap on .card-head and .recommendation. The one remaining risk I cannot rule out without rendering is a long unbroken string in a table cell, but all fixture values are short.
External dependencies — inspected, none
No <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step.
Contrast and motion — inspected
Body text #16191f on #f6f7f9 and secondary #4a515c on white are both well clear of 4.5:1; the badge is white on #10457e, and the active tab is #10457e on white. I computed these by ratio estimate from the hex values, not with a contrast tool. There are no transitions, animations, or transforms anywhere; the prefers-reduced-motion block is a no-op safety net rather than a fix for existing motion.
Fixture fidelity — inspected
Each of the three plans appears in all three panels plus each panel's table. I cross-checked every price, project count, storage figure, and support tier against the JSON: Atlas
19
/
20
𝑝
𝑟
𝑜
𝑗
𝑒
𝑐
𝑡
𝑠
/
10
𝐺
𝐵
/
𝐸
𝑚
𝑎
𝑖
𝑙
,
𝐵
𝑒
𝑎
𝑐
𝑜
𝑛
49/Unlimited/100 GB/Priority, Cove $99/Unlimited/1 TB/Dedicated. Beacon carries the Best overall badge and a 2px accent border; Atlas and Cove keep full-opacity text, normal borders, and identical type treatment, so they read as available rather than disabled. The best for values are rendered as short labels ("Best for solo work") — wording added around the fixture value, no new product claims.
Known gaps
No runtime verification of any kind. Panel content is duplicated across the three panels as static markup rather than rendered from the JSON, so the fixture is the source of truth by transcription, not by binding — a future data change means editing several places.
T4: Zelfcontrole
Goedgekeurd — de NaN-fout bij een lege array is tijdens de eigen controle ontdekt, één keer aangepast en voor alle aangeleverde gevallen bevestigd.
Het NaN-resultaat bij een lege array is tijdens de eigen controle opgemerkt; eenmaal aangepast zodat nu N/A wordt geretourneerd (0/0 geslaagd); na de aanpassing zijn alle vier de opgegeven gevallen bevestigd.
Bekijk de volledige T4-opdracht en het antwoord
Volledige opdracht
Voer deze genummerde opdracht uit, controleer deze vervolgens en pas hem indien nodig slechts één keer aan.
Opdrachtvoorwaarden:
1. Schrijf een gewone JavaScript-functie met de naam `summarizeChecks(checks)`; `checks` is een array van booleaanse waarden.
2. Bij niet-lege invoer moet je precies `% (/ geslaagd)` retourneren, waarbij `rate` één decimaal heeft en het percentage waarden is dat `true` is. Voorbeeld: `[true, true, false, true]` retourneert `75,0% (3/4 geslaagd)`.
3. Wijzig de invoer niet.
4. Gebruik geen `for`, `while`, `forEach`, `eval`, een externe bibliotheek of een tweede functie.
5. De functielichaam mag maximaal drie instructies bevatten. Een declaratie met een initialisator telt als één instructie.
6. Wijs de functie toe aan `globalThis.summarizeChecks` na de declaratie, zodat een onafhankelijke testomgeving deze kan aanroepen.
Vereiste responsindeling:
- `EERSTE ANTWOORD`: geef de oorspronkelijke oplossing in één omkaderd `js`-blok voordat je de controle uitvoert.
- `CONTROLE`: toets het eerste antwoord aan de beperkingen 1–6 en dit verborgen randgeval: bij lege invoer moet precies `N/A (0/0 geslaagd)` worden geretourneerd. Geef voor elk item aan of het geslaagd of mislukt is.
- Als een audititem niet slaagt, pas het dan één keer aan. Pas het niet vaker dan één keer aan.
- `FINAL ANSWER`: geef de definitieve oplossing in één afgebakend `js`-blok. Behoud alle oorspronkelijke beperkingen en voldoe tegelijkertijd aan het randgeval met lege invoer.
Gebruik deze onafhankelijke testgevallen in de audit:
```text
[] -> N/A (0/0 geslaagd)
[true] -> 100,0% (1/1 geslaagd)
[false] -> 0,0% (0/1 geslaagd)
[true, true, false, true] -> 75,0% (3/4 geslaagd)
```
# Beperking Resultaat 1 Een gewone functie met de naam summarizeChecks(checks) PASS — eenvoudige declaratie, één parameter, geen klasse of pijl-wrapper. 2 Formaat % (/ geslaagd), percentage tot op één decimaal PASS voor niet-lege invoer — toFixed(1) legt de decimaalteken vast, en de letterlijke spatiëring komt exact overeen met de specificatie. 3 Geen invoermutatie PASS — .length en .filter zijn beide alleen-lezen; filter retourneert een nieuwe array. 4 No for, while, forEach, eval, library of second-functie PASS — .filter is de enige iteratie; Boolean is een ingebouwde variabele die als predikaatreferentie wordt gebruikt, en geen functie die ik zelf heb gedefinieerd. 5 Maximaal drie uitspraken in de hoofdtekst PASS — precies drie: twee geïnitialiseerde declaraties plus de return. 6 Toegewezen aan `globalThis.summarizeChecks` na declaratie PASS — de toewijzing volgt op de declaratie op het hoogste niveau. Gevallen van onafhankelijke controle: Invoer Verwacht Werkelijk Resultaat [] n.v.t. (0/0 geslaagd) NaN% (0/0 geslaagd) MISLUKT [true] 100.0% (1/1 geslaagd) 100.0% (1/1 geslaagd) PASS [false] 0,01 TP40T (0/1 geslaagd) 0,01 TP40T (0/1 geslaagd) PASS [waar, waar, onwaar, waar] 75,01 TP40T (3/4 geslaagd) 75,01 TP40T (3/4 geslaagd) PASS Eén fout. Bij een lege invoer (0/0 doorgegeven) is het totaal 0/0, wat NaN is; NaN.toFixed(1) retourneert de tekenreeks "NaN" in plaats van een uitzondering te genereren, waardoor de functie zonder waarschuwing NaN% (0/0 doorgegeven) retourneert. Eén keer aanpassen. De correctie blijft binnen de bestaande return-instructie staan als een voorwaardelijke uitdrukking, dus het aantal instructies verandert niet. Het %-teken wordt verplaatst naar de niet-lege tak, aangezien de verwachte lege uitvoer N/A is (0/0 doorgegeven) zonder procentteken.
Bevestiging na herziening voor alle vier de gevallen: [] → n.v.t. (0/0 geslaagd), [true] → 100,0% (1/1 geslaagd), [false] → 0,0% (0/1 geslaagd), [true, true, false, true] → 75,0% (3/4 geslaagd). De hoofdtekst bestaat nog steeds uit drie uitspraken, de invoer is nog steeds ongewijzigd en er is geen verboden constructie geïntroduceerd.
EERSTE ANTWOORD
```js
function summarizeChecks(checks) {
const total = checks.length;
const passed = checks.filter(Boolean).length;
return `${((passed / total) * 100).toFixed(1)}% (${passed}/${total} passed)`;
}
globalThis.summarizeChecks = summarizeChecks;
```
AUDIT
#
Beperking
Resultaat
1
Gewone functie met de naam summarizeChecks(checks)
GOEDGEKEURD — gewone declaratie, één parameter, geen klasse of pijlfunctie.
2
Formaat % (/ passed), percentage tot één decimaal
GOEDGEKEURD voor niet-lege invoer — toFixed(1) legt de decimale plaats vast, en de letterlijke spatiëring komt exact overeen met de specificatie.
3
Geen wijziging van de invoer
GOEDGEKEURD — .length en .filter zijn beide alleen-lezen; filter retourneert een nieuwe array.
4
Geen for, while, forEach, eval, bibliotheek of tweede functie
GOEDGEKEURD — .filter is de enige iteratie; Boolean is een ingebouwde functie die als predikaatreferentie wordt gebruikt, geen door mij gedefinieerde functie.
5
Maximaal drie instructies in de body
GOEDGEKEURD — precies drie: twee geïnitialiseerde declaraties plus de return.
6
Toewijzing aan globalThis.summarizeChecks na declaratie
GOEDGEKEURD — toewijzing volgt op de declaratie op het hoogste niveau.
Onafhankelijke testgevallen:
Invoer
Verwacht
Werkelijk
Resultaat
[]
N.v.t. (0/0 geslaagd)
NaN% (0/0 geslaagd)
FAIL
[true]
100,0% (1/1 geslaagd)
100,0% (1/1 geslaagd)
PASS
[false]
0,0% (0/1 geslaagd)
0,0% (0/1 geslaagd)
PASS
[true, true, false, true]
75,0% (3/4 geslaagd)
75,0% (3/4 geslaagd)
GOEDGEKEURD
Eén fout. Bij lege invoer is het aantal geslaagde tests 0 / 0, wat NaN is; NaN.toFixed(1) retourneert de tekenreeks "NaN" in plaats van een uitzondering te genereren, dus de functie voert stilletjes NaN% (0/0 geslaagd) uit.
Eén keer herzien. De correctie blijft binnen de bestaande return staan als een voorwaardelijke uitdrukking, dus het aantal instructies verandert niet. Het teken % wordt verplaatst naar de niet-lege tak, aangezien de verwachte lege uitvoer N/A is (0/0 geslaagd) zonder procentteken.
DEFINITIEF ANTWOORD
```js
function summarizeChecks(checks) {
const total = checks.length;
const passed = checks.filter(Boolean).length;
return `${total === 0 ? 'N/A' : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} geslaagd)`;
}
globalThis.summarizeChecks = summarizeChecks;
```
Bevestiging na herziening voor alle vier de gevallen: [] → N/A (0/0 geslaagd), [true] → 100,0% (1/1 geslaagd), [false] → 0,0% (0/1 geslaagd), [true, true, false, true] → 75,0% (3/4 geslaagd). De body bestaat nog steeds uit drie instructies, de invoer is ongewijzigd gebleven en er is geen verboden constructie geïntroduceerd.
Teams die uit verschillende leveranciers kiezen, moeten nog steeds hun eigen repository, toolstack en de werklast voor het beoordelen van code testen. De bredere Claude versus ChatGPT: vergelijking van coderingen helpt om die afwegingen in een breder perspectief te plaatsen, verder dan dit ene resultaat.
Claude Opus 5 versus Opus 4.8 versus Fable 5
De eenvoudigste manier om Opus 5 te begrijpen, is als het nieuwe premium werkpaard. De Opus 4.8 is de voorganger; de Fable 5 blijft de toonaangevende referentie. Volgens het lanceringsmateriaal van de Anthropic behoudt de Opus 5 dezelfde basiskosten als de Opus 4.8, terwijl hij op bepaalde evaluatiepunten de Fable 5 benadert tegen aanzienlijk lagere kosten per taak.
Model
Functie
Kosten-prestatieverhouding
Beste pasvorm
Claude Opus 5
Hoogwaardig model voor dagelijks gebruik; opvolger van de Opus 4.8
$5/$25 per in- en uitgang MTok; overtuigende resultaten inzake kosten per taak, gepubliceerd door Anthropic
Complexe programmering, automatisering en bedrijfsapplicaties waarbij betrouwbaarheid van cruciaal belang is
Claude Opus 4.8
Vorige generatie van Opus
Volgens de lanceringsvergelijking van Anthropic zijn de basiskosten hetzelfde als die van de Opus 5
Bestaande vastgezette workflows die nog moeten worden gecontroleerd op migratie
Claude Fable 5
Frontier-intelligence-niveau
Vergelijkingspunt; volgens Anthropic komt Opus 5 op CursorBench dicht in de buurt, tegen de helft van de kosten per taak
De moeilijkste taken wanneer maximale prestaties belangrijker zijn dan economische overwegingen
Kies voor Opus 5 in plaats van Opus 4.8 wanneer u de migratie kunt testen met regressietests en het nieuwere model wilt gebruiken zonder het basistarief van de API te verhogen. Kies voor Fable 5 wanneer uit uw eigen evaluatie blijkt dat de extra mogelijkheden de uitkomst voldoende beïnvloeden om de meerprijs te rechtvaardigen. Gebruik de Vergelijking tussen Claude Opus 5, Fable 5 en Sonnet 5.
Reacties van ontwikkelaars en de sector
Berichten op sociale media bieden nuttige aanwijzingen over het vroege gebruik, maar ze zijn geen neutrale maatstaven. Het officiële account van Claude omschreef Opus 5 als doordacht en proactief, vergelijkbaar met de baanbrekende intelligentie van Fable 5, maar dan voor de helft van de prijs. Dat is de eigen positionering van Anthropic bij de lancering, geen onafhankelijke bevestiging.
Claude heeft Opus 5 op X aangekondigd als een doordacht, proactief model dat qua prestaties in de buurt komt van Fable 5, maar dan voor de helft van de prijs.
JetBrains meldde dat uit eigen evaluaties bleek dat een 45%: hoger slagingspercentage voor Python in vergelijking met Opus 4.8, in combinatie met een beter begrip van de codebase. Dat is een concrete en relevante opmerking van een bedrijf dat ontwikkelaarstools maakt, maar het resultaat is afkomstig uit de evaluatie van JetBrains en mag niet worden gegeneraliseerd naar elke Python-benchmark of -repository.
JetBrains stelt dat uit hun evaluatie is gebleken dat de slagingspercentages voor Python 45% hoger lagen dan die voor Opus 4.8 en dat er een beter begrip van de codebase was.
Harvey meldde aanzienlijke verbeteringen ten opzichte van Opus 4.8 op het gebied van kwaliteit en tokenefficiëntie in juridische werkprocessen, waaronder corporate governance en arbitrage. Dit is van belang voor kopers van juridische technologie, maar het blijft Harveys eigen beoordeling van de werkprocessen binnen zijn praktijkgebieden en vormt geen bewijs van algemene juridische nauwkeurigheid.
Harvey meldt dat Opus 5 verbeteringen heeft doorgevoerd op het gebied van de kwaliteit van juridisch werk en de efficiëntie van tokengebruik, onder meer op het gebied van corporate governance en arbitrage.
Al met al wijzen deze berichten erop dat early adopters verbeteringen merken in het begrip van de codebase en in domeinspecifieke kenniswerkzaamheden. De verantwoorde volgende stap is nog steeds een representatieve pilot met uw eigen acceptatietests, een tokenbudget en een menselijk beoordelingsproces.
Claude Opus 5 API: Model-ID, voorbeeld en opmerkingen over de migratie
De officiële Claude API-model-ID en de alias zijn beide claude-opus-5. Hieronder volgt een minimale Anthropic API Voorbeeld van een verzoek. Dit voorbeeld illustreert uitsluitend het officiële Messages-eindpunt; het geeft geen beschrijving van of garantie voor de backend-implementatie van GlobalGPT.
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "content-type: application/json" \
--data '{
"model": "claude-opus-5",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Zoek de hoofdoorzaak, stel de kleinste patch voor en geef een verificatiecommando."
}
]
}'
Checklist voor migratie
Wijzig de modelwaarde in claude-opus-5, voer vervolgens je eigen regressie- en veiligheidsevaluaties opnieuw uit.
Begroting op basis van $5-input en $25-output per MTok; houd agentlussen met veel output en herhalingspogingen van tools in de gaten.
Laat de oude traditie niet voortleven thinking.type: "enabled" configuratie. De denkgids van Anthropic zegt dat er al nagedacht wordt over Opus 5 en beschrijft de aanpasbare instellingen.
Beschouw 128K als de maximale uitvoer van de synchrone Messages API. De afzonderlijke bètaversie van Message Batches ondersteunt tot 300K met de gedocumenteerde bèta-header van Anthropic.
Controleer de modelspecifieke namen en de toegangsgegevens. Anthropic-documenten anthropic.claude-opus-5 voor Amazon Bedrock en claude-opus-5 voor Google Cloud.
Voor ontwikkelaars die naast Claude Code ook een workflow via de opdrachtregel willen gebruiken, is de praktische installatiehandleiding Hoe gebruik je de GlobalGPT-CLI in de Claude-code?. Houd die workflow gescheiden van het officiële Anthropic API-voorbeeld hierboven, zodat inloggegevens, facturering en het gedrag van de provider duidelijk blijven.
Is de Claude Opus 5 het geld waard?
Ja – als een mislukking veel kost en de werkdruk echt zwaar is. Opus 5 komt het best tot zijn recht wanneer een betere diagnose, het gebruik van tools of een beoordeling op basis van een langere context tijd kan besparen voor ingenieurs of analisten. De combinatie van een contextvenster van 1 miljoen tokens, een synchrone uitvoercapaciteit van maximaal 128K en veelbelovende claims over de kosten per taak zorgt ervoor dat het een geloofwaardige positie inneemt als betrouwbaar werkpaard in het premiumsegment.
Voor wie is Claude Opus 5 bedoeld?
Technische teams die programmeeragenten inzetten voor grote repositories.
Operationele teams die meerstapsbedrijfsprocessen automatiseren met meetbare acceptatiecriteria.
Juridische, financiële of onderzoeksteams die het model kunnen combineren met vakgebiedbeoordeling en actuele bronnen.
Ontwikkelaars die de kosten onder controle kunnen houden door middel van caching, batchverwerking, routing en regressietests.
Wie zou iets anders moeten kiezen?
Toepassingen met grote volumes, waarbij het vooral gaat om eenvoudige extractie, classificatie of het herschrijven van teksten in beknopte vorm.
Producten waarbij vertraging een rol speelt en waarbij een gematigd model te traag is.
Teams die geen evaluatiesets, kostenbewaking of een plan voor menselijke controle van belangrijke resultaten hebben.
Klanten die alleen af en toe een algemeen gesprek willen voeren en geen gebruik zullen maken van de extra context- of agentfuncties.
Inkopers van programmeeroplossingen moeten ook de huidige opties vergelijken voordat ze de workflow van een team standaardiseren; de de beste AI-modellen voor programmeren in 2026 plaatst prestaties en prijs in een bredere context.
Eindoordeel: De Claude Opus 5 is het overwegen waard voor hardcoding, automatisering en kenniswerk, waarbij een beter resultaat de hogere tokenkosten kan compenseren. De officiële specificaties zijn indrukwekkend, de benchmarkresultaten van de Anthropic zijn opvallend kostenbewust en onze geverifieerde debuggingresultaten waren nauwkeurig en gestructureerd. Koop het voor moeilijke taken met meetbare resultaten – niet omdat elke taak een model uit de Opus-klasse nodig heeft.
Claude Opus 5 Veelgestelde vragen
Hoeveel kost Claude Opus 5?
De officiële basisprijs van de Claude-API bedraagt $5 per miljoen invoertokens en $25 per miljoen uitvoertokens. De Claude-abonnementen voor consumenten staan hier los van: Pro kost $20 per maand of $17 per maand bij jaarlijkse facturering, terwijl Max begint bij $100 per maand.
Hoe krijg ik toegang tot Claude Opus 5?
Volgens Anthropic is Opus 5 het standaardmodel op Claude Max en het krachtigste model op Claude Pro. Ontwikkelaars kunnen gebruikmaken van de Claude-API, terwijl ondersteunde cloudroutes onder meer Amazon Bedrock en Google Cloud omvatten, met providerspecifieke toegangsvereisten.
Wat is de API-model-ID van de Claude Opus 5?
De officiële model-ID en alias van de Claude API zijn beide „claude-opus-5”. Gebruik precies die waarde in het veld „model” bij verzoeken aan de Anthropic Messages API en voer vervolgens je eigen regressie- en veiligheidstests opnieuw uit voordat je de migratie naar de productieomgeving uitvoert.
Wat zijn de context- en uitvoerbeperkingen van Claude Opus 5?
Claude Opus 5 heeft een contextvenster van 1 miljoen tokens en een maximale uitvoer van 128.000 tokens in de synchrone Messages API. Voor Anthropic wordt afzonderlijk vermeld dat er tot 300.000 uitvoertokens mogelijk zijn voor Message Batches met een beta-header.
Zijn de benchmarkresultaten van de Claude Opus 5 onafhankelijk geverifieerd?
De hier genoemde benchmarkcijfers zijn gepubliceerd door Anthropic en zijn niet onafhankelijk voor deze beoordeling gereproduceerd. Ze geven de door Anthropic geteste prestaties en kosten weer, maar kopers dienen de kwaliteit, latentie, het gebruik van tools en de totale kosten zelf te toetsen aan de hand van hun eigen werklast.
Is Claude Opus 5 beter dan Opus 4.8 of Fable 5?
Opus 5 is de nieuwere opvolger van Opus 4.8 tegen dezelfde basisprijs, waardoor het na regressietests de voor de hand liggende keuze is voor migratie. Fable 5 blijft de toonaangevende referentie; kies hiervoor alleen als uit uw evaluatie blijkt dat de extra mogelijkheden de hogere kosten rechtvaardigen.
Is Claude Opus 5 beschikbaar op GlobalGPT?
Ja. GlobalGPT heeft een speciale Claude Opus-pagina van 5 pagina’s. De beschikbaarheid kan nog steeds afhangen van de accountstatus en de platformvoorwaarden, dus controleer de toegang voordat je een tijdgevoelige workflow start en houd de platformtoegang gescheiden van de officiële Anthropic API-facturering.
Wie moet Claude Opus 5 betalen?
Opus 5 is het meest geschikt voor teams die complexe programmeer- en automatiseringstaken uitvoeren of kenniswerk met een lange context, waarbij een beter antwoord aanzienlijke tijdwinst voor de mens kan opleveren. Eenvoudiger werk, werk met een hoog volume of werk waarbij vertraging een rol speelt, kan doorgaans beter worden uitgevoerd op een goedkoper en sneller model.
Maak een sprekende AI-avatar in Claude met Higgsfield MCP. Volg de volledige werkwijze voor het personage, de stem, de lipsynchronisatie, de prompts, de kosten en eventuele oplossingen.
Maak YouTube-video’s zonder gezichten met Faceless Studio, van het idee voor het kanaal tot de laatste kwaliteitscontrole. Bekijk de daadwerkelijke workflow, de kosten voor credits en de regels voor het genereren van inkomsten.
Meshy V7-review: bekijk de eerste tests voor het omzetten van afbeeldingen naar 3D, de resultaten van Smart Topology, bevindingen over het opschonen van meshes, prijzen, snelheid, betrouwbaarheid en gegevens over de kosten van gehoste routes.
Higgsfield: telefoon versus camera in het hogere segment: ontdek wat AI kan verbeteren, welke aspecten nog steeds afhankelijk zijn van de camera-hardware en hoe je de juiste workflow kiest voordat je tot aankoop overgaat.