Wat er nieuw is

Changelog

Elke release van Deckyard, in gewone taal. De details op commit-niveau staan op GitHub; hier lees je wat het betekent voor wie ermee werkt.

  1. v1.97.5 Nieuwste

    Veiligere video-embeds

    Een bewerkte videobron kon een script in de app laten draaien. De Bunny-embed wordt nu opgebouwd uit zijn id’s, en al het andere embedt niets.

    Beveiligingsfix. De videoslide gebruikte een geplakte Bunny-URL als adres van zijn frame, na alleen te controleren of de tekst de spelerhost van Bunny noemde. Iedereen die in een slide kon schrijven, ook een collaborator, een import of een agent, kon zo een javascript:-adres opslaan dat in de pagina draaide bij iedereen die het deck in de app opende. Dezelfde controle liet ook een vreemde pagina als frame door. Gepubliceerde edities waren niet geraakt. Draai je een eigen installatie, upgrade dan naar deze release.

    De fix verandert hoe een Bunny-URL wordt gelezen. De videoslide haalt nu het bibliotheek-id en het video-id uit een play- of embed-URL op de spelerhost van Bunny en bouwt daaruit het embed-adres op. Een query of fragment op de geplakte URL vervalt. Een embed-URL met tokenauthenticatie draagt zijn token dus niet meer; gebruik je de embed-tokenauthenticatie van Bunny, controleer die video’s dan na de upgrade. Een URL die iets anders is, embedt niets en de slide toont zijn lege staat.

    Deze release vraagt geen databasemigratie of nieuwe configuratie.

  2. v1.97.4

    Veiliger downloaden bij bulkexport

    De bulkexport past de bestaande SSRF-beveiliging nu ook toe op externe afbeeldingen. Een view verlaten stopt voortaan de lopende taak, en AI schrijft gemengde openingen als lopende tekst.

    Beveiligingsfix. Een aangemelde gebruiker kon de bulkexport een URL uit de beeldbibliotheek of een themalogo laten ophalen, ook een adres op het interne netwerk van de server, en het antwoord in de ZIP terugkrijgen. De bulkexport gebruikt nu dezelfde beveiliging als de andere exportroutes. Draai je een eigen installatie, upgrade dan naar deze release.

    De beveiliging verandert wat er in een bulkexport terechtkomt. Interne adressen, doorverwijzingen en antwoorden die geen afbeelding zijn, gaan niet meer mee. Een logo of bibliotheekafbeelding op een intranethost verliest dus zijn bytes in de ZIP. Downloads stoppen nu na 8 seconden of 15 MiB. Elke geweigerde afbeelding telt als mislukte download in de bestaande exportwaarschuwing. Openbare afbeeldingen en bestanden die de installatie zelf serveert, gaan gewoon mee. Gebruik je interne beeldhosts, controleer die waarschuwing dan na je volgende bulkexport.

    Lange taken stoppen nu wanneer je hun view verlaat. Navigeer je weg tijdens een analyse, import of export, dan sluit het voortgangsvenster en volgt er geen late doorverwijzing of download meer. Annuleren draait niet terug wat de server al heeft gedaan.

    Als AI een presentatie opzet, wordt een opening die doel, status, rollen en scope mengt nu een of twee samenhangende zinnen. Lijsten met items van één soort blijven lijsten.

    Deze release vraagt geen databasemigratie of nieuwe configuratie.

  3. v1.97.3

    Volledige opnamen van de exportdialoog

    Het screenshotrecept voor de exportdialoog toont nu het hele venster, inclusief de diaselectie en alle exportopties.

    Het opnamerecept voor de volledige exportdialoog gebruikt nu een hoger venster. De diaselectie en alle exportrijen passen in beeld, zonder afgesneden of verborgen inhoud. De controle die een afgeknotte opname weigert, blijft actief.

    Dit wijzigt het screenshotrecept; de exportdialoog in de app blijft gelijk. Deze release werkt ook gebundelde afhankelijkheden bij en vraagt geen databasemigratie of nieuwe configuratie.

  4. v1.97.2

    Toegevoegde slides met eigen beeld

    Slides met AI toevoegen aan een bestaand deck volgt nu dezelfde beeldregel als een deck maken: beeld wordt naar je mediabibliotheek gekopieerd, en wat niet lukt wordt gemeld.

    Slides met AI toevoegen aan een bestaand deck laat geen beeldlinks meer achter die naar elders wijzen. In de editor, MCP append_slides en de publieke append-slides-API zijn beeld-URL’s in je brontekst nu kandidaten waaruit de generatie kan kiezen, en elk gekozen beeld wordt naar je mediabibliotheek gekopieerd. Daarmee is het gat dicht dat 1.97.1 nog openliet.

    Wat API- en MCP-gebruikers merken

    De regels zijn gelijk aan die voor een nieuw deck. Kopiëren gebeurt alleen als uploads aanstaan en de aanroeper mag uploaden, dus een API-sleutel heeft naast ai ook write nodig; een sleutel met alleen ai haalt niets op.

    Een beeld dat niet gekopieerd kan worden, laat een leeg veld achter. Hetzelfde geldt voor een beeld-URL die het model zelf schrijft. MCP append_slides en de publieke append-slides-API geven nu warnings terug, waarbij index de nieuwe slides telt. In de editor staat de waarschuwing in het beoordelingsraster boven de nieuwe slides.

    Alleen gedeclareerde beeldvelden worden gecontroleerd. Markdownbeeld in lopende tekst niet.

    Deze release voegt geen databasemigratie of configuratie toe.

  5. v1.97.1

    AI-decks met eigen beeld

    Beeld dat uit de brontekst wordt gekozen, wordt naar je mediabibliotheek gekopieerd voordat een AI-deck wordt opgeslagen, en kaartkoppen blijven leesbaar in statische exports.

    Een door AI gemaakt deck bewaart geen beeldlinks meer die naar elders wijzen. Staan er beeld-URL’s in de brontekst voor create_presentation, de publieke AI-wizard-API of een wizard in de editor, dan kan de generatie daaruit kiezen en wordt elk gekozen beeld naar je mediabibliotheek gekopieerd voordat het deck wordt opgeslagen.

    Wat API- en MCP-gebruikers merken

    Kopiëren gebeurt alleen als uploads aanstaan en de aanroeper mag uploaden. Een API-sleutel heeft naast ai ook het recht write nodig; een sleutel met alleen ai haalt niets op.

    Een beeld dat niet gekopieerd kan worden, laat een leeg veld achter en het deck wordt gewoon opgeslagen. Hetzelfde geldt voor een beeld-URL die het model zelf schrijft. MCP create_presentation en de publieke wizard-API melden dit nu in warnings, per slide met positie en bericht. Slides toevoegen aan een bestaand deck valt hier nog buiten.

    Leesbare kaartkoppen in exports

    Koppen en subkoppen van de icon card grid worden in PNG, PDF en MCP-previews, en in PPTX waar de slide als afbeelding wordt geplaatst, niet langer wit op een lichte ondergrond. De editor en presenter blijven hetzelfde.

    Forks

    Houdt je fork de gradient in PDF-exports, vervang dan de gedeelde gate STATIC_GRADIENT_CSS in zijn geheel. Als je de gradient houdt maar de tekstkleuren wist, wordt het verkeerde kleurenpaar gekozen.

    Deze release voegt geen databasemigratie of configuratie toe.

  6. v1.97.0

    Veiligere gastsessies in de sandbox

    Gastcookies in de sandbox zijn nu ondertekend en afgeschermd voor paginascripts. Beheerders moeten vóór de upgrade een geheim instellen.

    De publieke sandbox ondertekent nu elke gastsessie en schermt de cookie af voor paginascripts. Sandboxgasten kunnen geen API-sleutels aanmaken en de sandbox weigert te starten als samenwerking is ingeschakeld.

    Vóór een sandboxupgrade

    Stel vóór de upgrade een willekeurige AUTH_SECRET van minstens 32 tekens in en schakel COLLAB_ENABLED uit. Zet het geheim bij Docker Compose in het bestand .env naast de composebestanden en beperk de bestandsrechten tot modus 600. Je kunt een geheim genereren met openssl rand -hex 32.

    Bestaande, niet-ondertekende gastcookies worden ongeldig. Bezoekers beginnen als een nieuwe gast en decks van de oude gastsessie worden onbereikbaar. Ook een latere wijziging van het geheim laat elke gast opnieuw beginnen.

    Oplossing voor publiceren

    Vastgelegde edities bevatten niet langer de bron-URL die de contrastcontrole voor de eigen administratie gebruikt. Het brondeck en het weergegeven contrastoordeel blijven gelijk.

    Deze release voegt geen databasemigratie toe. Installaties die vanaf 1.95.0 upgraden, krijgen ook migratie 107 uit 1.96.0 voor reacties bij bibliotheekitems.

  7. v1.96.0

    Reacties bij bibliotheekslides en bescherming bij bewerken

    Bespreek gedeelde bibliotheekslides in een reactiedraad en ontkoppel de slide van een andere maker voordat je hem bewerkt. Publiceren verwerkt nu ook schijfuploads en S3-bestandsnamen met spaties.

    Slides die aan het bibliotheekitem van een andere maker gekoppeld zijn, staan nu op slot in de editor. Kies Ontkoppelen en bewerken om er eerst een eigen kopie van te maken. Het oorspronkelijke bibliotheekitem blijft bij de maker.

    Gedeelde bibliotheekitems hebben nu een eigen reactiedraad, zodat feedback bij de herbruikbare slide blijft.

    Oplossingen voor publiceren

    Publiceren leest bestanden met een relatief /uploads/-adres nu eerst van schijf en probeert de ingestelde S3-bucket alleen als het bestand ontbreekt. Ook S3-uploads met spaties in de bestandsnaam kunnen nu in een editie worden vastgelegd. De beperkingen op het ingestelde publieke basisadres en uploadsleutels blijven gelden.

    Voor wie zelf host

    Migratie 107 voegt opslag voor reacties bij bibliotheekitems toe. Er is geen nieuwe configuratie nodig. Gebruik je de renderrunner, registreer dan de renderer van deze release voordat je nieuwe edities publiceert, volgens docs/ops/renderer-runner.md. Installaties die oude publicaties omzetten, moeten hun dry-run op deze tag herhalen voordat ze de omzetting uitvoeren; deze fixes bewijzen op zichzelf niet dat elk brondeck publiceerbaar is.

  8. v1.95.0

    Bibliotheekslides die hun bron kennen

    Een slide uit de slidebibliotheek laat nu zien wanneer het item een nieuwere versie heeft, met Bekijken, Bijwerken en Negeren. Installaties met S3-media publiceren edities met hun eigen uploads, en bezoeken aan edities tellen weer mee in de statistieken.

    Een slide die je uit de slidebibliotheek invoegt, onthoudt nu van welk item en welke versie hij komt. Slaat de maker van het item een nieuwere versie op, dan krijgt de eigenaar van het deck een melding, staat er een markering op de thumbnail en biedt een balk boven het canvas Bekijken, Bijwerken en Negeren. Bekijken zet je slide en de nieuwste versie naast elkaar. Bijwerken neemt de nieuwe inhoud over in elke taal die het item heeft en laat je sprekersnotities staan; een decktaal die het item niet heeft, houdt zijn tekst en staat in het vertaaloverzicht als gewijzigd. Negeren slaat die versie over tot er een nieuwere komt. Slides die vóór deze release zijn ingevoegd, hebben geen koppeling.

    Publiceren met S3-media

    Op installaties die uploads in S3 bewaren, weigerde publiceren in 1.94.0 decks met eigen geüploade beelden. Edities lezen publieke uploadobjecten nu via de ingestelde S3-provider en leggen ze vast in de editie, zodat de gepubliceerde versie niet meer van het oorspronkelijke object afhangt. Alleen het ingestelde publieke basisadres en publieke uploads/-sleutels worden geaccepteerd; geen andere URL in een deck wordt opgehaald. ImageKit, Bunny-video en slidetypes uit de database vragen nog een expliciete omzetting voordat zulke decks kunnen publiceren; zie de release op GitHub en docs/reference/publication-editions.md voor het bronbeleid.

    Statistieken

    Bezoeken aan een gepubliceerde editie (canvas, lezer en embed) tellen weer mee in de statistieken van het deck, als anonieme bezoeken per versie.

    Voor wie zelf host

    Migratie 106 voegt de tabel slide_library_links toe; die is additief en heeft geen backfill. Gebruik je S3-opslag, controleer dan dat S3_PUBLIC_URL (of het afgeleide bucketadres) gelijk is aan het basisadres waar je decks naar verwijzen, en draai node scripts/scan-edition-input-size.js voordat je publiceert: die meet nu ook S3-objecten. De ongebruikte losse embed-SDK is verwijderd; embeds van edities blijven werken. Gebruik je de renderrunner (RENDERER_RUNNER_SOCKET), registreer dan de renderer van deze release zoals beschreven in docs/ops/renderer-runner.md.

  9. v1.94.0

    Edities die hetzelfde blijven

    Publiceren maakt een vaste editie met een eigen link. Latere bewerkingen blijven in je werkdocument; opnieuw publiceren krijgt een nieuw versienummer. Zelf hosten vraagt omzetting van bestaande links en aangepaste API-aanroepen.

    Publiceren legt nu een vaste editie vast: de slides, het thema, de beelden en de renderer horen bij die versie. Bewerk je het brondeck, dan blijft de gepubliceerde editie hetzelfde. Opnieuw publiceren maakt een nieuwe versie met een eigen link, canvas, reader en downloadbaar verificatiepakket. Depubliceren trekt alle edities van de reeks in; hun adressen geven dan een 410-antwoord.

    Samen bewerken

    Het Velden-formulier en de canvasselectie volgen het item dat je bewerkt als een medewerker het verplaatst. Een wijziging op afstand houdt de juiste titel voor jouw taal in beeld, inclusief het potloodje. Een deel van een taalversie opslaan wist de andere opgeslagen velden niet meer.

    Vóór het bijwerken

    Deze release verandert de publiceer-API en bevat databasemigraties 103-105. Maak eerst een backup en controleer dat je die kunt terugzetten. De migraties voegen opslag voor edities, intrekkingen en oude links toe, verwijderen de oude publicatiedescriptor uit decks en schrappen de verouderde previewinstelling. Het schema terugdraaien herstelt die gegevens niet.

    Bestaande publicatie- en embedlinks geven 404 tot je node scripts/migrate-publications-to-editions.js uitvoert. Begin zonder --apply, bewaar het rapport en beoordeel elke weigering, ook bronnen in de prullenbak. Voer daarna met --apply uit en test de oude links: ze verwijzen naar de eerste editie, ook nadat je latere versies publiceert. Controleer vervolgens oude previews met node scripts/sweep-published-previews.js --check voordat je --apply gebruikt.

    Publiceeraanroepen via de API vragen nu expectedRevision en idempotencyKey; een nieuwe editie geeft 201, een herhaalde aanvraag 200. De endpoints voor slugwijzigingen en previewregeneratie zijn verwijderd. Bezoeken aan edities verschijnen momenteel niet in de bezoekersstatistieken, en de oude embed-SDK-bediening werkt niet op editiecanvassen.

    Gebruik je RENDERER_RUNNER_SOCKET, registreer dan de renderer van deze release en controleer vóór het publiceren dat renderer-runner groen is in de doctor. Bewaar oudere rendererregistraties voor bestaande edities. Zie docs/ops/renderer-runner.md en de release 1.94.0 op GitHub voor de volledige upgradeaanwijzingen.

  10. v1.93.1

    De goede kaart

    Met live bewerken aan volgt het Velden-formulier een medewerker die items verplaatst, zodat wat je typt in de kaart belandt die je ziet; elke dialoog past op een telefoonscherm, en meer talen lezen natuurlijker.

    Met live bewerken aan volgt het Velden-formulier nu een medewerker die een item in een lijst verplaatst (een kaart, een tijdlijnpunt): zodra je het veld verlaat, staat je formulier in de nieuwe volgorde. Tot dat moment gaat wat je typt naar het item dat de rij toont, niet naar het item dat inmiddels op die plek staat. Vóór deze release kon een bewerking daar de tekst van een ander item in een andere taal overschrijven.

    Telefoons

    Elke dialoog blijft nu binnen het scherm van een telefoon: geen knoppen of velden meer die over de rand vallen.

    Talen

    Nederlandse actielabels gebruiken overal de infinitief, het Deens heeft één woord voor dupliceren, Portugese validatiemeldingen zijn direct in plaats van te openen met “Por favor”, en meldingen om het opnieuw te proberen volgen in het Duits, Spaans en Portugees het register van hun taal. Termen rond contentvelden zijn gelijkgetrokken in het Nederlands, Zweeds, Pools en de andere interfacetalen.

    Voor wie zelf host

    Er is geen migratie en geen nieuwe instelling. Gebruik je de renderrunner (RENDERER_RUNNER_SOCKET), registreer dan de renderer van deze release zoals beschreven in docs/ops/renderer-runner.md.

    Zie de release 1.93.1 op GitHub voor alle wijzigingen.

  11. v1.93.0

    Eén dia, of een paar

    Exporteer één dia of een selectie als PDF of als ZIP met PNG's, tabellen en live-bewerkingen houden elke taal gelijk, en een mislukt verzoek legt zich uit in de taal van je interface.

    De exportdialoog vraagt nu welke dia’s je wilt: alle, de huidige dia, of een selectie zoals 1,3-5, vooraf ingevuld met de dia’s die je in de dialijst hebt geselecteerd. De keuze geldt voor de dia-PDF en de ZIP met PNG’s; elk ander formaat exporteert nog steeds het hele deck. De bestandsnaam zegt welk deel erin zit, en een selectie die niet te exporteren is wordt direct onder de keuze uitgelegd.

    Vertaalde dia’s

    Een rij of kolom verwijderen in een tabel gebeurt nu in elke taalversie, en bewerkingen van medebewerkers tijdens een live-sessie komen per item in elke taal aan in plaats van de hele lijst te overschrijven. Na een bewerking in de Velden-weergave volgt de Inspector mee; na het verplaatsen van een item met het toetsenbord blijft de focus op dat item.

    Meldingen in je eigen taal

    Mislukt een verzoek zonder uitleg van de server, dan tonen de wachtwoordformulieren en zo’n dertig andere formulieren nu hun eigen vertaalde zin in plaats van een Engelse transportfout. Een geweigerde gedeelde link noemt de actieve taalversie. Poolse aantallen van twee tot vier gebruiken hun eigen naamval (“3 linki”).

    Verbeteringen

    Een dia die alleen live werkt, zoals de follow-along-uitnodiging, toont geen Toegankelijkheid-sectie meer die er niets te zoeken heeft, en de exportmelding over onvolledige dia’s herkent zulke dia’s ook. De opmerkingkaart op een plek in een dia post via het commentaarpaneel, zodat er één plek is waar je een opmerking schrijft.

    Voor zelfhosters

    Er is geen migratie en geen nieuwe instelling. De exportroutes voor de dia-PDF en de PNG-ZIP accepteren ?slides=1,3-5; een onleesbare selectie, of een selectie op een ander formaat, is een 400 invalid die het veld slides noemt. Gebruik je de renderer-runner (RENDERER_RUNNER_SOCKET), registreer dan de renderer van deze release zoals beschreven in docs/ops/renderer-runner.md.

    Zie de 1.93.0-release op GitHub voor alle wijzigingen.

  12. v1.92.1

    Elke taal, elke breedte

    Datums, aantallen en termen volgen de taal van je interface, de deeldialoog blijft heel op een telefoon en bij 200 % zoom, en een item verwijderen of verplaatsen in een vertaalde dia gebeurt nu in elke taal.

    Datums, tijden, relatieve tijden (“3 dagen geleden”) en aantallen volgen nu de taal van de interface, en termen gebruiken één woord per veld, status en instelling in alle talen. De interface zegt overal organisatie in plaats van soms werkruimte, en de Poolse deeldialoog schrijft zijn diakritische tekens.

    Smalle schermen en zoom

    Op 320 px breed, of bij 200 % zoom, houdt de deeldialoog de zichtbaarheidsopties, de uitnodigrij en de lijst met medewerkers binnen het Team-paneel; een rij die niet meer past, loopt door op een volgende regel in plaats van eruit te vallen. De acties in het meldingenpaneel en de eigendomsfilters boven je presentaties doen hetzelfde.

    Vertaalde dia’s

    Een item verwijderen, verplaatsen of omwisselen in een lijst (tijdlijnpunten, kaarten, een beeldenreeks) in één taalversie gebeurt nu ook in elke andere versie, zodat de versies niet meer uit elkaar lopen. Ontbrekende vertalingen aanvullen vertaalt elk gat apart, in plaats van tekst van naburige items te lenen.

    Reparaties

    Een galerij die een import, de AI of een agent zonder beelden maakt, krijgt geen demofoto’s meer. Een opmerking die je vanuit de lightbox opent, ziet eruit als de draad in het opmerkingenpaneel. Een veld schrijven dat een diatype niet kent, wordt in de editor en via MCP geweigerd met een duidelijke 400 unknown_field, zoals de publieke API al deed.

    Voor wie zelf host

    Er is geen migratie en geen nieuwe instelling. Gebruik je de renderrunner (RENDERER_RUNNER_SOCKET), installeer hem dan opnieuw vanuit deze release: de supervisor start nu bij het opstarten, zodat renderen na een herstart van de host terugkomt zonder handwerk. Registreer daarna de renderer van deze release zoals beschreven in docs/ops/renderer-runner.md.

    Zie de release 1.92.1 op GitHub voor alle wijzigingen.

  13. v1.92.0

    Controleer wat de AI maakte

    De AI-deckreview laat per dia zien waarom die er zo uitziet, citeert je bron waar dat kan en stelt voor waar een beeld hoort. Agents kunnen per dia een toelichting meegeven en je een reviewlink sturen. ImageKit-keuzes worden weer opgeslagen.

    Nadat de AI een deck heeft gemaakt van je tekst, bestand of Notion-pagina, toont de review elke dia naast de toelichting. Steunt die toelichting op je bron, dan citeert hij de passage waartegen hij is gecontroleerd; pas je een dia aan, dan meldt de toelichting dat hij over de eerdere versie gaat. Je kunt de review later vanuit de editor opnieuw openen.

    Beelden die je zelf kiest, geen stockfoto’s

    De AI vult een beeld niet meer met een stockfoto. Een dia die een beeld nodig heeft houdt een leeg beeldveld, de review biedt daar Afbeelding kiezen aan, en suggesties tussen dia’s laten je een beeldplek toevoegen of het idee negeren. Tot drie alternatieve diatypen blijven zichtbaar nadat je wisselt.

    Een dia waarvan het essentiële beeld nog leeg is, geldt als onaf. De editor bewaart hem, maar presenteren, elke export, publiceren en elk lezerskanaal laten hem weg; de editor noemt de overgeslagen dia’s voordat je presenteert of exporteert, en publiceren weigert met 422 incomplete_slides. PPTX, de handoff-ZIP en print laten nu ook concept- en niet-te-exporteren dia’s weg, zoals de andere formaten al deden.

    Een toelichting per dia van agents

    MCP-tools (create_presentation_from_slides, add_slide) en de publieke API (POST en PUT /presentations, POST /presentations/:id/slides) nemen per dia een reviewNote aan, tot 500 tekens. Die staat in de review, nooit in het deck zelf, en alleen voor wie het deck mag bewerken. Antwoorden bevatten een reviewUrl die de review opent; die link biedt nooit aan het deck weg te gooien. De publieke API weigert ruwe _ai*-sleutels met 400; een PUT zonder reviewNote behoudt de opgeslagen toelichting.

    Reparaties

    Een beeld kiezen uit ImageKit maakt een beelddia niet langer onopslaanbaar; migratie 102 bewaart imagekitFileId op beeld- en beeld-tekstdia’s in plaats van hem te verwijderen. Vier kernthema’s krijgen achtergrondvoorinstellingen voor titeldia’s. Termen voor delen, rollen, zoeken, bibliotheekacties, voortgang en fouten zijn consistenter in alle talen.

    Voor wie zelf host

    Er is geen nieuwe migratie. Een nieuwe optionele instelling, RENDERER_RUNNER_SOCKET, verbindt het renderen van bevroren edities met de Linux-renderrunner; zonder die instelling weigeren die renders, net als voorheen. Het Docker-image krijgt een stap voor de rendererbundel, en node scripts/doctor.js meldt de runner. De inrichting staat in docs/ops/renderer-runner.md.

    Zie de release 1.92.0 op GitHub voor alle wijzigingen.

  14. v1.91.1

    Doorschrijven bij validatiefouten

    Bestaande kwaliteitsfouten blokkeren andere bewerkingen niet meer en wisselen je bewerkingstaal niet. Expliciet herstel en een kopieerbaar foutrapport houden de regie bij jou.

    Een bestaande kwaliteitsfout, zoals een ongeldige datum in een andere taal, blokkeert andere bewerkingen niet meer en opent die taal niet automatisch. Bestaande hoofdinhoud blijft behouden; structurele metadata wordt waar nodig gericht genormaliseerd.

    Als inhoud herstel nodig heeft, biedt de editor een expliciete herstelactie en een kopieerbaar foutrapport, met een terugvaloptie wanneer het klembord niet beschikbaar is. Het rapport bevat de relevante fout en bewerkingscontext.

    AI-schrijftools bieden daarnaast optionele toegankelijkheidsvelden aan. Deze patch voegt geen configuratie, afhankelijkheden of databasemigraties toe. Wie vanaf 1.90.0 of eerder bijwerkt, leest eerst de upgrade-instructies voor 1.91.0 en maakt vóór migratie 102 een back-up.

    Bekijk de 1.91.1-release op GitHub voor alle wijzigingen.

  15. v1.91.0

    Eenduidige diavelden

    De editor, API en MCP weigeren onbekende velden voortaan op dezelfde manier. Maak voor de upgrade een back-up: migratie 102 verwijdert ongebruikte opgeslagen sleutels. Vertalingen en smalle schermen zijn verbeterd.

    De editor, publieke API en MCP-tools gebruiken voortaan dezelfde lijst met toegestane inhoudsvelden per diatype. Een onbekende sleutel op het hoogste niveau van de dia-inhoud wordt geweigerd met unknown_field; de publieke inhoudsschema’s leggen dezelfde beperking vast via propertyNames. Integraties moeten niet-ondersteunde sleutels verwijderen voordat ze een dia toevoegen of bijwerken.

    Maak voor de upgrade een back-up

    Migratie 102 verwijdert niet-gedeclareerde sleutels uit opgeslagen decks en hun taalversies, bewaarde versies, reactiesnapshots en bibliotheekdia’s met vertalingen. Oude invoer die de normale migratiestappen nog gebruiken blijft behouden, net als dia’s waarvan het type niet kan worden gevonden. Bij gewijzigde decks wordt de samenwerkingscache bij de volgende keer openen opnieuw opgebouwd. Het migratielog vermeldt elk verwijderd type/sleutelpaar; een terugmigratie herstelt de verwijderde waarden niet.

    Het ongebruikte payoff-veld tagline en content.videoOverride per dia worden niet meer gelezen. Gebruik de gedeclareerde velden van het diatype en de ingestelde live-videolaag. Er zijn geen nieuwe omgevingsinstellingen of pakketafhankelijkheden.

    Aangepaste velden bewust verwijderen

    Bij het verwijderen of hernoemen van een aangepast veld dat nog in gebruik is, zie je eerst welke inhoud geraakt wordt. API-clients krijgen 409 field_in_use met gebruiksaantallen. Na bevestiging, of met ?force=true, verdwijnt het veld in één bewerking uit opgeslagen inhoud en geopende samenwerkingsdocumenten. Andere gelijktijdige wijzigingen blijven behouden. Schrijfacties controleren de vastgelegde velddefinities en worden per organisatie na elkaar uitgevoerd; de doorvoer is nog niet gemeten.

    Duidelijkere termen in alle talen

    Analysemetingen, aangepaste diatypen, hoekvormen, weergave, typografie en uitlijning gebruiken consistentere termen. Een deck naar de prullenbak verplaatsen wordt niet meer aangekondigd als onomkeerbaar. Layouttegels, themakaarten en versieacties passen ook beter op smalle schermen.

    Voor bijdragers legt de vertaalcontrole nu vast bij welke Engelse brontekst en vertaalde waarde een beoordeling hoort. Zo is zichtbaar welke paren opnieuw beoordeeld moeten worden. Dit betekent niet dat alle vertalingen al beoordeeld zijn.

    Zie de release 1.91.0 op GitHub voor alle wijzigingen.

  16. v1.90.0

    Meer mailproviders

    Verstuur transactionele mail via SMTP, Brevo, Scaleway TEM of Mailgun. Bestaande Brevo-installaties hebben vóór de upgrade aangepaste configuratie nodig.

    Deckyard kan uitnodigingen, inloglinks en meldingen versturen via SMTP, Brevo, Scaleway TEM of Mailgun. Je kiest het transport expliciet en gebruikt bij iedere provider dezelfde afzenderinstellingen.

    Pas de mailconfiguratie aan vóór de upgrade

    Bestaande Brevo-installaties moeten MAIL_TRANSPORT=brevo toevoegen, BREVO_API_KEY behouden, BREVO_SENDER_EMAIL hernoemen naar MAIL_FROM en BREVO_SENDER_NAME naar MAIL_FROM_NAME. De oude namen werken niet meer. Opgeslagen afzenderinstellingen van de installatie blijven ondersteund en gaan vóór de omgevingsvariabelen.

    Kies MAIL_TRANSPORT=smtp, scaleway of mailgun met de bijbehorende providerinstellingen, of MAIL_TRANSPORT=none om uitgaande mail uit te schakelen. Alleen inloggegevens instellen selecteert geen provider meer. De configuratievoorbeelden en doctor-check leggen uit welke instellingen ontbreken of onvolledig zijn; de testmail in het beheer gebruikt dezelfde effectieve afzender als gewone mail.

    Inloggen via SSO en bestaande wachtwoorden blijven bruikbaar zonder mail. Uitnodigingen, meldingen, wachtwoordherstel, inloglinks en het instellen van een nieuw wachtwoordaccount hebben een werkend transport nodig. Bij een uitnodiging zie je nu wanneer bezorging niet beschikbaar was of mislukte.

    Forks en installatie

    Forks die de verwijderde module server/integrations/brevo.js importeren, moeten overstappen op server/integrations/email/index.js. Er is geen databasemigratie of nieuwe pakketafhankelijkheid. SMTP ondersteunt geauthenticeerde TLS-verbindingen; API-transports gebruiken de vaste endpoints van hun provider.

    Ook de opnamerecepten zijn bijgewerkt voor de huidige editor, met vertaaldemonstraties en vijf documentatieweergaven. Dit betreft de opnametools; vernieuwde websitebeelden worden afzonderlijk na review gepubliceerd.

    Bekijk de 1.90.0-release op GitHub voor alle wijzigingen.

  17. v1.89.1

    Opslaan en importeren hersteld

    Lange beeldbeschrijvingen blokkeren opslaan niet meer. Onderbroken imports stoppen netjes, deckbeschrijvingen zijn weer doorzoekbaar en de themalijsten van API en MCP volgen de organisatie-instellingen.

    Deze release herstelt het opslaan van decks met lange beeldbeschrijvingen en verbetert importeren, zoeken en themakeuze.

    Lange beeldbeschrijvingen blokkeren opslaan niet meer

    Een alttekst boven de veldlimiet verhindert niet meer dat het hele deck wordt opgeslagen. Beschrijvingen worden op een woordgrens ingekort met een beletselteken, binnen de gedeelde limiet van 180 tekens. Dat geldt ook voor bestaande beschrijvingen, geneste afbeeldingsvelden en vertalingen. AI-gegenereerde altteksten volgen dezelfde limiet. De limieten van andere velden blijven gelden.

    Importeren, zoeken en thema’s

    • Onderbroken bestands- en Notion-imports stoppen en geven de bediening terug aan het formulier. Ze versturen niet automatisch een nieuw aanmaakverzoek wanneer de uitkomst onzeker is.
    • Zoeken in metadata vindt decks weer op hun beschrijving.
    • De publieke API en MCP bieden de thema’s aan die voor de actieve organisatie zijn ingesteld, net als de editor. Bestaande decks behouden hun thema.

    Er is geen nieuwe databasemigratie of vereiste configuratie. Zie de release 1.89.1 op GitHub voor de details.

  18. v1.89.0

    Beheer past op kleinere schermen

    Statistieken en gebruikersbeheer blijven bruikbaar op smalle schermen en met grotere tekst. Forks die twee renderfuncties importeren, moeten hun importpaden aanpassen.

    Statistieken en gebruikersbeheer op kleinere schermen

    Koppen bij statistieken, acties in het gebruikersbeheer en knoppen voor paginering lopen nu door op een volgende regel of staan onder elkaar als de ruimte opraakt. Labels blijven zichtbaar bij 320 pixels breed en 200% tekst. De knoppen voor paginering zijn minimaal 44 pixels hoog.

    Brekende wijzigingen voor forks

    Pas deze imports aan als je fork de functies gebruikt:

    • Importeer escapeHtml uit shared/slide-types/helpers.js; de herexport vanuit server/utils/html-utils.js vervalt.
    • Importeer themeVarsCssText uit server/utils/theme-vars-css.js; de herexport vanuit server/utils/themes.js vervalt.

    Rendererbundels: architectuurproef

    Deze release voegt de architectuurproef toe voor bevroren rendererbundels met een inhoudshash. Het uitvoeren van historische rendercode blijft in productie uitgeschakeld totdat er een runner met isolatie op besturingssysteemniveau is. Deze release schakelt onveranderlijke publicatie-edities nog niet in.

    Er is geen nieuwe databasemigratie of vereiste configuratie. Zie de release 1.89.0 op GitHub voor de details.

  19. v1.88.0

    Ingetrokken toegang sluit ook de statistieken

    Een verwijderde samenwerker verliest nu ook toegang tot de statistieken en het weekoverzicht van het deck. De resterende lijsten laden per pagina. Forks die interne lijst-API’s of opslagfuncties gebruiken, moeten hun aanroepen aanpassen.

    Ingetrokken samenwerkers verliezen toegang tot statistieken

    Als de bewerk- of beheerrechten van een samenwerker op een deck worden ingetrokken, verdwijnt dat deck uit diens statistiekendashboard en wekelijkse e-mailoverzicht. Beide gebruiken nu dezelfde toegangscontrole. Eigenaarschap geeft nog steeds toegang; een deck alleen mogen bekijken of erop reageren geeft geen dashboard.

    De resterende lijsten laden per pagina

    Bezoekerssessies, statistiekenrapporten, de decklijst van het dashboard, organisatieleden en gebruikers in het beheer laden nu per pagina. Leden en gebruikers staan met de nieuwste bovenaan; de decklijst van het dashboard toont het laatst gewijzigde deck eerst. De ledenlijst houdt een aparte totaalteller en laadt meer leden zonder de al zichtbare rijen te vervangen.

    Brekende wijzigingen voor forks

    Forks die de interne lijst-API’s aanroepen, gebruiken voortaan limit en cursor en lezen de benoemde lijst en nextCursor uit het antwoord. offset wordt geweigerd en total vervalt. De dashboardlijst weigert ook sort; ranglijsten blijven beschikbaar bij de toppresentaties van het dashboard. Het aantal leden heeft een eigen endpoint: GET /api/organizations/:id/members/count. De publieke v1-API en MCP-contracten veranderen in deze release niet.

    Ook imports van opslagfuncties vragen aanpassing:

    • In server/storage/analytics/index.js of de onderliggende modules wordt getViewSessionsForPresentation vervangen door listViewSessions, en getPresentationsWithAnalytics door listDashboardPresentations. ANALYTICS_LIST_SORTS vervalt.
    • Deze functies, listAnalyticsReports, listOrganizationMembers en listUsers vereisen een pagina-argument en geven { items, next } terug.
    • parsePaginationParams vervalt uit server/utils/request-validators.js. Gebruik parseListPage, of parseListLimit voor een begrensde zoekopdracht, uit server/services/list-page.js.

    Voor zelfhosters

    Migratie 101 vult ontbrekende aanmaaktijdstippen aan bij statistiekenrapporten, organisatielidmaatschappen en gebruikers, maakt die kolommen verplicht en voegt de indexen voor paginering toe of vervangt ze. Er worden geen rijen verwijderd. De migratie draait bij het opstarten. Maak vooraf een databaseback-up; het aanmaken van indexen kan tijdens de migratie vergrendelingen vasthouden. Er zijn geen nieuwe dependencies of configuratie-instellingen. Zie de release 1.88.0 op GitHub voor de details.

  20. v1.87.0

    PowerPoint wordt bewerkbare slides

    Importeer een PowerPoint-bestand en krijg bewerkbare slides, met of zonder de PDF-export erbij. Opmerkingen en de activiteitenfeed laden nu een pagina tegelijk. Deze release verandert de opmerkingen-endpoints van de publieke API en MCP: lees de notities voordat je een koppeling bijwerkt.

    Een PowerPoint-bestand wordt bewerkbare slides

    De import die een deck omzet in bewerkbare slides leest nu rechtstreeks een .pptx: koppen, lijsten, tabellen, afbeeldingen en kleuren komen uit het PowerPoint-bestand zelf, overgeërfd via de lay-outs en het thema. Voeg je de PDF-export toe, dan levert die het beeld van elke pagina die Deckyard niet kan nabouwen; beide bestanden moeten evenveel zichtbare slides hebben. Een .pptx alleen werkt ook: een pagina die niet na te bouwen is, houdt zijn kop en tekst op een tekstslide, en het importverslag meldt dat de PDF-export je een beeld van die pagina’s zou geven. Afbeeldingen die als SVG, EMF of WMF zijn opgeslagen, noemt het verslag als ze achterblijven.

    Opmerkingen en activiteit laden een pagina tegelijk

    Het opmerkingenpaneel, de opmerkingen bij een gedeelde link en het tabblad Activiteit tonen een eerste pagina en laden meer terwijl je verder gaat, in plaats van alles tegelijk op te halen. De activiteitenfeed bevat alleen nog gebeurtenissen op decks die jij mag openen, en elke pagina is vol zolang er meer is.

    Brekend: opmerkingenlijsten in de publieke API en MCP

    GET /api/v1/presentations/{id}/comments en de MCP-tools list_comments en list_recent_comments gaan op het paginacontract dat de andere lijsten in 1.85.0 en 1.86.0 kregen. Stuur limit mee en, voor de volgende pagina, de cursor die je terugkreeg; het antwoord is { comments, nextCursor }, nieuwste eerst, en op de laatste pagina is nextCursor null. Op een deck telt een pagina gesprekken, elk met al zijn antwoorden.

    • total is weg, en offset ook: een verzoek met offset wordt geweigerd met 400 en de hint om cursor te gebruiken.
    • limit moet tussen 1 en 100 liggen. Voor de MCP-tools was dat 200.

    Een koppeling die total las of met offset door opmerkingen stapte, moet worden aangepast. De nieuwe vorm staat in de OpenAPI-beschrijving en de MCP-referentie.

    Kleinere reparaties

    • Het aantal decks bij een tag in Presentaties telt geen decks in de prullenbak meer mee.
    • Een slide van een type dat deze installatie niet heeft, houdt bij import de tekst van elke taalversie, lijsten inbegrepen, in plaats van overal de basistaal te herhalen.

    Voor zelfhosters

    Deze release draait migraties 099 en 100. 099 geeft elke activiteitsgebeurtenis een aanmaaktijd waar die ontbrak, maakt die kolom verplicht en vervangt de index achter de activiteitenfeed. 100 doet hetzelfde voor opmerkingen en voegt de twee indexen achter de opmerkingenlijsten toe. Beide draaien vanzelf bij het opstarten en vragen niets van je. Geen nieuwe dependency en geen configuratiewijziging. De details per commit staan in de 1.87.0-release op GitHub.

  21. v1.86.0

    Elke lijst bladert vanaf de server

    Home, gedeeld met mij, de prullenbak, de slidebibliotheek, collecties en de beeldbibliotheek laden nu pagina voor pagina, met filters en zoeken uitgerekend door de server. Deze release verandert de publieke API: lees de notities voordat je een koppeling bijwerkt.

    Lijsten die een pagina tegelijk laden

    Home, gedeeld met mij en de prullenbak laadden elk deck tegelijk en filterden ze in je browser. Ze tonen nu een eerste pagina en een knop Meer laden, en de filters, tags en zoekopdrachten beantwoordt de server, zodat een grote organisatie ze even snel opent als een kleine. Omdat de app niet meer elk deck vasthoudt, zijn de aantallen op de filterchips, het aantal decks op Home en het sorteren op titel verdwenen.

    De slidebibliotheek, collecties en de beeldbibliotheek werken net zo. Hun filterchips en taglijsten komen van de server, zoeken gebeurt daar terwijl je typt, en een collectie laadt alleen de slides die jij mag zien. Een selectie die je in de kiezer maakte, blijft staan als je zoekt of filtert.

    Brekend: GET /api/v1/slide-library en GET /api/v1/image-library

    Beide bibliotheek-endpoints gaan op het paginacontract dat GET /api/v1/presentations in 1.85.0 kreeg. Stuur limit mee en, voor de volgende pagina, de cursor die je terugkreeg; het antwoord is { items, nextCursor } voor de slidebibliotheek en { images, nextCursor } voor de beeldbibliotheek, en op de laatste pagina is nextCursor null. Nieuwste eerst.

    • offset, total en het object pagination zijn weg. Een verzoek met offset wordt geweigerd met 400 en de hint om cursor te gebruiken.
    • limit moet tussen 1 en 100 liggen. Een waarde daarbuiten wordt geweigerd met 400 in plaats van stil afgekapt.
    • De lijst categories zit niet meer in het antwoord van de beeldbibliotheek. Vraag hem op bij GET /api/v1/image-library/categories.

    Een koppeling die total, pagination of categories las, of met offset door pagina’s stapte, moet worden aangepast. De nieuwe vorm staat in de OpenAPI-beschrijving.

    Voor zelfhosters

    Deze release draait migraties 097 en 098. 097 voegt een index toe achter de prullenbak. 098 geeft elk bibliotheekitem, elke collectie en elke afbeelding een aanmaaktijd (het tijdstip van laatste wijziging, of nu, waar die ontbrak), maakt die kolom verplicht, slaat de uploader van een afbeelding op in dezelfde genormaliseerde vorm als elk ander adres, en voegt de indexen toe achter de drie bibliotheeklijsten. Beide draaien vanzelf bij het opstarten en vragen niets van je. Geen nieuwe dependency en geen configuratiewijziging. De details per commit staan in de 1.86.0-release op GitHub.

  22. v1.85.0

    De decklijst bladert met een cursor

    De publieke API en de MCP-server geven decks pagina voor pagina met een cursor, uit één databasequery die bepaalt wie welk deck ziet. Deze release verandert de publieke API: lees de notities voordat je een koppeling bijwerkt.

    Een decklijst die op elke omvang overeind blijft

    Welke decks je ziet, werd bepaald nadat de server elk deck in je organisatie had gelezen. Eén databasequery beslist het nu, gesorteerd op laatste wijziging met een vaste tiebreak, zodat de lijst snel blijft als een organisatie groeit en twee decks die op hetzelfde moment zijn opgeslagen altijd in dezelfde volgorde terugkomen. Een deck dat met je gedeeld is, houdt ook in elke lijst zijn deelgegevens, ook als het daarnaast zichtbaar is voor je hele organisatie. In de app zelf verandert in deze release niets.

    Brekend: GET /api/v1/presentations

    De publieke decklijst gaat op hetzelfde paginacontract als de rest van de API. Stuur limit mee en, voor de volgende pagina, de cursor die je terugkreeg; het antwoord is { presentations, nextCursor }, en op de laatste pagina is nextCursor null. Decks komen op volgorde van laatste wijziging, nieuwste eerst.

    • offset en het object pagination zijn weg. Een verzoek met offset wordt geweigerd met 400 en de hint om cursor te gebruiken.
    • limit moet tussen 1 en 100 liggen. Een waarde daarbuiten wordt geweigerd met 400 in plaats van stil afgekapt.

    Een koppeling die pagination.total las of met offset door pagina’s stapte, moet worden aangepast. De nieuwe vorm staat in de OpenAPI-beschrijving.

    MCP: list_presentations

    De MCP-tool list_presentations neemt een cursor en geeft nextCursor terug om de volgende pagina op te halen. Hij geeft geen total meer terug.

    Voor zelfhosters

    Deze release draait migratie 096: een deck zonder tijdstip van laatste wijziging krijgt zijn aanmaaktijd, die kolom wordt verplicht en de index achter de decklijst wordt vervangen door een die de nieuwe volgorde per organisatie bedient. De migratie draait vanzelf bij het opstarten en vraagt niets van je. Geen nieuwe dependency en geen configuratiewijziging. De details per commit staan in de 1.85.0-release op GitHub.

  23. v1.84.0

    Al je meldingen, niet alleen de laatste twintig

    De meldingenbel heeft nu een regel Meer laden, zodat oudere meldingen bereikbaar blijven, en een deck importeren waarvan het thema een titelslide gebruikt die deze installatie niet heeft, mislukt niet meer.

    Meer laden in je meldingen

    De meldingenbel toonde je twintig nieuwste meldingen en niets ouder. Hij eindigt nu met een regel Meer laden die de volgende twintig ophaalt, in elke weergave (Alles, Ongelezen, Mentions, Gearchiveerd). De lijst blijft op volgorde en toont elke melding één keer, ook als er nieuwe binnenkomen terwijl je scrolt. Archiveer je de meldingen die je ziet, dan schuiven de volgende op, in plaats van dat de bel zegt dat er niets meer is.

    Een deck importeren met een onbekend thema

    Een .deck-bestand importeren waarvan het thema nieuwe decks opent met een titelslide die deze installatie niet heeft, mislukte met een serverfout. De import lukt nu: slides van een onbekend type komen binnen als tekstslides die het type noemen, en een nieuw deck in dat thema opent op de standaard titelslide. Een geïmporteerd deck krijgt ook geen extra titelslide meer vóór zijn eigen slides.

    Voor API-gebruikers en zelfhosters

    Deze release draait migratie 095: elke melding zonder aanmaaktijd krijgt het vroegste moment waarop ze aantoonbaar bestond, die kolom wordt verplicht en de index voor de meldingenlijst wordt vervangen. De migratie draait vanzelf bij het opstarten en vraagt niets van je.

    Het interne endpoint GET /api/notifications bladert nu met een ondoorzichtige cursor en geeft nextCursor terug; offset wordt geweigerd met de hint om cursor te gebruiken. Het lijstfilter heeft één vorm, filter=all|unread|mentions|archived: het oude unread=true en onbekende filterwaarden worden geweigerd in plaats van genegeerd. De publieke /api/v1 verandert in deze release niet. Geen nieuwe dependency en geen configuratiewijziging. De details per commit staan in de 1.84.0-release op GitHub.

  24. v1.83.5

    Een geïmporteerde PDF lijkt meer op het origineel

    Een PDF importeren als bewerkbare slides volgt nu de opmaak en achtergrond van elke pagina, knipt een grafiek naast tekst uit als beeld, houdt een tabel naast tekst als tekst en laat een logo dat op elke pagina terugkomt weg.

    Geïmporteerde slides volgen hun pagina

    Importeer je een PDF als bewerkbare slides, dan neemt elke slide de keuzes over die de pagina al maakte, voor zover het slidetype ze biedt. Een beeld naast tekst houdt ongeveer zijn breedte (smal, half of breed), en een klein beeld in een hoek blijft in de hoek. Tekst in twee kolommen wordt een slide met twee kolommen. Een hoofdstuktitel houdt zijn plek boven, in het midden of onderaan de pagina en blijft gecentreerd als hij dat was. Een pagina met een donkere of getinte achtergrond krijgt een passende achtergrond uit je thema. Lettertypen en exacte kleuren gaan niet mee: de slide blijft in je thema.

    Grafieken en tabellen naast tekst

    Een pagina met een kop, tekst en een grafiek of diagram werd een afbeelding van de hele pagina. Staat de grafiek los van de tekst, dan wordt hij nu als beeld uit de pagina geknipt en blijft de tekst ernaast bewerkbaar. Een tabel naast tekst wordt niet meer voor een tekening aangezien: hij wordt een tekstslide met de tabel erin.

    Logo’s en andere terugkerende tekens

    Een klein beeld dat op drie pagina’s of meer op dezelfde plek staat, zoals een logo in een hoek, wordt uit de geïmporteerde slides weggelaten, en het importrapport meldt dat één keer. Het maakt niet langer van elke pagina een beeld naast tekst.

    Een duidelijker importrapport

    Een pagina waarvan het beeld niet op een slide paste, staat nu in het rapport als te lang, in plaats van een tekstslide te worden zonder het beeld. Fouten in het rapport verschijnen nu in de taal van je interface.

    Vertaalweergave

    De achtergrondinstellingen die bij de achtergrondafbeelding van een slide horen, worden niet meer als tekst aangeboden om te vertalen en tellen niet meer als ontbrekende vertaling.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen configuratiewijziging. De details per commit staan in de 1.83.5-release op GitHub.

  25. v1.83.4

    De vertaalweergave toont alleen velden met tekst

    Naast elkaar vertalen opent nu op de velden die in minstens één taal tekst hebben. Lege rijen blijven uit beeld tot je "Alle velden" kiest, en de tekst "No suggestion yet" is weg.

    Alleen de velden die vertaald moeten worden

    De vertaalweergave toonde elk veld dat een slide kan hebben, ook de velden die in beide talen leeg waren: een tussenkop die je nooit invulde, een lege zijnotitie, een ongebruikt toegankelijkheidsveld. Op een echt deck betekende dat scrollen langs rijen zonder iets om te vertalen. De weergave opent nu op een nieuw standaardfilter, “Velden met tekst”, dat rijen verbergt die in beide talen leeg zijn. Elke slide blijft in de index staan, dus naar een slide springen werkt zoals voorheen; een slide zonder tekst zegt dat ook. Kies “Alle velden” in het filter om de lege rijen terug te halen.

    Minder ruis in de suggestiekolom

    Een veld zonder suggestie toont niet langer “No suggestion yet”. De knop “Veld voorstellen” heeft nu een eigen plek in de cel, zodat hij niet meer tegen de suggestietekst aan staat, ook niet op een smal scherm of bij een grote zoomfactor.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen configuratiewijziging. De details per commit staan in de 1.83.4-release op GitHub.

  26. v1.83.3

    Een ingetrokken preview verdwijnt ook uit je bucket

    Met een S3-compatibele bucket voor media wordt de gegenereerde deelpreview van een gepubliceerd deck nu uit de bucket verwijderd zodra de publicatie hem niet meer draagt: bij depubliceren, opnieuw publiceren en het opnieuw genereren van de preview.

    Een ingetrokken preview wordt uit de bucket verwijderd

    Als je een deck publiceert, maakt Deckyard een deelpreview: de afbeelding die een link toont in chat-apps en op sociale media. Met de ingebouwde lokale opslag werd die afbeelding al alleen geserveerd zolang de publicatie bestond. Met een S3-compatibele bucket beantwoordt de bucket het adres van de afbeelding zelf, zodat een preview bereikbaar bleef nadat je het deck depubliceerde, opnieuw publiceerde of de preview opnieuw liet genereren. Deckyard verwijdert dat object nu uit de bucket zodra de publicatie het niet meer draagt. Het raakt alleen previews die het voor die publicatie maakte: een afbeelding die je zelf koos en je andere uploads blijven staan.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen nieuwe of verplichte configuratie. Bewaar je media in een S3-compatibele bucket, ruim dan eenmalig de previews van vóór deze release op: draai node scripts/sweep-published-previews.js --check om te zien wat er weg zou gaan, daarna --apply. Een kopie in een CDN- of crawlercache valt buiten het bereik van Deckyard. Met de lokale provider hoef je niets te doen. Forks met een eigen mediaprovider implementeren de nieuwe methode MediaProvider.withdrawPublicObject(url). De details per commit staan in de 1.83.3-release op GitHub.

  27. v1.83.2

    Een getypte vertaling heet niet meer vanzelf "Huidig"

    In de vertaalweergave beweert een vertaling die je met de hand typt niet meer dat ze bij haar brontekst past. Alleen een geaccepteerde suggestie markeert een veld als "Huidig".

    Een getypte vertaling claimt niet dat ze actueel is

    De vertaalweergave laat per veld zien of een vertaling bij haar brontekst past. Typen in een van beide kolommen werd vastgelegd alsof het een geaccepteerde vertaling was, zodat een met de hand getypte tekst “Huidig” kon tonen zonder dat iemand haar naast de bron had gelegd. Typen legt nu niets meer vast: alleen een geaccepteerde suggestie markeert een veld als “Huidig”. Een veld met “Bron gewijzigd” blijft zo staan nadat je het met de hand verbetert, tot je er een verse suggestie voor accepteert, zodat het signaal dat de bron veranderd is niet verloren gaat.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen nieuwe of verplichte configuratie. De details per commit staan in de 1.83.2-release op GitHub.

  28. v1.83.1

    Een gedupliceerde presentatie blijft een kopie, en de vertaalweergave bewaart elke wijziging

    Een meertalige presentatie dupliceren noemt de kopie nu in elke taalversie een kopie, en de vertaalweergave bewaart een wijziging in een slidetekst in de brontaal, ook als die tekst nog geen vertaling heeft.

    Een duplicaat houdt zijn naam in elke taal

    Een presentatie dupliceren gaf de kopie alleen aan de oppervlakte de naam “Kopie van …”. In een presentatie met meer dan één taalversie kreeg de kopie haar oorspronkelijke naam terug zodra je haar opende of opsloeg, zodat je twee presentaties met dezelfde titel had. Elke taalversie van de kopie heet nu een kopie in haar eigen taal (“Kopie van …” in het Nederlands, “Copy of …” in het Engels), en die naam blijft staan.

    De vertaalweergave bewaart wijzigingen in de brontaal

    In de vertaalweergave werd een wijziging in een slidetekst in de bronkolom niet bewaard als die tekst in de andere taal nog geen tegenhanger had, bijvoorbeeld een veld dat nooit vertaald was. Die wijziging wordt nu bewaard. Een geaccepteerde vertaalsuggestie legt nog steeds vast uit welke brontekst ze komt, en vergrendelde slides weigeren nog steeds wijzigingen.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen nieuwe of verplichte configuratie. De details per commit staan in de 1.83.1-release op GitHub.

  29. v1.83.0

    Rechten van een API-sleutel wijzigen, zonder nieuwe sleutel

    Een bestaande API-sleutel heeft nu een knop Rechten bewerken in Instellingen → API-sleutels, zodat een koppeling een nieuwe scope zoals reacties of samenwerkers krijgt zonder dat de sleutel vervangen hoeft te worden.

    De rechten van een bestaande API-sleutel bewerken

    Tot nu toe lagen de rechten van een API-sleutel vast zodra je hem aanmaakte. Elke nieuwe opt-in-scope, zoals comments:read of collaborators:write, betekende een nieuwe sleutel maken en elke koppeling bijwerken die de oude gebruikte. In Instellingen → API-sleutels staat nu bij elke actieve sleutel Rechten bewerken: vink dezelfde rechten aan of uit die je bij het aanmaken zag en sla op. De sleutel zelf blijft dezelfde, en toepassingen die hem gebruiken krijgen de nieuwe rechten bij hun volgende verzoek.

    De wijziging komt in je activiteitenoverzicht op Home, met de rechten die erbij kwamen en die vervielen. Koppelingen kunnen hetzelfde via de API doen met PATCH /api/api-keys/:id. Op een smal scherm lopen de acties bij een sleutel nu als hele knoppen door naar de volgende regel, in plaats van dat hun labels in elkaar worden gedrukt.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen nieuwe of verplichte configuratie. Achter de schermen herstelt deze release ook het screenshotrecept voor de pagina met presentatie-instellingen en slaat CI zijn vervolgjobs over als een run wordt geannuleerd. De details per commit staan in de 1.83.0-release op GitHub.

  30. v1.82.0

    Een uitgang uit de sandbox, een smallere invoegnaad

    De sandboxbanner wijst nu naar Deckyard zelf installeren en naar gehoste Deckyard; een slide tussen twee andere invoegen gaat vanuit een dunne naad, en de miniaturen in de slidelade vullen hun kaart op elke breedte.

    Van uitproberen naar zelf hosten

    De banner op de publieke sandbox zei alleen wanneer je werk zou verlopen. Nu toont hij ook de volgende stap: Installeer Deckyard zelf opent de quickstart voor zelf hosten in een nieuw tabblad, zodat je sandboxwerk blijft staan, en Of laat ons het voor je hosten opent een mail om naar hosting te vragen. Beide links staan op Home en in de editor. Het publiek ziet ze nooit: presenteren, het presentatievenster en meekijken blijven zonder banner. Op een smal scherm staan de twee links onder elkaar, elk met een volledig aanraakdoel.

    Invoegen tussen slides vanuit een dunne naad

    Tussen twee slides in de slidelijst van de editor zit nu een dunne naad in plaats van een vaste strook. Ga eroverheen en de buurslides krimpen even om plaats te maken voor een volledig zichtbare +; klik en de nieuwe slide komt precies daar. Zolang je niets invoegt kost de lijst geen ruimte, en de aanraak- en railweergave werken zoals voorheen.

    Miniaturen die hun kaart vullen

    De miniaturen in de slidelade krijgen hun maat nu van de breedte die ze echt op het scherm krijgen. Ze vullen hun kaart op elke vensterbreedte, na het breder of smaller slepen van de lade, op 200% zoom en in de smalle lade op een telefoon, in plaats van een lege rand te laten of afgesneden te worden.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen nieuwe of verplichte configuratie. De sandboxlinks verschijnen alleen op een instantie die met SANDBOX_MODE draait. De details per commit staan in de 1.82.0-release op GitHub.

  31. v1.81.0

    MCP-agents delen een deck privé

    Een AI-agent die via MCP verbonden is, ziet nu wie privé toegang heeft tot een deck en kan één collega toegang geven, zonder het deck te publiceren; beide tools vragen een recht dat je expliciet aan de API-sleutel toekent.

    Een deck privé delen vanuit een agent

    Twee nieuwe MCP-tools doen voor een agent wat de deeldialoog in de editor voor jou doet. list_collaborators laat zien wie privé toegang heeft tot een deck, met naam en recht. add_collaborator geeft één bestaand lid van je organisatie view-, comment-, edit- of admin-toegang.

    Beide volgen dezelfde regel als de editor: alleen wie de medewerkers van een deck mag beheren (de eigenaar, de maker of een medewerker met admin) mag de lijst lezen of iemand toevoegen. De agent handelt als de persoon in wiens sessie hij draait, nooit met de rechten van wie de API-sleutel bezit.

    • Privé blijft privé. Een medewerker toevoegen verandert niets aan de zichtbaarheid van het deck of aan de deellinks. Publiceren is een aparte handeling.
    • Alleen bestaande collega’s. De genodigde moet al gebruiker zijn in de organisatie van het deck. Onbekende adressen, mensen uit een andere organisatie en je eigen adres worden geweigerd, en er wordt niets weggeschreven.
    • Herhalen kan veilig. Twee keer dezelfde aanroep verandert de tweede keer niets. Wie al een ander recht heeft, houdt dat; de tool wijzigt nooit een bestaand recht.
    • Alleen mail als erom gevraagd wordt. Elke toekenning verschijnt als melding in de app en in de activiteit van het deck, net als in de editor. De uitnodigingsmail gaat alleen weg als de agent erom vraagt met sendInvitation: true.

    Nieuwe rechten voor API-sleutels

    De tools komen met twee nieuwe rechten op een API-sleutel: collaborators:read voor list_collaborators en collaborators:write voor add_collaborator. Beheren wie toegang heeft is een eigen recht, dus een sleutel die al decks mag bewerken kan ze pas delen als je deze rechten toekent in Instellingen → API-sleutels. Bestaande sleutels krijgen er niets bij, en een agent ziet alleen de tools die zijn sleutel mag aanroepen.

    Voor zelfhosters

    Geen migratie, geen nieuwe dependency en geen nieuwe of verplichte configuratie. De MCP-server biedt nu 29 tools. De details per commit staan in de 1.81.0-release op GitHub.

  32. v1.80.0

    Deckinstellingen als paneel, deellinklog verwijderd

    De deckinstellingen openen als zijpaneel in de editor met een eigen adres, naast de slidepreview; het verificatielog van deellinks, dat van elke bezoeker het IP-adres en de user-agent bewaarde, is weg.

    Deckinstellingen in een zijpaneel

    De instellingen van een deck zijn geen dialoog meer. Ze openen vanuit het ⋯-menu van de editor als paneel aan de rechterkant, terwijl de slidepreview ernaast zichtbaar blijft. Op een smal scherm opent het paneel als lade.

    Het paneel heeft een eigen adres. Herladen, terug en vooruit brengen je bij hetzelfde paneel en dezelfde sectie, en een link ernaar werkt, ook met een taalroute in de URL. De brontaal van een deck staat in het paneel als alleen-lezen. Opgeslagen waarden en rechten op de server veranderen niet.

    Tot nu toe schreef elke geslaagde verificatie van een deellink het IP-adres en de ruwe user-agent van de bezoeker weg in een apart log, buiten de analytics-schakelaar en zonder opruiming. Niets in Deckyard las dat log. Het wegschrijven is gestopt, en de interne route die het kon lezen, GET /api/presentations/:id/share-links/:linkId/access-log, is weg.

    Deellinks houden hun eigen gebruikstelling en het moment van laatste gebruik, en analytics blijft het enige record van wie een deck bekeek. Dit is de tweede stap van de privacyronde over bezoekersgegevens die in 1.79.0 begon; de rest van dat werk hoort niet bij deze release.

    Voor zelfhosters

    Deze update heeft één SQL-migratie, 094. Bij de upgrade verwijdert die de tabel share_link_access_log met alle rijen erin; daarna telt de database 94 migraties. De gegevens zijn niet terug te halen: de migratie terugdraaien maakt alleen een lege tabel aan. Las jij of je fork dat log wel, exporteer het dan vóór de upgrade. Maak eerst een backup, zoals bij elke migratie.

    Geen nieuwe dependency en geen nieuwe of verplichte configuratie. De details per commit staan in de 1.80.0-release op GitHub.

  33. v1.79.0

    Adresseerbare instellingen, kortere pogingsrecords

    Elke instellingensectie heeft een eigen adres en niet-opgeslagen wijzigingen vragen eerst om bevestiging; meldingen over pogingen op een ingetrokken link bevatten geen IP van de bezoeker meer en het pogingsrecord bestaat 24 uur.

    Instellingen waar je naar kunt linken

    Elke sectie van het instellingenmenu heeft nu een eigen #-adres. Terug, vooruit en herladen brengen je bij dezelfde sectie, en een link naar een sectie opent die sectie. Op smalle schermen opent één knop met de naam van de huidige sectie de lijst, in plaats van een horizontale strook.

    Een formulier met niet-opgeslagen wijzigingen vraagt nu eerst om bevestiging voordat je van sectie wisselt of terug naar het overzicht gaat. De slidetype-curatie is een gewoon formulier met een opslaanknop geworden in plaats van automatisch opslaan. Rechten op de server en opgeslagen waarden veranderen niet.

    Probeert iemand een ingetrokken deellink te openen, dan krijgt de auteur nog steeds een melding. Die melding bevat geen IP-adres van de bezoeker meer, en het record van de poging bestaat alleen nog voor de 24 uur waarin dubbele meldingen worden onderdrukt; de dagelijkse opruimtaak verwijdert oudere records.

    Dit is de eerste stap van een bredere privacyronde over bezoekersgegevens. De rest van dat werk hoort niet bij deze release.

    Voor zelfhosters

    Deze update heeft één SQL-migratie, 093. Bij de upgrade wist die oude pogingsrecords en haalt het IP-adres uit bestaande meldingen; daarna telt de database 93 migraties. De migratie logt twee tellingen, access_attempt_log: N row(s) past the window deleted en user_notifications: N access_attempt row(s) rewritten without accessorIp, waaruit je ziet hoeveel er is opgeruimd. Maak eerst een backup, zoals bij elke migratie.

    Geen nieuwe dependency en geen nieuwe of verplichte configuratie. De details per commit staan in de 1.79.0-release op GitHub.

  34. v1.78.0

    Instellingen per bereik, previews volgen publicatie

    Instellingen zijn gegroepeerd naar wie ze raken, elk formulier slaat één ding op, en publieke previewbeelden volgen nu of een deck gepubliceerd is; oude previewbestanden worden niet meer geserveerd.

    Instellingen per bereik

    De instellingen zijn nu gegroepeerd naar wie een instelling raakt: persoonlijk, organisatie, ontwerp en installatie. Routes en opgeslagen waarden blijven gelijk, dus links en bestaande configuratie blijven werken. Beleidsacties zien alleen organisatiebeheerders en installatieformulieren alleen instance-beheerders. Elk formulier slaat één ding op: het afzenderadres en de webhooks hebben bijvoorbeeld nu elk een eigen opslaanknop.

    De rechten op de server zijn niet veranderd. Wat veranderde is het menu: je ziet de instellingen die je echt kunt wijzigen, op de plek waar je ze zou zoeken.

    Publieke previews volgen publicatie

    Publieke previewbeelden (deelafbeeldingen en thumbnails) volgen nu de publicatiekeuze van het deck. Eerder gegenereerde previewbestanden worden niet meer geserveerd, en een gewone save van een deck verschuift de publicatiestand niet meer. Herpubliceren of de preview opnieuw genereren maakt een nieuw beeld.

    Daarmee geldt de kijkersbescherming uit de 1.77-releases ook voor gepubliceerde previews. Previews intrekken die een andere origin al heeft opgehaald is apart werk en hoort niet bij deze release.

    Voor zelfhosters

    Geen SQL-migratie, geen nieuwe dependency en geen nieuwe of verplichte configuratie. Decks waarvan de oude preview na de update niet meer wordt geserveerd, krijgen een nieuwe zodra ze opnieuw worden gepubliceerd of hun preview opnieuw wordt gegenereerd. De details per commit staan in de 1.78.0-release op GitHub.

  35. v1.77.5

    Kijkersexports zonder sprekersnotities

    Exports door kijkers, ook via achtergrondtaken, bevatten geen sprekersnotities of voor kijkers verborgen slides meer; alleen-notitiesdownloads zijn voor auteurs.

    Deckyard 1.77.5 breidt de kijkersbescherming uit naar exports. Exporteert iemand zonder schrijfrechten een deck, via de app of de publieke v1-API, dan bevat het bestand geen sprekersnotities, geen AI-toelichtingen en geen slides die voor kijkers verborgen zijn. Dat geldt voor elk formaat, ook portable JSON, .deck-bestanden en overdrachtspakketten, en voor elke taalversie in het deck. Eigenaren en bewerkers met schrijfrechten houden hun bestaande exportinhoud.

    Downloads met alleen notities (Markdown en Word) zijn nu alleen voor auteurs; kijkers krijgen een weigering. Exports die als achtergrondtaak lopen, onthouden wie ze aanvroeg en met welke rechten. Die rechten worden opnieuw gecontroleerd bij het bouwen en nog eens bij het downloaden: wie tussendoor schrijfrechten verloor, krijgt de kijkersversie of een weigering, en een klaar bestand gaat alleen naar degene die het aanvroeg. Oudere resultaten in de wachtrij zonder deze toegangsgegevens worden geweigerd en moeten opnieuw worden geëxporteerd.

    Gepubliceerde pagina’s en previewbeelden (deelafbeeldingen en thumbnails) vallen er nog buiten; ga er niet van uit dat deze wijziging ze afschermt. De referentie over kijkersdata beschrijft de precieze grens.

    Voor deze update is geen SQL-migratie, nieuwe dependency of verplichte configuratiewijziging nodig. De details per commit staan in de 1.77.5-release op GitHub.

  36. v1.77.4

    Meekijken toont de kijkersversie

    Wie een presentatie volgt, krijgt geen sprekersnotities of voor kijkers verborgen slides meer, in de meekijkweergave, Q&A, interacties en live-updates.

    Deckyard 1.77.4 breidt de kijkersbescherming uit 1.77.3 uit naar meekijken tijdens presenteren. Wie een presentatie volgt, krijgt nu de kijkersversie van het deck: geen sprekersnotities, geen AI-toelichtingen en geen slides die voor kijkers of in de presentatie verborgen zijn. Dat geldt voor de deckgegevens bij meekijken, server-gerenderde slides, de status van Q&A en interacties en beide live-updatestromen. Staat de presentator op een verborgen slide, dan zien volgers een neutraal wachtscherm in plaats van die slide.

    De meekijkantwoorden bevatten niet langer het live-sessie-id dat toegang geeft tot de notitiecompanion; dat id blijft nu op de server. De presentator en de notitiecompanion houden hun auteursweergave. Een companionlink die al is uitgedeeld, blijft geldig zolang de bestaande sessie loopt. Deze release herstelt ook racecondities bij het verbreken van een live-updatestroom.

    Exports (ook exportjobs in de wachtrij en notitiedownloads) en gepubliceerde pagina’s en previewbeelden vallen buiten deze release; ga er niet van uit dat deze wijziging ze afschermt. De referentie over kijkersdata beschrijft de precieze grens.

    Voor deze update is geen SQL-migratie, nieuwe dependency of verplichte configuratiewijziging nodig. De details per commit staan in de 1.77.4-release op GitHub.

  37. v1.77.3

    Sprekersnotities blijven bij auteurs

    Kijkers krijgen geen sprekersnotities of voor kijkers verborgen slides meer wanneer een deck als JSON of via MCP wordt geladen.

    Deckyard 1.77.3 beperkt wat een kijker ontvangt wanneer een deck als data wordt geladen. Wie geen schrijfrechten op het deck heeft, krijgt geen sprekersnotities, AI-toelichtingen of slides die voor kijkers verborgen zijn. Dat geldt voor de interne deck-API, de publieke v1-API voor decks en losse slides, deellinks en de lees- en previewtools van MCP, en voor elke taalversie in een deck.

    Wie als kijker geldt, hangt nu af van de werkelijke schrijfrechten op het deck. Een bewerker die op een bepaald deck niet mag schrijven, krijgt daarom ook de kijkersversie; eerder gaf die route nog de auteursgegevens terug. Eigenaren en bewerkers met schrijfrechten houden hun notities, ook als hun API-sleutel alleen read-rechten heeft.

    Deze fix dekt de genoemde JSON- en MCP-routes, nog niet alle routes. Meekijken tijdens presenteren, exports (ook exportjobs in de wachtrij en notitiedownloads) en gepubliceerde pagina’s en previewbeelden vallen er nog buiten; ga er niet van uit dat deze wijziging ze afschermt. De referentie over kijkersdata beschrijft de precieze grens.

    Voor deze update is geen SQL-migratie, nieuwe dependency of verplichte configuratiewijziging nodig. De details per commit staan in de 1.77.3-release op GitHub.

  38. v1.77.2

    Veiliger samenwerken

    Samenwerken weigert nu browserverbindingen vanaf een onverwachte website, terwijl verbindingen vanaf je eigen Deckyard-site blijven werken.

    Deckyard 1.77.2 scherpt de controle van verbindingen voor live samenwerken aan. Probeert een browser vanaf een andere website een samenwerkingsverbinding te openen, dan krijgt die een 403-antwoord, ook met een geldige sessiecookie. Verbindingen vanaf het eigen adres van je Deckyard-site blijven werken.

    De controle werkt ook wanneer Deckyard achter een ondersteunde reverse proxy draait. Native clients en serverintegraties die zonder browser-Origin-header verbinden, blijven ondersteund, met de gebruikelijke authenticatie en rechten.

    Voor deze update is geen SQL-migratie, nieuwe dependency of verplichte configuratiewijziging nodig. De details per commit staan in de 1.77.2-release op GitHub.

  39. v1.77.1

    Betrouwbaarder vertalen

    Grote decks worden nu in opgeslagen batches vertaald, zodat afgerond werk bewaard blijft als er later iets misgaat. De editor gebruikt één vertaalscherm en oudere decks behouden hun bedoelde achtergrondtekst bij het openen.

    Een groot deck vertalen is in 1.77.1 beter bestand tegen fouten. In de editor komt vertalen samen in één scherm. Daarnaast behouden oudere slides met een historische instelling voor achtergrondtekst hun bedoelde weergave.

    Afgeronde vertalingen blijven bewaard

    De directe vertaal-API en de worker vertalen een deck nu in batches en slaan elke afgeronde batch op. Gaat het later mis, dan blijft de tekst die al vertaald is in het deck staan. Een gedeeltelijk resultaat (502 translation_partial) vertelt API-gebruikers wat nog ontbreekt; herhaal hetzelfde verzoek met fillMissing: true om de gaten aan te vullen. Bewerkingen die iemand tijdens het vertalen in het deck doet, blijven behouden.

    Eén vertaalscherm in de editor

    Het taalmenu en het contextmenu van een slide openen nu hetzelfde vertaalscherm met de talen naast elkaar. De losse acties om een heel deck, één slide of één veld te vertalen zijn vervallen; je werkt met die teksten in het gezamenlijke scherm.

    Oudere achtergrondtekst blijft zoals bedoeld

    Oudere decks die default voor de tekstkleur bij een achtergrond hadden opgeslagen, behouden hun oorspronkelijke weergave bij het openen, ook bij live samenwerken. Deckschema 24 normaliseert deze historische waarde automatisch. Huidige geldige instellingen blijven zoals ze zijn.

    Voor zelfhosters is geen SQL-migratie, nieuwe dependency of configuratiewijziging nodig. De details per commit staan in de 1.77.1-release op GitHub.

  40. v1.77.0

    Reproduceerbare schermafbeeldingen van nieuw-deckdialogen

    Core bevat nu opnamerecepten voor de drie manieren om een deck te beginnen: Leeg, Genereren uit inhoud en Bestaand deck importeren. In de app zelf verandert niets.

    Deckyard 1.77.0 voegt drie screenshotrecepten toe aan core, één voor elke manier om een nieuw deck te beginnen: Leeg, Genereren uit inhoud en Bestaand deck importeren. Een recept zet de dialoog in een vaste toestand met demodata, zodat de documentatiebeelden van deze schermen vanaf elke release opnieuw kunnen worden opgenomen, in plaats van met de hand gemaakt en langzaam verouderd.

    Deze release maakt alleen de recepten beschikbaar. Het opnemen van de nieuwe beelden en het vervangen van de verouderde op deze site is een aparte levering, los van deze release.

    Er verandert niets in de app, er is geen SQL-migratie, geen nieuwe dependency en geen configuratiewijziging. Het aantal ingebouwde slidetypes blijft gelijk. De details per commit staan in de 1.77.0-release op GitHub.

  41. v1.76.0

    Bronnen houden hun structuur

    Een rapport of een Word-document bereikt de AI nu als document in plaats van als lap tekst: koppen, lijsten en tabellen blijven overeind, voetnoten en paginakoppen niet, en een pagina in twee kolommen wordt kolom voor kolom gelezen. Afbeeldingen uit de bron worden kandidaten die de AI op een slide kan zetten, en het vertaalscherm kreeg slidenavigatie, voorstellen die je eerst ziet, en per veld een registratie van welke brontekst een vertaling volgde.

    Een bron komt binnen als document

    Een deck genereren uit een rapport plette dat rapport: elke pagina werd een blok tekst, koppen verloren hun rangorde, alinea’s braken af op de paginarand en de paginavoet kwam overal mee. Een PDF reist nu als een gemarkeerd document. Koppen krijgen een rangorde naar hoe ze zich verhouden tot de broodtekst, de omslag wordt de titel, alinea’s worden over de paginagrens aan elkaar gezet, lijsten blijven lijsten en gegevenstabellen blijven tabellen. Terugkerende kantlijntekst vervalt, en voetnoten en de verwijstekens die ernaar wijzen ook.

    Een pagina in twee kolommen wordt nu kolom voor kolom gelezen in plaats van regel voor regel over allebei, zodat een kerncijfertabel niet meer door het commentaar ernaast wordt geweven. Word-documenten houden hun kopniveaus en hun lijsten, geneste punten inbegrepen, en gaan als één doorlopend document mee.

    Twee dingen blijven met opzet zoals ze waren. Een liggende pagina met weinig tekst geldt nog steeds als slide en niet als document, en de slide-import leest nog steeds rijen in plaats van kolommen: kaders naast elkaar op een slide zijn vormgeving, geen tekstkolom.

    Afbeeldingen uit je bron

    Een afbeelding in je brondocument haalde het deck nooit: figuren uit een PDF werden overgeslagen, die uit een Word-document vielen met de opmaak weg, en een Notion-pagina zette elke afbeelding behalve de eerste achteraan. Elke bron markeert zijn afbeeldingen nu op de plek waar ze staan en biedt ze aan als kandidaat. De AI koppelt ze aan secties en zet er hoogstens één op een inhoudsslide; alleen de afbeeldingen die een slide echt gebruikt worden geüpload.

    Wat bij de paginavormgeving hoort blijft buiten beeld: pictogrammen, briefhoofdlogo’s, achtergronden achter tekst en afbeeldingen die op meerdere pagina’s terugkomen. Uit een Word-document komen afbeeldingen van 40 pixels per zijde of groter mee, en bij Notion wordt de afbeelding uit de eerste sectie de titelachtergrond.

    Vertalen: navigeren, vooraf zien, en zien wat veranderde

    Drie aanvullingen op het vertaalscherm uit 1.75.0:

    • Slidenavigatie. Je loopt het deck door binnen het scherm, en de slide waar je in typt blijft de geselecteerde. Scrollen met de muis selecteert nog steeds waar je naar kijkt.
    • Voorstellen die je eerst ziet. Een derde kolom kan een vertaling voorstellen voor een veld, voor een slide, of voor alle lege velden tegelijk. Een voorstel blijft lokaal tot je het aanvaardt; in bulk aanvaarden vult alleen velden die nog leeg zijn. Is de bron of de vertaling veranderd sinds het voorstel, dan wordt het tegengehouden en vraag je een nieuw voorstel. Deze knoppen volgen je AI-instelling.
    • Bron gewijzigd. Een vertaald veld legt nu vast welke brontekst het volgde. Bewerk je die bron in de gewone editor, dan krijgt de vertaling de melding Bron gewijzigd, die bewaard blijft bij opslaan, herladen, ongedaan maken en opnieuw, en bij bewerkingen van anderen in een live sessie. Je kunt de rijen erop filteren, en op vertalingen die nog gelijk zijn aan hun bron.

    Ook opgelost

    • Grafieklabels uit een getagde PDF komen één keer mee. Een door Deckyard geëxporteerde grafiekslide die je uit een getagde PDF importeerde herhaalde elk label uit zijn groep, waardoor een as als 555555555 werd gelezen. Elk label wordt nu één keer gelezen.
    • Een pictogramnaam telt niet meer als onvertaalde tekst. De naam van een pictogram is een zoeksleutel, geen tekst, maar het taalmenu telde hem als ontbrekend en het vertaalscherm bood er een rij voor aan. Machinevertaling zou die sleutel hebben vertaald en de kaart zonder pictogram hebben achtergelaten. Vier andere velden van hetzelfde soort hadden er ook last van: een mediabibliotheek-id, een opgeslagen coördinatenlijst en twee slideverwijzingen.

    Voor zelfhosters en forks

    Geen SQL-migratie en geen nieuwe instellingen. Het opgeslagen deckschema gaat van 22 naar 23 voor een optionele registratie per veld van waar een vertaling vandaan komt; er wordt niets bijgewerkt met terugwerkende kracht, en een ouder deck opent ongewijzigd. deckyard doctor meldt nu een thumbnailcache waarin hij niet kan schrijven, wat voorheen opdook als thumbnails die stilletjes uitbleven. pdf-parse is uit de optionele afhankelijkheden verdwenen: de AI-route en de slide-import lezen PDF’s nu via dezelfde lezer.

    Voor forks: een veld met tekst die de lezer niet afgedrukt ziet, zoals de invulhint van een interactie, geeft dat aan met interactionCopy: true; dat is de tegenovergestelde claim van presentational: true (machinegegevens), en allebei tegelijk is een waarschuwing. De publieke v1-catalogus van slidetypes bevat nu ook de eigen slidetypedefinities van de organisatie. Het aantal ingebouwde slidetypes is niet veranderd. Details in de release op GitHub.

  42. v1.75.0

    Een deck naast elkaar vertalen

    Een nieuw vertaalscherm toont elke tekst van een deck in twee talen naast elkaar, allebei bewerkbaar, zodat je een heel deck vertaalt zonder van versie te wisselen. Door AI gemaakte slides zijn weer kort, met de uitleg in de sprekersnotities, en een beveiligingsfix houdt de AI-toelichting per slide bij wie het deck mag bewerken.

    Beveiliging: de AI-toelichting per slide blijft bij de auteur

    Een deck dat met AI is gemaakt of geïmporteerd bewaart per slide de redenering, alternatieven en waarschuwingen van de AI voor het reviewoverzicht. Die tekst kon terechtkomen bij mensen die het deck alleen mogen bekijken: lezers, gasten via een deellink (ook met wachtwoord), de meekijkpagina en de publieke API. Er kan tekst uit het bronbestand in staan. Alleen wie het deck mag bewerken krijgt hem nu nog. Live bewerken controleert de toegang ook opnieuw zolang een verbinding openstaat, zodat iemand van wie de toegang wordt ingetrokken binnen enkele seconden geen wijzigingen meer ontvangt. Zelfhosters doen er goed aan bij te werken.

    Naast elkaar vertalen

    Naast elkaar vertalen… in het taalmenu en in het contextmenu van een slide opent een schermvullend overzicht met elke tekst van het deck als rij: links de bron, rechts de vertaling, allebei bewerkbaar. Een filter toont alleen de velden die nog een vertaling nodig hebben. Bij meer dan twee talen kies je het paar. In een live sessie verschijnen wijzigingen van anderen en ongedaan maken en opnieuw in het overzicht, en een slide waar iemand anders aan werkt blijft vergrendeld.

    Kortere AI-slides

    Door AI gemaakte slides waren uitgegroeid tot lappen tekst. Een slide draagt nu de kern in zo’n zestig woorden, met één korte regel per punt, en de uitleg gaat naar de sprekersnotities. Een deck genereren met Claude kost ook merkbaar minder, omdat het vaste deel van de instructies tussen aanroepen wordt gecachet.

    Voor zelfhosters en forks

    Geen migratie en geen nieuwe instellingen. Live bewerken weigert nu wie het deck niet mag bewerken; kijkers gebruikten het nooit. Voor forks: tekst in elke taalversie gaat via writeVersionText (client/views/editor/version-text.js), en slideTextRows in shared/i18n-progress.js loopt de tekst van een deck in twee talen af. Een AI-bericht kan cache: true dragen. Details in de release op GitHub.

  43. v1.74.0

    Een PDF importeren als bewerkbare slides

    Een bestaand deck importeren kan een slide-PDF nu omzetten in bewerkbare slides in plaats van beelden, met de tekst letterlijk overgenomen. Elke AI-route (de wizard, bestands- en Notion-import, de API en MCP) draait nu één generatiepijplijn, reacties laten duidelijk zien of ze bij de slide of bij een plek erop horen, en een beveiligingsfix laat het wachtwoord van een deellink ook het gesprek met gasten afschermen.

    Een deellink met wachtwoord en reacties aan liet een gast meepraten zonder dat die het wachtwoord gaf. Een gast moet nu eerst het wachtwoord invullen voordat die kan reageren, en een ingetrokken wachtwoordlink noemt zijn deck niet meer. Een deellink met wachtwoord die je in een chat of mail plakt, toont ook geen decktitel meer. Zelfhosters die wachtwoordlinks gebruiken, doen er goed aan bij te werken.

    PDF als bewerkbare slides

    Bestaand deck importeren → PowerPoint of PDF biedt nu Als bewerkbare slides (standaard) naast Als beelden. Een slide-PDF wordt echte slides met titels, tekst en lijsten die je kunt bewerken, letterlijk overgenomen en zonder AI. Een pagina die zich niet goed laat vertalen, zoals een pagina met een grafiek of tekening, blijft een beeldslide, en het importrapport zegt welke pagina’s dat zijn en waarom.

    Eén pijplijn achter elke AI-route

    De aanmaakwizard, bestands- en Notion-import, de publieke API en MCP maken een deck nu op dezelfde manier. Geïmporteerde decks krijgen sprekersnotities, het model ziet de kleuren van het thema, de titelslide volgt het thema en het reviewoverzicht toont alternatieven en waarschuwingen voor elke route. Alle imports tonen dezelfde voortgangsstappen, in de taal die je koos. Mislukt het genereren, dan zie je nu de fout in plaats van stilletjes een zwakker deck.

    Reacties

    Reacties op de hele slide en reacties op een plek ervan zien er nu verschillend uit. Een leeg reactiepaneel biedt allebei (“Reageer op deze slide” en “Markeer een plek”), een vastgeprikte reactie krijgt een speldicoon en een actie Toon op slide, en je kunt een speld ook met het toetsenbord plaatsen. Lezers en reagerende gasten zien de spelden ook. Een reactiemarker noemt de auteur en het begin van de reactie, in plaats van “undefined”.

    Taal

    In een Nederlands deck spreken de lege video- en embedslide, de knoppen van de countdown en de toegankelijke namen van de cyclus-, trechter-, proces- en piramideslide nu Nederlands.

    Voor zelfhosters en forks

    Geen migratie en geen nieuwe instellingen. Voor forks: generateDeckV2 heet nu generateDeck, reattachAiMeta is vervangen door generatedDeckToParts (beide in server/utils/ai/index.js, zonder alias), loadAiThemeContext verhuisde naar server/utils/themes.js, en server/utils/openai/deck.js is weg. De importvoortgang stuurt de fasewoorden parse, analyze, convert en fetch niet meer. De client-seam van de slide-import heet nu createDeckFilesPicker / importDeckFiles, en er is een nieuw endpoint, POST /api/presentations/import/slides. Details in de release op GitHub.

  44. v1.73.0

    Twee manieren om een deck te beginnen

    Een deck maken biedt nu twee routes voordat je een bestand kiest: met AI een nieuw deck genereren uit inhoud, of een bestaande PowerPoint of PDF één op één importeren als beeldslides, zonder AI. De themakeuze toont elk thema als de echte titelslide waarmee je deck begint, de deeldialoog opent op Gasten, en een vertaald deck houdt de taalversie waarin je werkt.

    Genereren of importeren

    De aanmaakweergave vraagt eerst wat je wilt en pas daarna om een bestand. Genereren uit inhoud leest een tekst, een document of een Notion-pagina en schrijft met AI een nieuw deck. Een bestaand deck importeren neemt een PowerPoint, een PDF of allebei en maakt van elke pagina een beeldslide met de sprekersnotities, in het thema en de taal die je kiest. De import werkt zonder AI, dus ook op een installatie waar AI uit staat. Importeren van .deck, JSON en Markdown staat er zoals voorheen naast.

    Eén kaart per thema

    Als je een deck begint, toont elk thema de titelslide die het deck echt krijgt, met foto, in de aanmaakweergave en op Home. De werkruimtestandaard is geen aparte kaart meer maar een badge op zijn eigen thema. Een nieuw deck, en een titelslide die je in de editor invoegt, krijgt nu de eerste achtergrondpreset van het thema in plaats van een willekeurige; bestaande decks blijven zoals ze zijn.

    Delen

    De deeldialoog opent op Gasten, met een regel boven de tabs die zegt hoe het deck ervoor staat (“Privé · 2 gastlinks · Niet gepubliceerd”). Nieuwe reactielinks staan standaard open voor iedereen met de link; bestaande links houden hun instelling. Label en wachtwoord staan onder “Meer opties”, en elke link zegt wanneer hij vervalt. Een ingetrokken, verlopen of opgebruikte deellink toont geen decktitel meer als je hem in een chat of mail plakt.

    Vertaalde decks

    Een deck met meerdere taalversies houdt de versie waarin je werkt wanneer een import, een verwerkte reactie, een gepromote vraag, een publicatie of een herstel het terugschrijft. Een wijziging via de API of door een agent zonder taalgegevens komt in de hoofdtaalversie terecht, zodat de editor daarna niet meer het oude deck toont.

    Fixes in de editor

    • Het slidemenu volgt het toetsenbord: pijltjes lopen erdoorheen en na een actie staat de focus weer op de slide.
    • Op precies 1024 pixels breed (een iPad liggend) toont de editor de volledige desktopweergave met inspector; de ingeklapte slidebalk toont één nummer per slide.
    • Plakt een collega slides midden in een deck, dan verschijnen ze in jouw tabblad op de juiste plek, zonder verversen.
    • Een lege achtergrond toont de standaard van het slidetype (of van het thema), dus “Terug naar standaard” slaat geen waarde meer op.
    • Op een beeld-tekstslide heeft de beeldbreedte één knop, de split-tegels.
    • Duidelijkere veldnamen: “Detailregel” (was Meta), “Kanttekening” (was Terzijde) en “Op je telefoon” (was Notities (QR)); grafiek- en videovelden noemen geen formaten meer in hun label. Een handvol tooltips en labels die Engels bleven, volgen nu de taal van de interface.
    • AI-import houdt een lijst bij zijn eigen items; een opmerking over de lijst gaat eruit.

    Voor zelfhosters en forks

    Geen migratie en geen nieuwe instellingen. Voor forks: het breekpunt lg ligt nu op max-width: 1023px / min-width: 1024px (was 1024/1025), dus een fork-stylesheet met de oude grens moet mee. De slide-import-UI verhuisde naar client/views/slide-import/, en er is een nieuw endpoint, POST /api/presentations/import/images. /api/slide-types draagt nu autoBackgroundPreset. Details in de release op GitHub.

  45. v1.72.0

    De editor met het toetsenbord

    Je werkt nu met het toetsenbord door de editor: de slidelijst is één Tab-stop met pijltjestoetsen, canvasvelden staan in de Tab-volgorde en elke stop toont dezelfde focusring. De inspector markeert de standaard van elke instelling en biedt "Terug naar standaard". Lange exports, imports en AI-taken tonen hun voortgang in één venster dat je kunt annuleren, en HTML-exports met veel foto's zijn een fractie van hun oude omvang.

    De editor met het toetsenbord

    De slidelijst is één Tab-stop: pijltjes, Home en End lopen over de slides, Links en Rechts klappen een sectie in en uit, en Enter, de menutoets of Shift+F10 openen de acties van de gefocuste slide. Daarna bereikt Tab elk veld op het canvas in de volgorde van de slide, Enter begint met bewerken en Escape of Enter zet je terug op het veld. Lege velden en de ”+“-chips voor ontbrekende velden hebben een naam die een schermlezer voorleest, en elke stop toont dezelfde focusring, in licht en donker.

    De standaard, en de weg terug

    Elke instelling in de inspector markeert haar standaardoptie met een stip en “(Standaard)” in de tooltip. Wijkt een instelling af, dan verschijnt ernaast de knop “Terug naar standaard”. Die vervangt de aparte optie “Standaard” bij beeldvulling en de knop “Midden” bij het focuspunt.

    Een rustigere inspector

    Zolang het beeld van een slide nog leeg is, is de beeldkaart de eerste rij van de inspector, zodat je eerst het beeld toevoegt en dan de layout kiest; zodra er een beeld staat, komt Layout weer bovenaan. Elk beeld heeft één kaart. Blokuitlijning onder “Deze tekst” is geen grijze knop meer, maar een regel die zegt waarop het blok staat, met een knop naar de Layout-rij. Elke scope heeft één label, en het letterlijke “null” boven de zoekbalk van de beeldbibliotheek is weg.

    Lange taken die je kunt volgen en annuleren

    PDF, PNG-zip, beide PowerPoint-exports, de handoff-zip, slide-import en AI-analyse tonen hun voortgang in één venster (“Slide 13 van 54”) met een knop Annuleren. Annuleren stopt het werk ook op de server.

    Kleinere exports

    De HTML-export, de gepubliceerde /p/-pagina en het PNG-voorbeeld verkleinen foto’s nu zoals de PDF-route dat al deed. Een testdeck van 54 fotoslides ging bij de HTML-export van ruim 300 MB naar zo’n 50 MB.

    Bewerkfixes

    Een stijl- of layoutwijziging tijdens het inline bewerken van tekst is meteen op het canvas te zien, en een klik in de inspector vlak na het typen op het canvas komt in één keer aan.

    Voor zelfhosters en forks

    Geen migratie en geen nieuwe instellingen. Decks of bibliotheekslides die een thema nog bij zijn oude slug noemen (een installatie die scripts/migrate-theme-references.js nooit draaide) geven nu een waarschuwing bij het opstarten, en npm run doctor wordt rood op de nieuwe check theme-references, met het aantal en het commando om het op te lossen. Een bibliotheekslide aanmaken met een onbekend thema wordt geweigerd. Details in de release op GitHub.

  46. v1.71.0

    De nieuwe editorflow

    De editorflow is af: je bewerkt een slide als formulier in het tabblad Velden, Layout staat bovenaan de inspector en de slide-acties zitten in de slidelijst. De slidekiezer toont één tegel per type en opent op "Start here". Exports en deckminiaturen herstellen zich als de headless browser faalt.

    Velden: een slide als formulier, naast het canvas

    Het tabblad Velden boven de canvaskolom toont de inhoud van de gekozen slide als formulier, en de slide verandert mee terwijl je typt. Het vervangt het venster “All text”, dat niet meer bestaat. Instellingen staan alleen nog in de inspector, zodat inhoud en instellingen niet meer door elkaar staan. De slidebibliotheek bewerkt haar slides met hetzelfde formulier.

    Layout voorop, slide-acties in de slidelijst

    Layout is de eerste rij van de inspector. De type-pil bovenaan is een menu om het slidetype te wisselen. Dupliceren, kopiëren, plakken, verbergen en verwijderen staan in het menu van de slidelijst en op elke miniatuur, waar je toch al kijkt als je een slide kiest.

    Grafiekdata live bewerken

    De grafiekdata-editor werkt de slide bij terwijl je bewerkt en sluit met Klaar. De hele sessie is één ongedaan-maakstap, en het formulier toont een samenvatting van de data in plaats van het raster.

    Een rustigere slidekiezer

    De kiezer toont één tegel per slidetype; types met varianten (callout, beeld + tekst, lijst) vouwen die in een rij onder de tegel. Zonder geschiedenis opent hij op “Start here”, acht types om mee te beginnen. De Media-plank leest in twee rijen, “One image” en “Collection”, en “Image blocks” heet nu “Image cards” (zelfde type, zelfde id). De strook “From your library” is weg; dezelfde slides staan in het tabblad Slide library.

    Exports en miniaturen die zich herstellen

    Elke download in het exportvenster haalt zijn bestand ter plekke op: geen leeg tabblad meer terwijl een grote PowerPoint of handoff-zip wordt gebouwd, een bezette knop in de tussentijd en een leesbare fout onder de rij als het misgaat. Crasht de headless browser of start hij niet, dan start de volgende export een nieuwe, zonder herstart van de server. Deckkaarten op Home en Presentations tonen hun miniatuur, of meteen hun placeholder als een render mislukt, in plaats van een eindeloze shimmer.

    Voor zelfhosters en forks

    Geen migratie. Eén nieuwe optionele instelling, EXPORT_BROWSER_LAUNCH_TIMEOUT_MS (standaard 30000, 0 zet de grens uit). Een browser die niet start antwoordt nu 503 browser_unavailable in plaats van 500 export_failed, en npm run doctor start de browser echt, zodat een Chromium die bij het starten crasht rood wordt. Forks met eigen editoraanpassingen kijken best in de release op GitHub: de bulk-surface en bulk-edit-modal.js zijn weg, bulkOnlyFields() heet nu fieldsOnlyFields(), en rijen in het exportvenster beschrijven zich met preview of file in plaats van open.

  47. v1.70.0

    Editorindeling en import

    De editor krijgt tabbladen boven zijn twee werkkolommen, een lade voor de inspector op kleinere schermen en Tab om tussen de velden op de slide te springen. Slides importeren als afbeeldingen houdt de sprekersnotities, uit het PowerPoint-bestand dat je naast de PDF meegeeft.

    Tabbladen boven het canvas en de inspector

    De twee werkkolommen van de editor hebben elk hun eigen tabbladen: Canvas | Velden boven de slide, Inspector | Opmerkingen bovenaan de rechterkolom. Panelen, podium en bovenbalk krijgen elk een eigen tint, zodat je in één oogopslag ziet waar je werkt.

    Een lade voor de inspector op 1024 pixels en kleiner

    Op een laptop of tablet stond de inspector onder het canvas en kromp de slide tot een postzegel. Op 1024 pixels en kleiner opent hij nu als lade over de rechterrand van het canvas, en houdt de slide zijn hoogte. Escape, de sluitknop of het actieve tabblad sluit hem weer.

    Met Tab door de slide

    Terwijl je tekst op het canvas bewerkt, springen Tab en Shift-Tab naar het volgende of vorige veld van de slide, ook naar de lege velden die je nog kunt invullen. De suggesties voor lege velden blijven zichtbaar terwijl je typt, niet alleen bij hover.

    Bij beeldslides komt het beeld eerst

    Bij een beeldslide of een slide met beeld en tekst opent de inspector op het beeld zelf: kiezen of uploaden als het leeg is, en de miniatuur, Vervangen en de alt-tekst daar direct onder als er een beeld staat. Instellingen die alleen bij een afbeelding horen, wachten tot er een is. De alt-tekst krijgt een waarschuwing zolang publiceren het beeld zou weigeren. De beeldbreedte heet overal hetzelfde: 37% · 50% · 63%, van smal naar breed.

    Sprekersnotities bij importeren als afbeeldingen

    “Slides importeren als afbeeldingen” houdt nu je sprekersnotities. Geef de PDF die je presentatieprogramma exporteerde samen met het PowerPoint-bestand: de pixels komen uit de PDF, de notities uit de .pptx, gekoppeld op volgorde van de slides. Tellen de twee bestanden een ander aantal slides, dan meldt de import dat en schrijft hij niets. Een PowerPoint-import komt ook weer in de volgorde van het deck binnen, met de eigen notities per slide, ook als je slides in PowerPoint hebt verschoven.

    Geen migratie en geen nieuwe configuratie. Voor de lijst met commits, zie de 1.70.0-release op GitHub.

  48. v1.69.1

    Herstel PDF-import

    Een PDF importeren als slide-afbeeldingen werkt weer op servers waarvan de browser geen ingebouwde PDF-viewer heeft, zoals het Docker-image. Bij het overdragen van een deck wordt het adres van de nieuwe eigenaar herkend, hoe je het ook met hoofdletters schrijft.

    Een PDF importeren als afbeeldingen

    “Slides importeren als afbeeldingen” faalde op elke PDF in het Docker-image en op elke andere installatie waarvan de headless browser geen PDF-viewer heeft: de browser behandelde het bestand als download en de import stopte met een fout. Deckyard opent de PDF niet meer als pagina, maar telt en rendert de pagina’s direct. Een mislukte of afgebroken import laat ook geen pagina meer openstaan in de gedeelde browser.

    Eigendom overdragen en hoofdletters in e-mail

    Sinds 1.69.0 bewaart de server elk e-mailadres in één schrijfwijze. De editor vergelijkt adressen nu zoals de server ze stuurt, en vouwt alleen het ene adres dat je zelf typt: de nieuwe eigenaar bij het overdragen van een deck. Ann@Example.org vindt de samenwerker ann@example.org.

    Geen migratie en geen nieuwe configuratie. Voor de lijst met commits, zie de 1.69.1-release op GitHub.

  49. v1.69.0

    Eerste beheerder en hoofdletters in e-mail

    Een verse installatie maakt de eerste beheerder aan uit AUTH_ADMIN_EMAIL, dus je hoeft het inloggen niet meer uit te zetten om te beginnen. Een e-mailadres vindt nu dezelfde gebruiker, hoe je het ook met hoofdletters schrijft. Verborgen slides blijven verborgen in elke taalversie, en bestands-, Notion- en Markdown-imports controleren eerst de slidevelden. Forks passen één importpad aan; migratie 092 herschrijft opgeslagen adressen.

    Een eerste beheerder bij een verse installatie

    Zet AUTH_ADMIN_EMAIL en start Deckyard op een lege database: het maakt dat adres aan als eerste beheerder en logt hoe je inlogt, via magic link of SSO. Je hebt AUTH_ENABLED=false niet meer nodig om voorbij een lege gebruikerstabel te komen. Zodra er een gebruiker bestaat, doet de variabele niets. Is er geen e-mailverzending en geen SSO ingesteld, dan waarschuwt de log dat de beheerder nog niet binnen kan komen.

    Eén schrijfwijze per e-mailadres

    Ann@Example.org en ann@example.org zijn nu overal dezelfde persoon: bij inloggen, delen, favorieten en de persoonlijke slideplank. Adressen worden op één plek gevouwen, en migratie 092 herschrijft de hoofdletters van adressen die al zijn opgeslagen. Zouden twee opgeslagen rijen op een unieke kolom botsen, dan laat de migratie ze staan en schrijft een warn-regel in de deploylog; lees die log dus na de upgrade.

    Verborgen slides blijven verborgen in elke taal

    Een slide die voor kijkers verborgen was, viel weg uit de hoofdtaal van het deck, maar bereikte een kijker of commentator nog via de andere taalversies in de deckdata. Hij valt nu uit elke versie weg.

    Imports controleren eerst de slidevelden

    Bestandsconversie, Notion-import en Markdown-import gaan nu door dezelfde veldcontrole als de editor en de JSON-import. Een ongeldige waarde wordt geweigerd met taal, slide en veld erbij, voordat er een deck bestaat.

    Brekende wijzigingen voor forks

    ModuleWijziging
    server/utils/normalize.jsExporteert normalizeEmail niet meer; importeer hem uit shared/email.js
    Migratie 092Zet opgeslagen adressen in kleine letters in users, user_settings, presentation_collaborators, presentations.trashed_by, presentation_versions, slide_library, slide_collections en view_sessions; botsingen op een unieke kolom blijven staan met een warn in de deploylog

    Nieuwe configuratie: AUTH_ADMIN_EMAIL (optioneel). Zie de 1.69.0-release op GitHub voor de commitlijst.

  50. v1.68.0

    Slidesprongen en verzoeklimieten

    Een link naar slide 3 leidt nu overal naar slide 3: in de presenter, de reader, PDF, PPTX en geëxporteerde decks. Imports weigeren ongeldige slidevelden voordat er een deck ontstaat, en verzoeklimieten delen één token bucket over instances. Forks werken de Redis-rate-limitaanroep en één projectie-optie bij.

    Een slidesprong betekent overal dezelfde slide

    Een knop of link naar #3 opent nu de derde slide van het deck op elke plek waar je hem kunt volgen: in de presenter, de reader, de alleen-lezenpagina, print en PDF, en beide PPTX-exports. Eerder telden sommige daarvan alleen de slides die ze toevallig toonden, zodat een overgeslagen of verborgen slide eerder in het deck de sprong één slide te ver stuurde. Een sprong waarvan het doel niet getoond wordt, wordt geen link in plaats van een verkeerde.

    Geëxporteerde decks schrijven sprongen binnen het deck in dezelfde positievorm, geteld op de geëxporteerde volgorde. Een sprong waarvan het doel buiten de export valt, vervalt, zodat het geëxporteerde deck weer zonder fouten importeert.

    Imports controleren eerst de slidevelden

    Een deck met slides aanmaken, JSON importeren en een .deck-bundel importeren halen nu elke taalversie door dezelfde veldcontrole als de editor. Een ongeldige waarde wordt geweigerd met taal, slide en veld erbij, voordat er een deck bestaat, dus een mislukte import laat niets halfs achter.

    Eén verzoeklimiet over instances

    Rate limiting gebruikt nu een token bucket die zich in het geheugen en in Redis hetzelfde gedraagt, met één atomaire stap per verzoek. Wie zelf host met meerdere instances achter Redis krijgt één gedeelde limiet in plaats van net andere tellingen per backend. Gebruikers aanmaken als beheerder volgt dezelfde limiter: twintig achter elkaar, daarna één per drie minuten.

    Brekende wijzigingen voor forks

    ModuleWijziging
    server/utils/rate-limit-redis.jscheckRateLimitRedis(key, { capacity, windowSeconds }) is weg; gebruik allowRequestRedisDetails(key, { capacity, refillPerSec }, runWithRedis?). Sleutels staan onder ratelimit:token-bucket:; oude sleutels verlopen vanzelf
    shared/slide-types/semantic-projection.jsDe projectie-optie slideIds heet nu slideJumps ({ deck, document }, uit slideJumpsFor())
    server/export/pptx.jsbuildPptxBuffer en buildEditablePptxBuffer nemen het opgeslagen deck en laten live-only slides zelf weg; geef het ongefilterde deck mee. Alleen-lezenresponsen pinnen sprongen met pinSlideJumps() uit shared/slide-types/deck.js

    Deze release voegt geen databasemigratie en geen nieuwe configuratievariabele toe. Zie de 1.68.0-release op GitHub voor de commitlijst.

  51. v1.67.0

    Opslaglaag voor forks

    Voor wie Deckyard gebruikt verandert er niets. Elke opslagaanroep die de database raakt krijgt nu eerst een scope, en de database-infrastructuur verhuist naar server/db. Forks moeten zeven aanroepen en vijf importpaden bijwerken.

    Elke opslagaanroep noemt nu zijn scope

    Deze release maakt de overstap naar scope-first opslag af die in 1.65.0 en 1.66.0 begon. Elke geëxporteerde opslagfunctie die de database raakt, krijgt nu een StorageScope als eerste argument: de organisatie waarvoor hij werkt, of een expliciete instancescope met reden. In de editor, de API en exports verandert niets. Voor wie zelf host betekent het dat één regel nu voor de hele opslaglaag geldt, zodat een aanroep die vergeet voor welke organisatie hij werkt niet meer door de controle glipt.

    Breaking changes voor forks

    Zeven domeinexports krijgen StorageScope als eerste argument. Voeg die toe vóór alle bestaande argumenten; de oude signaturen zijn verwijderd.

    ModuleWijziging
    server/storage/activity-events.jsdeleteOldActivityEvents(scope, olderThan): alleen een instancescope voor bewaartermijnen
    server/storage/slide-locks.jscleanupExpiredSlideLocks(scope): alleen een instancescope voor bewaartermijnen
    server/storage/themes.jslistSeedThemes(scope): organisatiescope of instancescope met reden
    server/storage/settings.jsresolveSeedThemeSlug(scope, slug), installationDefaultThemeId(scope): organisatiescope of instancescope met reden
    server/storage/tags.jsreplaceTagLinks(scope, { linkTable, rowId, tagNames }): het veld orgId vervalt
    server/storage/utils/index.jsgetUserIdByEmail(scope, db, email): het argument orgId vervalt

    De database-infrastructuur verlaat server/storage/, zonder doorverwijzing op de oude paden:

    ExportOud padNieuw pad
    withDbGuardserver/storage/utils/db-guard.js (ook geëxporteerd via server/storage/utils/index.js)server/db/client.js
    initializeStorage, closeStorageserver/storage/lifecycle.jsserver/db/lifecycle.js
    pendingMigrationsError, strandedFileDataErrorserver/storage/boot-check.jsserver/db/boot-check.js

    De lege testhelper __resetStorageForTests is verwijderd, en daarmee uninstallFacadeStorage() in tests/pg/helpers/harness.js: een pg-test in een fork laat die aanroep weg, closeTestDb() is de hele opruimstap. Bewaartermijnjobs weigeren elke scope die een organisatie noemt. Een fork die replaceTagLinks of getUserIdByEmail met een orgId aanriep, geeft nu de scope van die organisatie mee. De storage-scope-referentie beschrijft het contract.

    Deze release voegt geen databasemigratie of nieuwe configuratievariabele toe. De commitlijst staat in de 1.67.0-release op GitHub.

  52. v1.66.0

    Beveiliging en API-limieten

    Afgedwongen SSO blokkeert nu ook inloggen met wachtwoord of magic link via de API. Rate-limitheaders tonen het echte verzoekbudget. Forks moeten 42 opslagaanroepen en twee rate-limithelpers bijwerken.

    Afgedwongen SSO sluit de lokale inlogroutes

    Met SSO_ENFORCE=true en een geldige SSO-configuratie waren de inlogformulieren al verborgen, maar inloggen met wachtwoord, magic links en wachtwoordherstel werkten nog als je ze rechtstreeks aanriep. Die routes weigeren nu met HTTP 403 en { "ok": false, "error": "sso_required" }, vóór enige wachtwoordcontrole, token of e-mail. Magic links en herstellinks die vóór het afdwingen zijn verstuurd, werken ook niet meer. Bestaande sessies blijven werken, en een uitgeschakelde of onvolledige SSO-configuratie zet de controle niet aan.

    Rate-limitheaders tonen het echte verzoekbudget

    De X-RateLimit-*-headers op publieke API-antwoorden noemden een theoretisch dagtotaal, terwijl de limiter bij een piek al veel eerder weigerde, met een vaste Retry-After: 60. Antwoorden en 429-weigeringen geven nu limiet, resterende verzoeken, resettijd en wachttijd uit dezelfde limiterbeslissing. De dagquota voor AI en exports houden hun betekenis. Leest een client deze headers, dan ziet hij veel kleinere getallen die wel kloppen.

    Breaking changes voor forks

    Twee rate-limithelpers veranderen. getRateLimitHeaders in server/storage/api-usage.js accepteert alleen nog de expliciete limieten ai en exports; voor verzoeken gebruik je checkRequestRateLimit uit server/utils/rate-limit.js. allowRequestRedis in server/utils/rate-limit-redis.js heet nu allowRequestRedisDetails en geeft een beslisobject terug: lees .allowed, of gebruik allowRequest uit server/utils/rate-limit.js voor een boolean.

    De volgende 42 exports voor analytics, live-sessies, interactieslides en deellinks krijgen StorageScope als eerste argument. Voeg die toe vóór alle bestaande argumenten, ook vóór het databaseargument in getCompletionCounts(scope, db, ...) en getValidShareLinkById(scope, db, ...). Importpaden blijven gelijk; de oude signaturen zijn verwijderd.

    ModuleExports met een nieuw eerste scope-argument
    server/storage/analytics/aggregations.jsgetCompletionCounts, getDetailedSlideEngagement, getInteractionHeatmapData, getPresentationAnalyticsOverview, getViewerJourneyData
    server/storage/analytics/dashboard.jsgetDashboardSummary, getDashboardTimeline, getPresentationsWithAnalytics, getSourceBreakdown, getTopPresentations
    server/storage/analytics/slide-views.jsdeleteOldSlideViews, endAllSlideViewsForSession, transitionToSlide
    server/storage/analytics/view-sessions-gdpr.jsanonymizeOldIpAddresses, deleteUserAnalyticsData, eraseAnalyticsDataForDevice, eraseAnalyticsDataForSession, exportUserAnalyticsData
    server/storage/analytics/view-sessions.jscreateViewSession, deleteOldViewSessions, getActiveViewerCount, getViewSessionsForPresentation
    server/storage/analytics/weekly-summary.jsgetTeamWeeklyAnalytics, getWeeklyAnalyticsForUser
    server/storage/interaction-slides.jsensureInteractionSlide, getInteractionSlide, updateInteractionSlide
    server/storage/live-sessions/close.jscloseSession
    server/storage/live-sessions/db.jscountPersistedSessions, deletePersistedSession, hydrateSession, hydrateSessionsForPresentation, persistSession, schedulePersist, sweepExpiredSessions
    server/storage/live-sessions/sse.jstouchSessionSync
    server/storage/share-links/access-log.jsgetShareLinkAccessLog, logShareLinkAccess
    server/storage/share-links/crud.jsgetValidShareLinkById, shareLinkCreatorNames
    server/storage/share-links/guests.jsrequestGuestVerification
    server/storage/share-links/index.jscleanupExpiredShareLinks

    Geef de organisatiescope van de betreffende presentatie mee. AVG-verzoeken van een ingelogde gebruiker, anonieme verwijdering via een token en bewaartermijnjobs vragen een expliciete instancescope met reden. Een scope vervangt de autorisatie van de aanroeper niet. De storage-scope-referentie beschrijft het contract.

    Deze release voegt geen databasemigratie of nieuwe configuratievariabele toe. De commitlijst staat in de 1.66.0-release op GitHub.

  53. v1.65.0

    Bewerken en forkonderhoud

    Slidevelden worden bij iedere opslag gecontroleerd, met herstel bij het invoerveld in de editor. Forks moeten bij 35 opslagfuncties de scope als eerste argument meegeven.

    Ongeldige velden herstellen vóór het opslaan

    Slidewijzigingen krijgen nu dezelfde veldcontrole in de editor, API en MCP. De editor wijst het veld en de taal aan die aandacht vragen en bewaart je invoer tijdens het herstel. Bestaande ongeldige waarden op ongewijzigde slides blijven leesbaar; zodra je zo’n slide wijzigt, moet je die waarden herstellen. Onvolledige vertalingen blijven op te slaan zonder brontekst naar de vertaling te kopiëren.

    Breaking change voor opslagfuncties in forks

    De volgende 35 exports krijgen StorageScope als eerste argument. Schuif ieder bestaand argument één positie op, ook het databaseargument in ensureMembership(scope, db, ...). De importpaden blijven gelijk; de oude signatures zijn verwijderd.

    ModuleExports met een nieuw eerste argument scope
    server/storage/collaborators.jsaddCollaborator, getCollaboratorPermission, listCollaborators, removeCollaborator, updateCollaboratorPermission
    server/storage/display-identity.jsresolveDisplayNames, resolveNamesForAddresses
    server/storage/identity-resolver.jsresolveIdentity, resolveIdentityByEmail
    server/storage/identity-verification.jsverifyIdentityConsistency
    server/storage/identity.jsgetUserByEmailGlobal, resolveActiveMembership, resolveActiveOrganization
    server/storage/login-membership.jsensureMembership
    server/storage/password-reset.jscleanupOldAuditLogs, getPasswordChangedAt, hasDatabaseCredentials, logAuthEvent, verifyUserPassword
    server/storage/user-organizations/memberships.jsaddMember, countOrganizationMembers, getMembership, getMembershipByEmail, getOrganizationMember, listOrganizationMembers, listUserOrganizations, removeMember, transferOwnership, updateMemberDesigner, updateMemberRole
    server/storage/user-organizations/organizations.jscreateOrganization, deleteOrganization, getOrganizationById, getOrganizationBySlug, updateOrganization

    Gebruik voor organisatiegebonden wijzigingen de scope van de doelorganisatie en voor collaborators de organisatie van het bijbehorende deck. Vóór het inloggen, bij provisioning en bij instancebrede identiteits- of auditoperaties is een expliciete instancescope met reden nodig. Een scope vervangt de autorisatie van de aanroeper niet. De storage-scope-referentie beschrijft het contract.

    Deze release voegt geen databasemigratie of configuratievereiste toe. De commitlijst staat in de 1.65.0-release op GitHub.

  54. v1.64.0

    Onderhoud voor forks

    Appstyles staan nu bij hun eigen onderdeel. Forks die core-CSS importeren of aanpassen moeten paden bijwerken en de cascadevolgorde controleren.

    De bronbestanden van de appstyles staan nu bij het onderdeel of de gedeelde UI-widget waartoe ze behoren. Forks die deze bestanden importeren of aanpassen moeten vóór de upgrade de paden bijwerken; op de oude paden staan geen compatibiliteitsbestanden.

    Gewijzigde CSS-paden

    Alle onderstaande paden zijn relatief aan client/styles/app/.

    Oud padNieuw pad
    shell/20-editor-layout.csseditor/20-editor-layout.css
    shell/21-editor-skeleton.csseditor/21-editor-skeleton.css
    shell/107-collab-presence.csseditor/107-collab-presence.css
    shell/05-avatar.cssuser/05-avatar.css
    shell/99-notification-bell.cssuser/99-notification-bell.css
    shell/96-activity-feed.csslist/96-activity-feed.css
    list/17-deck-grid.csseditor/17-deck-grid.css
    settings/103-data-source.csseditor/103-data-source.css
    editor/modals/10-modals-base.csscomponents/10-modals-base.css
    editor/modals/11-modals-loading.csscomponents/11-modals-loading.css
    editor/106-shortcuts-overlay.csscomponents/106-shortcuts-overlay.css
    components.csscomponents/00-components.css
    editor/modals/13-modals-misc.csstheme-select/13-theme-picker.css
    shell/110-sandbox-banner.csslist/110-sandbox-examples.css
    share-viewer/75-share-viewer.csseditor/modals/19-modals-revoke.css

    Uit 13-modals-misc.css verhuist alleen de themakiezer, uit 110-sandbox-banner.css alleen het voorbeeldenoverzicht en uit 75-share-viewer.css alleen het intrekkingsvenster. De overige styles blijven bij het oorspronkelijke onderdeel. De slidekiezer- en vertaalvarianten van de modalbasis staan in editor/modals/10-modals-editor.css. components.css is nu een gegenereerd verzamelbestand.

    Controleer overrides die van de laadvolgorde afhangen

    De gedeelde modalbasis laadt nu vóór alle featurestyles; de editorlayout volgt op de shellutilities. Selectors en declaratiewaarden zijn behouden, maar forks met overrides die op de bronvolgorde steunen moeten de cascade controleren.

    Deze release voegt geen databasemigratie of configuratievereiste toe. De commitlijst staat in de 1.64.0-release op GitHub.

  55. v1.63.0

    Onderhoud voor forks

    Slidelockfuncties vragen nu expliciet om de organisatiescope. Forks die opslaghelpers aanroepen moeten twee wijzigingen overnemen.

    Deze release verstevigt de opslaggrens bij het opslaan van slides. Slidelocks blijven hetzelfde werken; de functies die het lockbeleid afdwingen controleren eerst de organisatiescope. Forks die deze helpers rechtstreeks aanroepen, moeten hun aanroepen vóór de upgrade aanpassen.

    Aanroepen van slidelockfuncties

    In server/storage/presentations/crud/enforce-slide-locks.js vragen zowel enforceSlideLocks als enforceSlideWritePolicy nu om (scope, opts) in plaats van ({ctx, ...opts}). Geef de organisatiescope als eerste argument mee en verwijder opts.ctx. Het importpad blijft gelijk.

    Helper voor themaseeds in forks

    upsertThemeSeeds(db, seeds) is verhuisd van server/utils/theme-seeds.js naar server/storage/themes.js en heet daar upsertThemeSeeds(scope, seeds). Pas rechtstreekse imports aan en geef een expliciete instantiescope mee in plaats van een databasehandle. Op het oude pad staat geen compatibiliteitsexport.

    Deze release voegt geen databasemigratie of configuratievereiste toe. De commitlijst staat in de 1.63.0-release op GitHub.

  56. v1.62.0

    Beveiligingsrelease

    Sandboxgasten zijn beter van elkaar afgeschermd en organisaties kunnen eigen instructies voor AI-vertalingen instellen.

    Deze release sluit meer manieren af waarop bezoekers van een openbare sandbox elkaar kunnen zien of benaderen. Organisatiebeheerders kunnen daarnaast terminologie en stijl per doeltaal instellen voor AI-vertalingen. Forks die het oude pakket met vertaalregels gebruiken of presenter-runtimebestanden rechtstreeks importeren, moeten vóór de upgrade worden aangepast.

    Gebruikt je fork ciiic-translation-rules? Bewaar de terminologie en stijltekst per taal vóór de upgrade. Vul die tekst na de upgrade in onder Instellingen > Beheer > Vertaalinstructies, voordat je weer vertaalt. Het pakket wordt niet meer geladen en er is geen automatische migratie.

    Privacy van sandboxgasten

    • Organisatietags zijn verborgen. De taglijst en automatische aanvulling van de organisatie tonen geen gedeelde termen meer aan sandboxgasten. Gasten kunnen nog wel tags op hun eigen privépresentaties gebruiken.
    • Voorbeeldpresentaties worden geen gesprekskanaal. De voorbeelden blijven leesbaar, maar reacties, aantallen, live-updates en het overzicht met recente reacties zijn afgesloten, ook voor berichten die vóór deze release zijn geplaatst.
    • Deelopties zijn afgesloten. De sandbox weigert deellinks en het deelvenster legt uit waarom de opties op het tabblad Gasten zijn uitgeschakeld.

    Vertaalinstructies per organisatie

    Beheerders kunnen gedeelde terminologie en een aparte stijl voor elke ingeschakelde doeltaal invullen onder Instellingen > Beheer > Vertaalinstructies (/settings#admin). De velden staan in organizations.settings.translationInstructions: terminology geldt voor alle doeltalen en styleByLanguage[taalcode] alleen voor die taal. Bij ingeschakelde AI gebruiken vertalingen deze instructies.

    Migreer je een fork met ciiic-translation-rules, bewaar dan vóór de upgrade een kopie van de terminologie en stijltekst per taal. Zet die tekst na de upgrade over naar de nieuwe velden en verwijder daarna het verouderde pakket en de installatie ervan in de Dockerfile. Controleer de opgeslagen instructies voordat je weer vertaalt; er wordt niets automatisch overgenomen.

    Gewijzigde importpaden voor forks

    De presenter-runtimebestanden zijn zonder compatibiliteitsshims verhuisd. Pas rechtstreekse imports aan voordat je naar deze versie synchroniseert:

    Oud padNieuw pad
    client/views/presenter/step.jsclient/lib/slide-runtime/step.js
    client/views/presenter/auto-advance.jsclient/lib/slide-runtime/auto-advance.js

    De commitlijst staat in de 1.62.0-release op GitHub.

  57. v1.61.0

    Onderhoudsrelease

    Forks die de tag-editor importeren moeten de nieuwe publieke ingang gebruiken.

    De tag-editor staat nu bij de tags-feature. In Deckyard werkt hij hetzelfde, maar forks die hem via een bestandspad importeren moeten die import vóór de upgrade aanpassen.

    Voor forks: importpad van de tag-editor verhuisd

    Vervang client/views/list/tag-editor.js door de publieke ingang client/views/tags/index.js voor createTagEditor. Het oude pad is zonder compatibiliteitsshim verwijderd. Er is geen migratie van opgeslagen gegevens of nieuwe configuratie nodig.

    De commitlijst staat in de 1.61.0-release op GitHub.

  58. v1.60.0

    Onderhoudsrelease

    Beschrijvingen van gepubliceerde decks volgen de gekozen taal; forks moeten comments-imports aanpassen.

    Gepubliceerde decks gebruiken nu de gekozen taal voor hun standaardbeschrijving, de terugvaltekst bij een ontbrekende titel en de link naar de leesweergave. Dat geldt ook voor zoekmetadata en gestructureerde gegevens: een Engels deck krijgt geen Nederlandse standaardbeschrijving meer. Lege lijsten en keuzeschermen hebben daarnaast een consistentere vormgeving.

    Voor forks: comments-imports verhuisd

    Pas eigen imports aan vóór de upgrade. Zeven modules zijn zonder compatibiliteitsshim verhuisd van client/views/editor/ naar client/views/comments/:

    Vorig padNieuw pad
    client/views/editor/comment-markers.jsclient/views/comments/comment-markers.js
    client/views/editor/comments-api.jsclient/views/comments/comments-api.js
    client/views/editor/comments-panel.jsclient/views/comments/comments-panel.js
    client/views/editor/comments-panel-actions.jsclient/views/comments/comments-panel-actions.js
    client/views/editor/comments-panel-renderers.jsclient/views/comments/comments-panel-renderers.js
    client/views/editor/comments-panel-sse.jsclient/views/comments/comments-panel-sse.js
    client/views/editor/comments-read-state.jsclient/views/comments/comments-read-state.js

    Importeer createCommentMarkers, createCommentsApi en createCommentsPanel via de publieke ingang client/views/comments/index.js. De overige verhuisde bestanden zijn interne onderdelen van die feature. Deze release vraagt geen nieuwe configuratie of migratie van opgeslagen gegevens.

    De commitlijst staat in de 1.60.0-release op GitHub.

  59. v1.59.1

    Onderhoudsrelease

    Bibliotheekitems met een ongeldige vorm voor taalversies worden vóór opslag geweigerd.

    Deckyard controleert nu de vorm van de taalversies van een bibliotheekitem voordat het item wordt opgeslagen. Ongeldige gegevens krijgen een duidelijke weigering in plaats van dat ze bewaard worden en bij een latere bewerking taalinhoud kunnen verliezen. Bestaande geldige bibliotheekitems blijven werken zoals voorheen.

    Deze release herstelt ook de QR-renderer voor de automatische documentatiebeelden van de website. De QR-codes die gebruikers in Deckyard zien veranderen niet.

    De volledige commitlijst staat bij de 1.59.1-release op GitHub.

  60. v1.59.0

    Feature-release

    Clientmodules staan nu bij de schermen en gedeelde widgets die ze gebruiken. Forks met imports uit verplaatste bestanden moeten hun paden aanpassen.

    Forks die rechtstreeks clientmodules van Deckyard importeren moeten de onderstaande paden vóór de upgrade aanpassen. Deze breaking change verschijnt tijdens de beta als MINOR-release. Decks en opgeslagen gegevens hebben geen migratie nodig.

    De modules voor live bewerken staan nu bij de editor. Gedeelde browserhelpers staan in de DOM-, netwerk- en statelagen. Zo heeft elke module één duidelijke eigenaar. Deze release bevat geen nieuwe functies of verplichte omgevingsvariabelen.

    Gewijzigde importpaden voor forks

    Oud padNieuw pad
    client/lib/util/clipboard.jsclient/lib/dom/clipboard.js
    client/lib/format/lang-selector.jsclient/lib/dom/lang-selector.js
    client/lib/util/qr.jsclient/lib/dom/qr.js
    client/views/ui-mode-switcher.jsclient/lib/dom/ui-mode-switcher.js
    client/lib/util/file.jsclient/lib/net/file.js
    client/lib/util/debug.jsclient/lib/state/debug.js
    client/lib/util/dev-runtime.jsclient/lib/state/dev-runtime.js
    client/lib/util/id.jsclient/lib/state/id.js
    client/lib/collab/live-doc-binder.jsclient/views/editor/live-edits/live-doc-binder.js
    client/lib/collab/presence-session.jsclient/views/editor/live-edits/presence-session.js
    client/lib/collab/textarea-merge.jsclient/views/editor/live-edits/textarea-merge.js
    client/views/notes-join.jsclient/views/notes/notes-join.js
    client/views/present-window.jsclient/views/presenter/present-window.js
    client/views/theme-select.jsclient/views/theme-select/index.js

    Voor de oude paden bestaan geen compatibiliteitsshim. Pas imports in je fork aan voordat je naar deze tag synchroniseert. De volledige wijziging staat in de 1.59.0-release op GitHub.

  61. v1.58.0

    Feature-release

    Gasten kunnen weer reageren via een deellink. Beeldvoorbeelden tonen het hele beeld, grafiekkoppen volgen het thema en de wekelijkse samenvatting werkt voor accounts die zich aanmelden.

    Forks die de oude QR- of slughelpers importeren moeten hun imports vóór de upgrade aanpassen. Dit is tijdens beta een MINOR-release omdat die modulepaden veranderen.

    Deze release herstelt gastreacties, maakt beeldvoorbeelden en grafiekkoppen consistenter en brengt de wekelijkse samenvatting terug als opt-inmail. AI en MCP gebruiken op meer paden hetzelfde aanbod van slidetypes, inclusief eigen types in stdio-sessies.

    Delen en bewerken

    • Gastreacties werken via deellinks. Gasten kunnen reacties lezen en hun eigen reacties toevoegen, bewerken of verwijderen via de link van het gedeelde deck.
    • Beeldvoorbeelden tonen het hele gekozen beeld, ook bij portretten en vierkante bestanden. Grafiekkoppen volgen nu de hoofdletterinstelling van het thema.
    • Een ongeldige publicatieslug wordt inline geweigerd. Een expliciet opgegeven URL-slug moet al geldig zijn en wordt niet meer stil gerepareerd. Slugs die uit titels worden afgeleid verwerken accenten en scheidingstekens consistent. Bestaande publicatieslugs blijven staan.
    • Een geweigerde invoer blijft bij het veld. Verkeerde wachtwoorden en weigeringen bij databronnen staan inline; een bestaand gebruikersadres markeert en focust het e-mailveld. Instellingen en de zijbalk gebruiken dezelfde tablijst.

    AI en agents

    • MCP-stdio ziet gepubliceerde eigen slidetypes en de curatie van de standaardorganisatie. Een mislukte lookup geeft een weigering in plaats van een lege catalogus. AI-generatie accepteert een type alleen waar het wordt aangeboden.
    • Imports en AI-verzoeken gebruiken dezelfde invoerregels. De v1-API weigert een niet-tekstuele raw, veilige aanmaakinstellingen gaan mee en gewone imports gebruiken voor lege beeldvelden dezelfde placeholders als AI-output.
    • HTTP-fouten hebben machineleesbare codes. Applicatiefouten op het hoogste niveau behouden hun code en geregistreerde details; MCP-transportfouten gebruiken error en message. JSON-RPC-fouten behouden hun protocolvorm.

    Breaking changes voor forks

    • QR-helpers verhuizen van client/lib/slide-runtime/poll.js naar client/lib/util/qr.js. Pas imports van renderQrToCanvas en createQrDataUrl aan. De ongebruikte exports getOrCreateVoterId en mountPollBars zijn verwijderd.
    • server/utils/slug.js en de export safeSlug zijn verwijderd. Gebruik generateSlug uit shared/slug.js; geef { fallback: 'presentation' } mee waar die standaard nodig is. Expliciete slugs worden met isValidSlug gecontroleerd, niet gerepareerd.

    Voor self-hosters en forks

    • De wekelijkse samenvatting werkt weer en is opt-in. Accounts zonder expliciet ingeschakelde voorkeur ontvangen geen samenvatting. Een account met digest.enabled: true kan weer mail ontvangen; controleer bestaande opgeslagen voorkeuren als je de samenvatting eerder had aangezet.
    • Migratie 091 normaliseert opgeslagen e-mailstempels op decks. Ze trimt owner_email, created_by en updated_by, zet ze om naar kleine letters, maakt lege waarden NULL en logt het aantal aangepaste rijen per kolom. Nieuwe schrijfacties gebruiken dezelfde normalisatie. Maak vooraf een databasebackup; een rollback herstelt de oorspronkelijke hoofdletters niet.
    • AI-gesprekslogging heeft één optionele instelling: AI_SESSION_LOGS. Zonder instelling worden volledige gesprekken alleen gelogd bij NODE_ENV=development; in productie staat dit uit. Stel de variabele expliciet in om logging aan of uit te zetten. Fork-aanroepers moeten de verwijderde optie enableLogging per aanroep weghalen.
    • Loaders voor het aanbod van slidetypes vereisen een gevalideerde storage-scope. Fork-integraties die deze loaders aanroepen moeten die scope meegeven. Er zijn geen dependencywijzigingen of nieuwe verplichte omgevingsvariabelen; het aantal core-slidetypes blijft 34.

    De volledige lijst per commit staat in de 1.58.0-release op GitHub.

  62. v1.57.0

    Feature-release

    AI en agents bouwen met de slide-types van je eigen organisatie, en de Notion-import werkt weer. Het PPTX-sjabloon verhuist naar de themakaart en opent op een voorbeeld per layout, de slidebibliotheek krijgt een eigen adres, zoeken in een deck leest vertalingen mee, en een ronde feedback-fixes: minder toasts, de reden van de server als iets mislukt, en focus die landt waar je was.

    De rode draad in deze release is dat de AI-paden eindelijk dezelfde slide-types zien als jij. Een deck dat het model genereert, importeert of analyseert, wordt samengesteld uit de types en grenzen van je eigen organisatie, niet uit de ingebouwde catalogus. Daaromheen: het PPTX-sjabloon krijgt een betere plek, de slidebibliotheek een adres dat je kunt delen, en een lange lijst kleine dingen die de interface slecht vertelde, worden nu goed verteld.

    AI en agents gebruiken de slide-types van je organisatie

    • Gegenereerde en geïmporteerde decks gebruiken je eigen types. Aanmaken via MCP, converteren, Notion, markdown-import, de wizard, toevoegen en verfijnen stellen allemaal samen uit de typemap van de organisatie en de ingestelde defaults, en de AI krijgt je eigen types aangeboden terwijl uitgeschakelde types buiten beeld blijven. De analyse die een type voorstelt doet hetzelfde.
    • De Notion-import werkt weer. Elke Notion-import met inhoud om te verfijnen faalde sinds 1.0.0; hij loopt weer door.
    • AI-suggesties en de v1-API voegen in de goede groep in. Een slide die na een kindslide wordt ingevoegd, hoort nu bij de groep van dat kind, in plaats van op het hoogste niveau tussen de kinderen te belanden.
    • Vertalen en ontbrekende vertalen bereiken elke string in een lijst- of kaartitem, ook die het type niet declareert, zodat een vertaalgat eindelijk dicht kan.
    • De AI kiest alleen een achtergrond die het slide-type aanbiedt, dus een slide komt niet meer terug met een keuze die de editor stilletjes terugzet.

    Bewerken

    • De slidebibliotheek heeft een eigen adres, /app/slide-library. Een gekopieerde slide-link opent die slide in een nieuw tabblad, en Sluiten brengt je terug naar de bibliotheek; een ontbrekende of verborgen slide zegt dat inline. Eerder werd de bibliotheek-route behandeld als een deck met de naam “slide-library”.
    • Zoeken in een deck leest vertalingen en itemtitels. Diep zoeken vindt slidetekst in andere taalversies en in de titels van lijst- en kaartitems.
    • Een grafiekkoppeling neemt een bereik en krijgt een tabel. Koppel een grafiek aan A1:B10 in een sheet of CSV en de hele tabel komt binnen met de eerste rij als kop, waar eerder één waarde aankwam en de grafiek brak.
    • Instellingen onthoudt het tabblad zonder je browsergeschiedenis te vullen: wisselen van tab voegt geen regel per klik meer toe.
    • Bunny-videospelers nemen hun kleuren uit het thema in plaats van vaste merkkleuren, en een kale Bunny-video-UUID heeft nu een bibliotheek nodig: vul het Bunny-bibliotheek-ID van de slide in, plak een volledige Bunny-URL, of zet BUNNY_LIBRARY_ID op de instance zodat nieuwe videoslides in je eigen bibliotheek beginnen.

    Feedback die zegt wat er gebeurde

    • Achtentwintig succes-toasts zijn weg waar het scherm het resultaat al toont: een thema verwijderen, een deck dupliceren, een foto uploaden, een collectie aanmaken. Toasts blijven voor opslaan zonder ander zichtbaar teken en voor effecten buiten beeld.
    • Een mislukte actie toont de reden van de server, “te groot” of “verkeerd type”, in plaats van algemene tekst, bij afbeeldingen uploaden, van organisatie wisselen, bulk naar de prullenbak en terug, PDF-export en meer.
    • Een fout op de achtergrond blijft waar hij hoort. Een falende export-poll, een herlaad van slide-types of een autosave van een bibliotheekbeschrijving toont een inline melding naast wat faalde, die verdwijnt bij het volgende succes, in plaats van een toast die na vijf seconden weg is.
    • De minutenlange toast “Wijzigingen opslaan…” is weg. Een kleine pil linksonder verschijnt alleen als opslaan langer dan een moment duurt, en een afbeelding die wordt geüpload dimt op zijn plek.
    • Een mislukte taak zegt in gewone woorden waarom, “Presentatie niet gevonden”, of de eigen tekst van het paneel, nooit een rauwe interne fout.
    • Een rij die verdwijnt geeft de focus terug aan de lijst. Een thema, lettertype, gebruiker, lid, collectie, API-sleutel of weggegooid deck verwijderen zet de focus op de buurrij en zegt het hardop; terugzetten uit de prullenbak landt op de volgende kaart.

    Presenteren en kijken

    • KPI-tegels zijn leesbaar op elke donkere ondergrond. Het glas van de tegel volgt zijn ondergrond en de positieve en negatieve delta’s halen AA-contrast op Midnight, calm en elk eigen donker thema.
    • De foutkaart van een grafiek spreekt de taal van het deck en staat op de ondergrond van de slide, waar hij eerder een felle plaat op een donkere slide was, altijd in het Nederlands. Lijngrafieken bieden nu “Waarden tonen” zoals de andere.
    • Analytics: de tijdlijn van weergaven labelt elke rasterlijn met de eigen waarde, in hele stappen, en schermlezerteksten op de heatmap en tijdlijn krijgen het juiste meervoud.
    • Linkvoorvertoningen volgen de instance. Met OG_IMAGE_URL en OG_DESCRIPTION ingesteld ontvouwt een gedeelde app-link met je eigen naam, beeld en beschrijving, en een deel- of publicatielink zonder deckbeeld valt op dat beeld terug.

    Exporteren en insluiten

    • Het PPTX-sjabloon download je van het thema, niet van een deck. Elke themakaart in Instellingen → Thema’s heeft “PPTX-sjabloon downloaden”, genoemd naar het thema. Het opent op één voorbeeldslide per layout, met de themanaam op de cover en een gestippeld beeldkader, in plaats van een lege zwarte slide.
    • Videoplaceholders in een PPTX-export nemen de kleuren van het thema, niet vaste merkkleuren.
    • De embed-SDK-box groeit met de balk mee onder ui: 'strip', zodat de bediening niet meer wordt afgesneden, en de controller krijgt setOptions(patch).

    Voor wie zelf host of forkt

    Geen databasemigraties. Drie nieuwe variabelen, allemaal optioneel: OG_IMAGE_URL en OG_DESCRIPTION voor linkvoorvertoningen, BUNNY_LIBRARY_ID voor nieuwe videoslides. Het aantal slide-types blijft 34.

    • Het deckschema gaat van v18 naar v22, via vier stappen in de leesfunnel die draaien bij lezen, schrijven en importeren: slidecreator.deck vouwt naar deckyard.deck; layout van de image-slide vouwt naar fit en bleed; altNl en altEn vouwen naar alt; de oude bgImage, bgAlt en bgImagekitFileId op elke slide vouwen naar de gedeelde achtergrondlaag. JSON-schema-id’s verhuizen naar /v22/.
    • De import laat contentsleutels vallen die een type niet declareert, bij JSON, .deck, Notion, converteren en de AI-paden. Een fork-type dat een ongedeclareerde sleutel leest, moet hem declareren, als verborgen veld of via instanceKeys.
    • MCP wordt strenger. add_slide en update_slide slaan inhoud op zoals verstuurd of weigeren met 400 en errors; ze repareren niet meer stilletjes (validation: 'fix' blijft). De alias id is weg: elke deck-gebonden tool neemt presentationId. get_slide_types geeft het echte voorbeeld van het type als example. Een deck zonder lang valt bij converteren, itereren en toevoegen terug op nl.
    • API: een geweigerde actie op een gepromoveerde vraag antwoordt closed (409); locked betekent nu alleen nog de slide-lock (423). GET /api/jobs/:id geeft voor een mislukte taak geen error meer, alleen message als er een zin voor de aanroeper is. Nieuw: GET /api/v1/themes/{id}/template.pptx; de sjabloonroute per deck is weg.
    • Naden die een fork raakt: newSlide(), convertSlideToType(), newPresentation() en de AI-fix- en refine-functies vereisen slideTypes en gooien zonder; loadSlideTypeContext is vervangen door loadSlideTypeOffer(); de ai.examples van een eigen type hebben de vorm { variation, content }; de title-view-naad in core-layouts.js exporteert titleInlineEdit en rendert zonder ondergrond als view.background null is. Weg: validate-slide-structure.js, shared/phosphor-icons.js, shared/slide-schemas.js, TitleView.bgImage, resolveSlideBgImage, BUNNY_PLAYER_COLORS en de alias ?s= voor ?slideId=.
    • Een globale box-sizing: border-box-reset staat nu in de gedeelde primitives en op .slide; fork-CSS die op content-box rekende, kan met zijn padding verschuiven. De klasse van de opslagindicator is .editor-save-status met .is-failure.

    De volledige lijst op commitniveau staat in de 1.57.0-release op GitHub.

  63. v1.56.0

    Feature-release

    Zet een deck op je site met een smalle bedieningsbalk onder de slide in plaats van pijlen eroverheen. Nieuwe titelslides openen op een themafoto, kijkpagina's spreken de taal van het deck, getelde woorden krijgen het juiste meervoud en tekst over een achtergrondfoto blijft leesbaar, hoe het deck ook gemaakt is.

    Het enige nieuwe in deze release is voor wie een deck op een website zet. De rest is een ronde fixes die je merkt tijdens bewerken en presenteren: een deck dat vanaf de eerste slide klopt, pagina’s in de goede taal en een manier minder waarop tekst in een foto verdwijnt.

    Een bedieningsbalk voor ingesloten decks

    • Zet ?ui=strip achter een geëxporteerd deck (/p/ of de gedownloade .html) of een hosted embed en je krijgt de slide van rand tot rand met één smalle balk eronder: Vorige, Volgende, de teller en Volledig scherm. Een site die een deck in een iframe zet, hoeft geen eigen pijlen meer over de slide te leggen.
    • In volledig scherm stapt de balk opzij en komt hij terug als je de muis beweegt, net als in de presenter.
    • De gewone exportbalk heeft nu ook een knop Volledig scherm, en de teller in de embed is weer leesbaar (hij was zwart op zwart).

    Bewerken

    • Een nieuwe titelslide opent op een foto van het thema als het thema achtergrondpresets heeft, of je hem nu invoegt, importeert of ernaar omzet. De sectie Achtergrondbeeld staat op de cover standaard open. Thema’s zonder presets blijven vlak.
    • Tekst over een achtergrondfoto blijft op elke route leesbaar. Een deck dat nooit door de editor gaat (gemaakt via MCP, geïmporteerd, door AI gegenereerd of meteen gepresenteerd) krijgt nu dezelfde tekstkleur en scrim die de editor zou kiezen, in de presenter, op een deellink en in de PDF.
    • Een themawissel die het type van een slide verandert, doet dat nu in elke taalversie van het deck, elk met de eigen tekst, in plaats van alleen in de hoofdtaal.
    • De slide-werkbalk deelt het grijs van het canvas, zodat je in één oogopslag ziet welke balk bij de slide hoort en welke bij het hele deck.

    Kijken en de interface

    • Deellinks, meekijkpagina’s en /go spreken de taal van het deck, anders die van de browser, anders Engels. Een opgeslagen voorkeur of ?locale= wint nog steeds, en /go is nu vertaald.
    • Getelde woorden krijgen het juiste meervoud: “1 slide” in plaats van “1 slides”, in het startscherm van de presenter, de bibliotheek, delen, importeren en tientallen andere tellers.
    • Kleine fixes uit de sandbox-ronde: de knop Analytics verschijnt meteen nadat je een deellink maakt, het taalfilter in de bibliotheek telt goed, Home in het Nederlands is helemaal Nederlands, de themakaart Midnight is leesbaar en de topbalk van de presenter past op een telefoon.

    Voor wie zelf host of forkt

    Geen databasemigraties en geen nieuwe variabelen. Het aantal slide-types blijft 34.

    • Een MCP-tool die onverwacht faalt, antwoordt nu “Internal server error” en logt de rest, net als de v1-API. Een eigen tool die een gewone Error gooit met een zin voor de gebruiker, gooit voortaan een AppError met de passende status.
    • De standaard interfacetaal is overal Engels. Een verse browser zonder voorkeur ziet de loginpagina in het Engels; DEFAULT_UI_LOCALE staat in shared/constants/ui-locale.js.
    • Getelde zinnen lopen via één meervoudsnaad: een t()-aanroep voor een getelde zin geeft { one, many } als fallback plus { count }, en een fork-locale vult <sleutel>.one en <sleutel>.many.
    • Het contrast over een achtergrondbeeld wordt bij het opslaan op de server bepaald. Een eigen schrijfpad via de storage-facade krijgt dat vanzelf; een pad dat updatePresentationRow omzeilt niet.
    • Een eigen override van de embed-toolbar moet data-presenter-chrome houden, anders blijft hij in volledig scherm niet staan onder de muis.

    De volledige lijst op commitniveau staat in de 1.56.0-release op GitHub.

  64. v1.55.0

    Onderhoudsrelease

    Vertaalde decks raken geen tekst meer kwijt: themawissels, vertalingen en MCP-bewerkingen laten elke taalversie staan. Editor, API en MCP weigeren dezelfde foute invoer met hetzelfde antwoord, Insights toont echte voltooiingspercentages en de sandbox kreeg een poetsronde.

    Deze release gaat erover dat een deck zich hetzelfde gedraagt, hoe je het ook aanraakt: in de editor, via de publieke API of via een AI-agent over MCP. Het meeste werk zit eronder, maar je merkt het aan minder stille verrassingen. Werk je met vertaalde decks, update dan: verschillende schrijfacties konden een andere taalversie van een deck overschrijven met de brontekst.

    Check vóór je updatet: API- en MCP-wijzigingen

    Deckyard is in beta, dus strengere invoercontroles komen in een minor release. Roep je de API aan of draai je een MCP-agent, dan zijn deze antwoorden veranderd:

    • Onbekende waarden worden geweigerd in plaats van geraden. Een commentfilter (status, commentType, since), een thema, ownership, viewOnly, deep, een analytics-sort of -period, een niet-boolean keepAsCollaborator of isViewOnly, en een ontbrekende of onbekende vertaaltaal geven allemaal een 400 invalid met het veld in details.field.
    • Te groot is overal een 409 limit_exceeded. Een v1-save, een create, een vertaling of een MCP-schrijfactie boven de groottelimiet antwoordde eerder 200 of 201 zonder op te slaan; nu zegt hij het.
    • MCP list_presentations en list_recent_comments kennen collection (jouw decks plus de organisatie-zichtbare, zoals Home ze toont). all neemt nu ook organisatie-zichtbare decks mee, en owned matcht op je account in plaats van op een e-mailstring.
    • MCP-toolfouten dragen de v1-envelope (error, message, details), dus een agent ziet welk veld fout was. Een mislukte AI-generatie via v1 is een 502 bad_gateway die zegt wat het model fout deed, en elk v1-foutantwoord draagt de rate-limit-headers.
    • Eigendom en zichtbaarheid wijzigen is strenger: zichtbaarheid wijzigen vraagt leestoegang tot het deck, een org-admin wijzigt alleen decks die hij kan lezen, en de notificatie- en webhooklinks worden gebouwd op APP_URL in plaats van de Host-header van het verzoek.

    Vertaalde decks houden hun talen

    • Een themawissel of publicatie op een deck dat je laatst in een andere taal bewerkte, overschrijft die taalversie niet meer.
    • Vertalen vanuit een niet-dominante taal (bijvoorbeeld Duits op een Nederlands deck) overschrijft die bronversie niet meer, en de editor, de API en de vertaalwachtrij weigeren nu dezelfde fouten.
    • MCP-bewerkingen (update_slide, remove_slide, reorder_slides, append_slides, compress_presentation, iterate_presentation) schrijven alleen de slides en laten de andere taalversies staan. remove_slide weigert de laatste slide, en gegenereerde slides met een onbekend type worden geweigerd in plaats van opgeslagen.
    • Een deck dat je start vanuit bibliotheekslides krijgt de taal waarin die slides geschreven zijn.

    Insights

    • Het voltooiingspercentage toont een echt getal op Insights, in Top Performing en op de eigen analytics van een deck: het aandeel sessies dat de laatste slide haalde, in plaats van altijd een streepje.

    Bewerken en de sandbox

    • Een themawissel die een slide niet kan omzetten wordt geweigerd, met de reden naast Toepassen, in plaats van de slide ongewijzigd onder het nieuwe thema te laten.
    • De bouwblokken op Home tonen dezelfde slidepreview als de bibliotheek, ook op een telefoon, en het “Nieuw voor jou”-label bedekt het typelabel niet meer.
    • De sandbox is eerlijker over wat hij is: geen zinloze uitlogknop, de accounttab legt uit waarom foto en wachtwoord ontbreken, de slidetaal en de bibliotheekpreviews volgen de interfacetaal, en een voorbeelddeck openen vult Insights met zijn kijkgeschiedenis.
    • Analyticspagina’s tonen geen letterlijke accolades meer (Device {id}), op elke installatie.

    Voor wie zelf host

    Geen databasemigraties en geen nieuwe variabelen. Het aantal slidetypes blijft 34.

    Voor de volledige lijst op commitniveau, zie de 1.55.0-release op GitHub.

  65. v1.54.0

    Feature-release

    PowerPoint-export die je kunt bewerken: de meeste slidetypes komen nu mee als echte tekst, beelden, grafieken en tabellen in plaats van als plaatje. Tekststijlen worden per slidetype aangeboden, beelden upload je in batches en de sandbox-bibliotheek toont echte voorbeeldslides. Forks en API-gebruikers lezen eerst de brekende wijzigingen.

    De kern van deze release is een tweede PowerPoint-export: een die je kunt blijven bewerken. Daarnaast worden tekststijlen nu per slidetype aangeboden in plaats van overal, upload je beelden in batches met desgewenst AI-alt-tekst, en kan een installatie live presenteren, stockbeeld en de publieke API elk weglaten. Deckyard is in beta, dus de brekende wijzigingen hieronder komen in een minor release; draai je een fork of roep je de API aan, lees dan eerst het eerste blok.

    Check vóór je updatet: API- en forkwijzigingen

    • Het type custom-html-slide is weg (34 ingebouwde types, was 35). Een opgeslagen slide van dat type verschijnt als gearchiveerde slide met de markup als tekst. CUSTOM_HTML_EDITOR_EMAILS doet niets meer en kan uit je omgeving.
    • Tekststijlen zijn een aanbod per type. Uitlijning en grootte worden alleen geaccepteerd waar het slidetype ze declareert; al het andere wordt geweigerd met een 400 text_style_*. Tekstkleur per veld is weg en opgeslagen kleuren vallen bij het lezen weg, en thema’s verliezen textSwatches. Een fork-type met eigen JavaScript declareert zijn aanbod (textStyle, itemTextStyle, textStyleSets), anders vallen zijn opgeslagen stijlen weg. De volledige regel staat in de referentie over tekststijlen.
    • Quote-slides bewaren elke quote in quotes[]. API- en MCP-aanroepers posten quotes[]; de platte sleutels worden door strikte validatie geweigerd. Opgeslagen decks vouwen bij het lezen.
    • De CSS van een fork-type staat alleen nog in custom/styles/. Een custom/slide-types/*.js-type dat bij het renderen een <style>-blok uitstuurt, wordt bij het laden geweigerd; zet de regels in een stylesheet, genest onder de rootklasse van het type. Een fork kan de titelslide van core nu componeren via shared/slide-types/core-layouts.js in plaats van hem te kopiëren.
    • De ImageKit-slot geeft createImageKitPanel mee en levert { el, detach }; de picker beheert de dialoog. openImageKit meegeven werpt een fout.
    • Clientmodules verhuisd, voor forks die per pad importeren: slide-bibliotheek, comments, collecties, gebruiker, de analytics-tracker en de themakeuze zijn nu views (client/views/…/index.js). De volledige padlijst staat in de GitHub-release.

    PowerPoint die je kunt bewerken

    • Twee PowerPoint-rijen in het exportmenu. “PowerPoint” blijft pixel-perfect: elke slide als beeld, video’s spelen af. “PowerPoint, bewerkbaar” schrijft slides op de layouts van je thema als echte tekst, en meldt welke slides nog als beeld meegingen.
    • De meeste slidetypes exporteren native: titel, tekst, lijst, tabel, tekstblokken en eindslide, plus beeld, beeld met tekst, quote, hoofdstuktitel, KPI-kaarten, grafieken (als bewerkbare PowerPoint-grafiek), callouts en vergelijkingen. Opsommingstekens overleven gemengde opmaak, ook in LibreOffice.
    • Je geüploade lettertypen houden hun desktopnaam in het PowerPoint-bestand, zodat een machine met dat lettertype het ook toont.
    • Via API en MCP: GET /api/v1/presentations/{id}/export/pptx-editable (de header X-Image-Slides noemt de beeldslides), en MCP export_presentation biedt pptx-editable met een downloadlink.

    Bewerken

    • Tekststijlen waar ze iets betekenen. Uitlijning en grootte verschijnen alleen op slidetypes die ze aanbieden. Op de titelslide schalen titel en subtitel los van elkaar S/M/L. MCP-clients zien het aanbod per type in get_slide_types.
    • Itemsettings hebben een eigen tab. Klik een rij, cel of kaart aan en de instellingen (kleur, pijl, icoon, link) staan in een tab “Deze rij” / “Deze cel” / “Deze kaart”; “Alle tekst” is daarvoor niet meer nodig.
    • Keuzes in de inspector kiezen zelf hun control: korte optielijsten worden knoppen naast elkaar, langere een dropdown, met de uitleg in een tooltip.
    • De KPI-noot is op het canvas te bewerken, en op quote-slides kies je de portretten van elke quote op het canvas.
    • De slidetype-builder kan de kop van een eigen type aanwijzen, die de reader dan als titel van de slide toont.
    • Slidetypenamen in de kiezer zijn vertaald waar ze in het Nederlands nog Engels waren.

    Beeld

    • Upload een hele batch tegelijk voor de bibliotheek, galerijen, logowanden en beeldsets, en bewerk namen en alt-teksten per taal op één scherm vóór je bevestigt.
    • Genereer ontbrekende alt-teksten voor de hele batch, alleen nadat je ermee instemt (OpenAI, aantal beelden, mogelijke kosten), en nooit over tekst die je zelf schreef.

    Presenteren, AI en de sandbox

    • De sprekersnotities tonen de huidige slide altijd volledig, met volgende slide, notities en vragen ernaast op een breed scherm.
    • AI-outlines ontstaan in twee stappen, eerst bronanalyse en dan slidestructuur, en Claude staat standaard op Opus 5. Te lange gegenereerde tekst wordt geweigerd en één keer herschreven in plaats van met ”…” afgekapt.
    • De sandbox-bibliotheek toont echte voorbeeldslides en een collectie, en de bouwblokken staan vanaf het eerste bezoek op Home.

    In productie

    • Nog drie modules zijn weg te laten: LIVE_ENABLED (follow-along, livesessies, polls), STOCK_MEDIA_ENABLED (verlopen, Unsplash, Giphy) en PUBLIC_API_ENABLED (/api/v1, MCP en API-sleutels). Alle drie staan standaard aan.
    • Een gebruiker verwijderen trekt diens openstaande inloglinks in.

    Kleinere fixes

    “Workspace default” noemt het thema waar het op uitkomt; een poll zonder codes noemt de echte follow-URL; het accentpaar van het thema playful haalt 4,5:1 contrast; de voortgangsbalk bij importeren loopt gelijkmatig; comments en compressie noemen een eigen slidetype bij zijn eigen kop.

    Voor wie zelf host

    Eén databasemigratie, die bij het opstarten vanzelf draait. Drie nieuwe optionele variabelen (hierboven), alle standaard aan; CUSTOM_HTML_EDITOR_EMAILS kan weg. Het aantal ingebouwde slidetypes gaat van 35 naar 34, en het deckschema is nu versie 18.

    Voor de volledige lijst op commitniveau, zie de 1.54.0-release op GitHub.

  66. v1.53.0

    Feature-release

    Een beeld kiezen en uploaden past op één scherm, met een directe uploadknop en desgewenst automatische alt-tekst. Installaties zonder uploads tonen geen kapotte uploadknoppen meer, en analytics is nu helemaal uit te zetten.

    Deze release maakt werken met beeld sneller en laat een installatie weglaten wat ze niet gebruikt: uploads en analytics. Bij het updaten hoeft er niets te veranderen.

    Beeld

    • De beeldkiezer past op één scherm. De preview staat naast het formulier, minder gebruikte velden zitten achter “More details” en de actiebalk blijft onderin staan. “Use this image” slaat je wijzigingen ook op.
    • Direct uploaden vanuit een beeldveld. Naast “Choose image…” staat nu een knop “Upload from computer”.
    • Alt-tekst in één stap. De AI-knop voor alt-tekst staat bij het alt-veld, en een onthouden schakelaar, “Generate alt text automatically after upload” (standaard uit), maakt uploaden en alt-tekst schrijven één stap.
    • De Back-knop in de detailweergave laat de beeldkiezer niet meer leeg achter.

    Installaties zonder uploads

    • Geen uploadknoppen waar uploads uit staan. Met UPLOADS_ENABLED=false, IMAGEKIT_ONLY of de demomodus zijn uploadknoppen, dropzones en uploadhulpteksten afwezig in plaats van kapot, ook in de theme-editor, waar het logo-URL-veld blijft. In de publieke sandbox blijven ze zichtbaar maar uitgegrijsd, met één zin uitleg.

    Analytics is uit te zetten

    • Een nieuwe optionele omgevingsvariabele, ANALYTICS_ENABLED (standaard aan). Uit: de tracking- en analytics-API’s antwoorden met 404, gepubliceerde pagina’s krijgen geen trackingscript, deellinks en follow-along tracken niet, de pagina’s Insights, Analytics en publieke reports bestaan niet, de wekelijkse digestmail gaat niet uit, en alle analyticsknoppen en -instellingen verdwijnen uit de app.
    • Opgeslagen data blijft staan. De retentie-opruiming loopt door, en één logregel bij het opstarten meldt hoeveel rijen er nog liggen. Met de schakelaar aan verandert er niets.

    Voor wie zelf host

    Geen databasemigratie en niets te hernoemen; ANALYTICS_ENABLED is de enige nieuwe variabele. Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.53.0-release op GitHub.

  67. v1.52.0

    Onderhoudsrelease

    Twee omgevingsvariabelen hebben een nieuwe naam en uitgeschakelde modules antwoorden nu met een gewone 404. Een release voor beheerders en forks: in de editor verandert niets.

    Deze release is vooral voor wie Deckyard draait. Elke optionele feature declareert zijn schakelaar nu op één plek, zodat een feature die uit staat overal tegelijk uit is: zijn routes, zijn rij in de featuretabel en zijn MCP-tool. Twee omgevingsvariabelen kregen daarbij een duidelijkere naam.

    Controleer dit eerst: hernoemde omgevingsvariabelen

    Deckyard is in bèta, dus deze wijziging komt in een minor release.

    • NOTION_FEATURE heet nu NOTION_ENABLED en schakelt de hele /api/notion/*-module (standaard uit). Een installatie die alleen NOTION_SECRET zette, moet nu ook NOTION_ENABLED=true zetten.
    • DISABLE_ANALYTICS heet nu EXTERNAL_ANALYTICS_ENABLED, met omgekeerde betekenis: true is aan.
    • De oude namen blijven werken met een waarschuwing bij het opstarten, tot de eerste release na 1 november 2026. Hernoem ze voor die tijd.

    Uitgeschakelde modules antwoorden op dezelfde manier

    • Met LIVE_DATA_ENABLED uit antwoordt /api/data-sources/* met 404 (was 403).
    • Met RSS_FEED_ENABLED uit toont /feed/* de gewone 404-pagina in plaats van een 404 in platte tekst.

    Voor wie zelf host

    Geen databasemigratie. Kijk in je omgeving naar NOTION_FEATURE, NOTION_SECRET en DISABLE_ANALYTICS en hernoem zoals hierboven. Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.52.0-release op GitHub.

  68. v1.51.0

    Feature-release

    Een overzicht van de gezondheid van je instance in de admin, reacties die niet meer verloren gaan vlak na een wijziging, en één gedeelde typografische ladder voor kaarten en diagrammen. Decks en reacties aanmaken, dupliceren en verwijderen loopt nu via één service; API-gebruikers en forks lezen de breaking changes.

    Deze release geeft beheerders zicht op hoe hun instance ervoor staat, repareert een manier waarop een reactie in de editor verloren kon gaan, en laat kaarten en diagrammen consistenter schalen. Onder de motorkap worden decks en reacties nu door één service aangemaakt, gedupliceerd en verwijderd, langs welke weg je Deckyard ook aanspreekt. Daardoor veranderen een paar details voor API-gebruikers en forks; lees dan eerst het eerste blok.

    Controleer dit eerst: wijzigingen in API en fork-code

    Deckyard is in bèta, dus deze wijzigingen komen in een minor release.

    • POST /api/v1/presentations/:id/comments beantwoordt een slideId die geen slide van het deck is met 404 slide_not_found (was 400), naast het bestaande parent_not_found.
    • MCP add_comment en reply_to_comment sturen nu mailnotificaties en vuren de comment-webhook, zoals de REST-API en de editor al deden. Een ontbrekend deck geeft 404, een ontbrekend recht om te reageren 403.
    • Een deck aanmaken met een niet-ondersteunde lang wordt geweigerd voordat er werk gebeurt.
    • Voor fork-code: maybeFireWebhook(repoRoot, origin, event) neemt een origin-string waar hij de request nam, en notifyCommentCreated en notifyMentionsAdded nemen geen request meer. notifyCommentCreatedInApp en routes/api/presentations/comments-shared.js zijn weg; importeer in plaats daarvan uit server/services/comments.js.

    Gezondheid van de instance

    • Een nieuwe admin-view laat zien hoe je instance gebruikt wordt: een telling en het gebruik per as, geteld op de plekken waar Deckyard het werk al afhandelt.

    Editor en reacties

    • Een reactie vlak na een slide-wijziging gaat niet meer verloren. De wachtende opslag gaat eerst, daarna de reactie.
    • Het reactieveld blijft binnen het paneel.
    • Het slidenummer staat in een goot naast de thumbnail, in de accentkleur in plaats van rood.

    Slides

    • Kaarten en diagrammen delen één typografische ladder. Kaartrollen en de diagramfamilies halen hun tekstgrootte uit dezelfde schaal, dus matrixtitels en kaartkoppen schalen consistenter.

    In productie draaien

    • npm run doctor waarschuwt als een https-instance zonder TRUST_PROXY draait; dan delen alle gebruikers één rate-limit-bucket. De uploadcheck test nu de echte uploadmap.

    Kleinere reparaties

    • De aanmeldschermen tonen APP_NAME in de titel van het browsertabblad.

    Voor wie zelf host

    Eén databasemigratie (089_instance_health). De Docker Compose-opzet draait hem voor het opstarten; een gewone Node-installatie draait npm run db:migrate. Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.51.0-release op GitHub.

  69. v1.50.0

    Feature-release

    Een productieprofiel: npm run doctor controleert een installatie, het Docker-image heeft een healthcheck en is een derde kleiner. De PNG-export is betrouwbaarder. De exportinstellingen zijn hun PDF_-voorvoegsel kwijt; controleer je omgeving voordat je bijwerkt.

    Deze release maakt Deckyard makkelijker om in productie te draaien, en betrouwbaarder bij het exporteren. Eén ding vraagt je aandacht voordat je bijwerkt: vijf exportinstellingen hebben een nieuwe naam.

    Controleer dit eerst: exportinstellingen hernoemd

    De exportinstellingen gelden voor PNG net zo goed als voor PDF, dus ze zijn hun PDF_-voorvoegsel kwijt:

    OudNieuw
    PDF_EXPORT_TIMEOUT_MSEXPORT_RENDER_TIMEOUT_MS
    PDF_EXPORT_IMAGE_COMPRESSIONEXPORT_IMAGE_COMPRESSION
    PDF_EXPORT_IMAGE_MAX_PXEXPORT_IMAGE_MAX_PX
    PDF_EXPORT_IMAGE_QUALITYEXPORT_IMAGE_QUALITY
    PDF_EXPORT_IMAGE_RETINA_SCALEEXPORT_IMAGE_RETINA_SCALE

    De oude namen werken niet meer als alias. Een instance die er nog een zet, valt na de update stil terug op de standaardwaarde. Roept een fork de functies direct aan: pdfImageEmbedTransform heet nu exportImageEmbedTransform, en pdfImageCompressionConfig heet nu exportImageCompressionConfig.

    In productie draaien

    • npm run doctor controleert een installatie en vertelt wat er ontbreekt of verkeerd staat.
    • Het Docker-image heeft een HEALTHCHECK, zodat je orchestrator weet wanneer Deckyard draait.
    • Het Docker-image is kleiner. Een build in twee stappen brengt het van 2,0 GB naar 1,34 GB.
    • Nieuwe documentatie over het productieprofiel, deployen naar een PaaS en back-ups.

    Export

    • De PNG-export is betrouwbaarder. Hij wacht tot de pagina geladen is in plaats van tot het netwerk stil is, dus de sporadische “Navigation timeout of 30000 ms” bij beeldrijke slides is weg. Beelden worden op weergavegrootte ingebed, zoals de PDF-export al deed.
    • Naadbeelden van een fork alleen waar ze getekend worden. Een export neemt een beeld uit custom/styles/*.css alleen nog op als de export het echt tekent; een deck zonder fork-slidetypes krijgt er geen meer mee.
    • Chrome sluit netjes af na een export op macOS.

    Kleinere reparaties

    • De melding bij een geweigerde aanmelding heeft ruimte tot de kaart eronder.

    Voor contributors

    Acht nieuwe capture-recepten dekken de slide-editors en de editorfamilie, dus de oudste handgemaakte screenshots in de documentatie kunnen nu opnieuw gegenereerd worden. Een font-download zonder antwoord wordt herhaald, en laat npm install falen als hij dan nog niet binnenkomt.

    Voor wie zelf host

    Geen databasemigraties. Het aantal ingebouwde slidetypes blijft gelijk. Hernoem de exportinstellingen hierboven voor of met de update.

    Zie voor de volledige lijst op commitniveau de 1.50.0-release op GitHub.

  70. v1.49.0

    Feature-release

    SSO instellen gaat makkelijker goed: Deckyard controleert de redirect-URI, leest groepen uit een claim, vraagt om extra scopes en toont instance-admins de claims van recente logins. Operators krijgen een runbook voor meerdere organisaties, en forks duidelijkere naden.

    Deze release gaat vooral over single sign-on: in één keer goed instellen, en zien wat je identity provider echt meestuurt als het niet lukt.

    Single sign-on

    • Deckyard controleert de OIDC-redirect-URI bij het opstarten. Klopt hij niet, dan waarschuwt de serverlog en noemt de URI die verwacht werd, zodat je die in je identity provider kunt plakken.
    • Een stap voor de eerste login. Wie als eerste via SSO inlogt, krijgt een stap “Your first login” in plaats van een lege instance.
    • Groepen uit een claim. OIDC_GROUPS_CLAIM vertelt Deckyard in welke claim de groepen van een gebruiker staan.
    • Extra scopes. OIDC_EXTRA_SCOPES voegt scopes toe bovenop openid email profile. Sommige claims komen alleen mee achter een eigen scope, zoals de organisatieclaim van ZITADEL.
    • De claims zien zonder devtools. Instance-admins vinden onder Settings → Admin de claims van de laatste tien SSO-logins, geweigerde logins inbegrepen. Ze staan alleen in het geheugen, en tokens worden nooit getoond.

    Meerdere organisaties

    • Een runbook voor operators en npm run org:create. Meerdere organisaties op één instance draaien heeft nu een beschreven werkwijze, en een commando om een organisatie aan te maken.

    Forks

    • Een fork verklaart welke naden hij bezit. npm run fork:seams toont ze, en de CLAUDE.md van de repository is stabiel, zodat een fork hem door een eigen versie kan vervangen.
    • Beelden uit fork-stijlen komen mee in de export. Lokale beeld-url()’s in custom/styles/*.css zitten nu in PDF-, PNG- en standalone-HTML-exports, zoals fork-fonts al deden.

    Voor wie zelf host

    Geen databasemigraties. Het aantal ingebouwde slidetypes blijft gelijk.

    Breaking, maar alleen als je client-modules importeert. Client-modulepaden zijn verhuisd zonder compatibiliteitslaag: client/lib/dom.js is nu client/lib/dom/index.js, en view-entries staan op client/views/<view>/index.js. Een instance zonder eigen clientcode merkt niets. Tijdens de beta komen zulke breaking changes in een 1.x-release.

    Zie voor de volledige lijst op commitniveau de 1.49.0-release op GitHub.

  71. v1.48.0

    Feature-release

    Installaties met meerdere organisaties kunnen het aanmaken van een organisatie voorbehouden aan instance-admins, en inloggen met een magic link belandt niet meer in een lus terug naar de inlogpagina. Een export overleeft elk onleesbaar font, en de piramide-slide is op elk thema leesbaar.

    Een release van losse eindjes: twee voor installaties met meerdere organisaties, één voor de export, één voor de piramide-slide, en een opgeruimde publieke API.

    Meerdere organisaties

    • Een organisatie aanmaken kan beperkt worden tot instance-admins. Een nieuwe instelling, MULTI_ORG_USER_CREATE_ENABLED, staat standaard op true, dus er verandert niets tenzij je hem zet. Op false krijgt een gewone gebruiker een 403 op “nieuwe organisatie”; alleen instance-admins kunnen er dan een aanmaken. Geldt alleen met MULTI_ORG_ENABLED.
    • Inloggen met een magic link eindigt niet meer in een lus terug naar /login. Wie via een magic link inlogt zonder lidmaatschap van een organisatie, krijgt er nu een in de thuisorganisatie: eigenaar als die leeg is, anders lid. Zo doet SSO het sinds 1.46.0. Installaties met één organisatie blijven ongewijzigd.

    Export

    • Een onleesbaar font kost dat font, niet de export. Sinds 1.47.0 ging de export door na een onleesbaar font; deze release doet hetzelfde voor elk soort font: geüpload, gecureerd en lokaal. Het font dat niet te lezen is valt weg met een waarschuwing in de serverlog, en de PDF- of HTML-export komt af.

    Slides

    • De piramide-slide is leesbaar op lime en mist. Elk niveau is nu een zichtbaar vlak, en de tekst volgt de balk waarop hij staat. Op de thema’s lime en mist verdwenen de bovenste of onderste niveaus eerder in de achtergrond.

    API

    • Het slide-type-schema heeft één route. Het staat op /api/v1/schema/slide-types/:id.json, met het gepubliceerde id als sleutel (bijvoorbeeld eu.deckyard.slide.title). De kale registersleutel en de tweede route, /api/v1/slide-types/{slideType}/schema, zijn weg. Gebruikte je een van beide, schakel dan om.
    • Elke v1-operatie heeft een operationId in /api/v1/openapi.yaml. Genereer je clientcode uit de spec, dan krijg je nu stabiele methodenamen.

    Voor wie zelf host

    Geen databasemigraties en geen breaking changes behalve de vervallen schema-route hierboven. Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.48.0-release op GitHub.

  72. v1.47.0

    Feature-release

    Geüploade fonts zijn privé: Deckyard serveert ze zelf in plaats van via een publieke URL. Een export faalt niet meer op één onleesbaar font en neemt elke fontrol mee.

    Deze release gaat over fonts. Een font dat je uploadt staat niet meer op een publieke URL, en een deck exporteren gaat robuuster om met de fonts die erin gaan.

    Geüploade fonts zijn privé

    • Deckyard serveert geüploade fonts zelf. Een font dat je uploadt staat niet meer op een publieke bucket- of /uploads/-URL. Deckyard serveert het op /fonts/managed/…, alleen voor deze site en zonder indexering. Voor gelicenseerde fonts, het geval waarvoor dit is gebouwd, is dat de grens die haalbaar is: geen open CDN of bucket. Exports (PDF, PNG, HTML) bevatten het font nog steeds, zoals elke PDF z’n fonts bevat.
    • Gebruik je S3? Controleer de bucket-policy. Publieke leestoegang hoort alleen op uploads/* te staan. Blijkt een geüpload font toch publiek leesbaar, dan weigert Deckyard de upload met een melding die dat zegt.

    Export

    • Eén onleesbaar font laat de export niet meer mislukken. Is een font niet te lezen, dan rendert de tekst die het gebruikt in de fallback en gaat de export door.
    • Elke fontrol komt in de export. Een gecureerd font in de mono- of captionrol (bijvoorbeeld JetBrains Mono via typography.mono) zit nu ook in de PDF en PNG, niet alleen de heading- en bodyfonts.

    Voor wie zelf host

    Eén databasemigratie (088, die font_variants.url schrapt) draait automatisch bij het opstarten. Had je al fonts geüpload, draai daarna één keer node scripts/privatize-font-variants.js --apply om ze naar privéopslag te verplaatsen.

    Draai het eerst met --check om te zien of er iets te verplaatsen valt. Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.47.0-release op GitHub.

  73. v1.46.0

    Feature-release

    Thema's worden één soort record dat met een deck meereist, SSO-logins landen in de juiste organisatie, de presentatorconsole past op kleinere schermen en de follow-invite-slide krijgt één QR-plaat.

    De vormgeving van een deck gaat nu overal mee naartoe waar het deck heen gaat. Deze release stuurt single sign-on-logins ook naar de juiste organisatie, houdt de presentatorconsole op kleinere schermen volledig in beeld en vereenvoudigt de follow-invite-slide.

    Thema’s

    • Een thema is één soort record. Ingebouwde en eigen thema’s worden op dezelfde manier opgeslagen en behandeld, en de vormgeving van een deck reist mee bij export en import. Een bundel opent dus zoals hij gemaakt is.

    Organisaties en single sign-on

    • Een OIDC-login landt in de juiste organisatie. Stuurt je identity provider een organisatieclaim mee, dan zet Deckyard de gebruiker daarmee in de bijbehorende werkruimte.
    • Via SSO aangemaakte gebruikers krijgen meteen een lidmaatschap. Een automatisch aangemaakte gebruiker kan in een instance met meerdere organisaties vanaf de eerste login aan de slag, in plaats van zonder werkruimte binnen te komen.

    Presenteren en bewerken

    • De presentatorconsole past op kleinere schermen. Op een smaller scherm loopt de bovenbalk door naar een tweede rij, en blijft het podium met de timer, de volgende slide en je notities volledig in beeld.
    • De follow-invite-slide toont één QR-plaat in plaats van twee kaarten, zodat het publiek één code ziet om te scannen, met de link ernaast.
    • Escape sluit eerst het bovenste open oppervlak in de editor, en niet iets wat eronder ligt.

    Breaking, voor forks

    Deckyard blijft op 1.x zolang het beta-label er staat, dus een minor release met een breaking change is de bedoelde vorm en geen vergissing. Deze raakt alleen forks die de slidetypes stylen tegen hun eigen kopie:

    • De follow-invite- en feedbackslides gebruiken nieuwe classnamen. .sfi-card en .sfi-card-title worden .sfi-qr-plate, .sfi-link en .sfi-method-label, en de wrapper .sfi-qr-wrap verdwijnt. De core-thema’s gaan mee; hernoem de regels in je eigen stylesheet.

    Voor wie zelf host

    Drie databasemigraties draaien automatisch bij het opstarten: 085 (thema-seeds), 086 (presentatie-extensies) en 087 (organization_external_id). Er is geen handmatige stap nodig. Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.46.0-release op GitHub.

  74. v1.45.0

    Feature-release

    Bewerken is de hoofdactie op een deckkaart, de editor geeft rustiger feedback, de live-video-overlay bereikt ook het follow-publiek en API v1 behandelt thema's en slidetypes op één consequente manier.

    Een deck openen om het te bewerken is nu de vanzelfsprekende eerste stap op het dashboard. Deze release maakt ook de feedback in de editor eenvoudiger, brengt de live-video-overlay naar wie meekijkt en maakt de API strenger en consequenter over thema’s en slidetypes.

    Dashboard en editor

    • Bewerken is de primaire actie op een deckkaart. De andere acties blijven op de kaart, maar Bewerken springt eruit.
    • Opslagfeedback is eenvoudiger. De editor meldt het opslaan op één plek in plaats van op meerdere, en de miniatuur van de geselecteerde slide houdt zijn breedte.
    • De slidetype-bouwer koppelt zijn vinkjes goed aan hun label. Een klik op een label zoals Verplicht zet het eigen vinkje om en nooit een ander.

    Presenteren en importeren

    • De live-video-overlay bereikt het follow-publiek. Wie een presentatie op een eigen apparaat volgt, ziet de live video nu ook, niet alleen het hoofdscherm.
    • De follow-weergave volgt de analytics-voorkeur van de kijker. De eigen instelling van de kijker bepaalt het meten in de browser; de opt-out van de eigenaar wordt nog steeds op de server afgedwongen.
    • Een geïmporteerde bundel houdt zijn thema. Gebruikt een bundel een thema dat niet is geïnstalleerd, dan houdt het deck dat thema als standaard in plaats van terug te vallen op een ander.

    Voor API- en MCP-clients

    • Eén vorm voor een thema op v1. Een deck noemt een bibliotheek-theme, en default is een eigen waarde.
    • Slidetypeschema’s lossen op tegen canonieke en organisatietypes. Een eigen slidetype van een organisatie valideert op v1 nu net zo als een ingebouwd type.
    • Elk aanmaakpad controleert het thema zoals v1 dat doet, en weigert een contentByLang die geen object-map is.

    Geen databasemigraties. Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.45.0-release op GitHub.

  75. v1.44.0

    Feature-release

    Videotranscripten en matrixasnamen komen in de reader terecht, decktalen werken consequenter en gepubliceerde decks krijgen verbeteringen voor toegankelijkheid en privacy.

    Videotranscripten en matrixasnamen komen nu mee naar de reader. Deze release maakt ook de talen van een deck consequenter en verbetert toegankelijkheid en privacy op gepubliceerde decks.

    Readers en gepubliceerde decks

    • Videoslides nemen hun transcript mee naar de reader. Matrix-slides benoemen hun assen, en de reader toont die namen boven het raster.
    • De taalkeuze past bij het deck. De presenter en follow-weergave bieden alleen de talen van het deck zelf aan, en de reader spreekt in de decktaal.
    • Ontbrekende beeldbeschrijvingen vallen beter op. Een gepubliceerd deck blijft waarschuwen zolang een afbeelding zonder alt-tekst live staat; afbeeldingen in eigen markup vallen onder dezelfde alt-controle. Tabelkoppen in het canvas geven voor hulptechnologie aan welke kolom of rij ze beschrijven.
    • Publieke pagina’s beschermen de identiteit van de eigenaar. Ze leiden geen eigenaarsnaam meer af uit een e-mailadres, en de JSON-LD van een gepubliceerd deck noemt geen auteur meer.

    Editor en API

    • De interface is consistenter. Iconen komen uit de Lucide-set, Escape sluit steeds één open laag en de avatars van samenwerkers passen in de bovenbalk. Een geselecteerd tekstveld houdt zijn ring als de focus naar de zijbalk gaat. Logowanden schalen mee met het aantal logo’s en tijdlijnkaarten met het slide-canvas.
    • API v1 meldt echte waarden voor createdAt en updatedAt. Een wissel van slidetype converteert de slide of wordt geweigerd; MCP wijst de agent dan de juiste route. Fouten bij ongeldige slides sturen details als object.
    • Taalversiesleutels moeten canoniek zijn. Schrijven van decks en bibliotheekslides weigert aliassen zoals en wanneer en-GB de canonieke sleutel is.

    Voor self-hosters en forks: databasemigraties 083_canonical_version_keys.js en 084_library_canonical_version_keys.js zetten opgeslagen aliassleutels om naar canonieke taalsleutels. Een deck met zowel een alias als de canonieke sleutel blijft staan en wordt gelogd; een beheerder moet dat oplossen voordat het deck weer kan worden opgeslagen.

    Het aantal ingebouwde slidetypes blijft gelijk.

    Zie voor de volledige lijst op commitniveau de 1.44.0-release op GitHub.

  76. v1.43.0

    Feature-release

    Klik op een afbeelding voor Replace en Settings; logowanden schalen mee met de slide en de taalknop in de presenter blijft op één rij.

    Afbeeldingen zijn makkelijker te bewerken. Klik erop voor een selectiering en een werkbalk met Replace en Settings. Dubbelklikken vervangt nog steeds de afbeelding, en een bestand op een gevulde afbeelding slepen vervangt haar nu ook. De oude labels “Double-click to replace” liggen niet meer over logo’s.

    Logowanden tonen grotere logo’s en schalen mee met de slide in plaats van met het browservenster. In de presenter blijft de taalknop op één rij, ook bij een smalle bovenbalk.

    Geen databasemigraties of wijzigingen in het aantal ingebouwde slidetypes.

    Zie voor de volledige lijst op commitniveau de 1.43.0-release op GitHub.

  77. v1.42.0

    Feature-release

    De editor maakt essentiële slidevelden duidelijker, en de publieke API vraagt nu theme en lang in plaats van themeId en language.

    De editor laat nu zien welke velden een slide nodig heeft om er compleet uit te zien, zonder knoppen over de inhoud te leggen. API-clients moeten hun deckverzoeken controleren: themeId en language geven nu een 400-fout; gebruik theme en lang.

    Duidelijker bewerken

    • Knoppen om velden toe te voegen liggen niet meer over je tekst. De knop staat op de naad waar het veld zou komen; als daar geen ruimte is, verschijnt een kleine + in de marge.
    • Essentiële velden vragen om inhoud. Een lege titel op een titelslide, een beeld op een beeldslide of de eerste kaart in een kaartenlijst is zonder hover zichtbaar. Optionele velden verschijnen bij hover. Deze aanwijzingen staan alleen in de editor, niet in presentaties, exports of print.
    • Eigen slidetypes kunnen een veld als Essential markeren in Settings → Slide Types. Required blokkeert publiceren zonder waarde; Essential geeft aan dat de slide zonder dat veld onaf oogt. Agents ontvangen essential naast required via MCP get_slide_types en GET /api/v1/slide-types/:type/schema.

    Fixes en API-clients

    • De publieke API gebruikt overal theme en lang. Verzoeken met themeId of language krijgen nu een 400-antwoord dat de juiste veldnaam noemt. Antwoorden melden het werkelijke thema en de werkelijke taal, en een PUT met theme wisselt het thema.
    • Een lege presentatie zonder titel toont de fout bij het titelveld in plaats van stil te weigeren.
    • Sprongknoppen blijven na import naar de juiste slide wijzen, ook als die slide een nieuw ID krijgt.

    Geen databasemigraties of wijzigingen in het aantal ingebouwde slidetypes.

    Zie voor de volledige lijst op commitniveau de 1.42.0-release op GitHub.

  78. v1.41.1

    Onderhoudsrelease

    Copy to clipboard in de slidebibliotheek zet de slide nu op het klembord van de editor, klaar om in een deck te plakken.

    Copy to clipboard in de slidebibliotheek werkt nu. Kies Use → Copy to clipboard, selecteer een slide in een deck en druk op Ctrl/Cmd+V om de bibliotheekslide daar te plakken. Dit kopieert een slide binnen Deckyard; plakken in een andere app wordt nog niet ondersteund.

    Geen databasemigraties of wijzigingen in het aantal ingebouwde slidetypes.

    Zie voor de volledige lijst op commitniveau de 1.41.1-release op GitHub.

  79. v1.41.0

    Feature-release

    Image blocks kunnen een persoon voorstellen met naam, functie en een korte bio; de countdown-knoppen verdwijnen in fullscreen mét de presenter-balken; Duplicate kopieert een slide met zijn subslides.

    De belangrijkste toevoeging is een personenkaart: Image blocks krijgen een korte beschrijving, zodat één blok een foto, naam, functie en bio kan tonen. Bij het updaten hoef je niets te doen.

    Personenkaarten op Image blocks

    • Elk blok heeft een optioneel veld Beschrijving (markdown) onder het onderschrift. Zodra een blok een beschrijving heeft, wordt de foto kleiner en de kaart breder zodat de tekst past. Zie Image Blocks.
    • Een blok zonder foto toont alleen zijn tekst in de presentatie en de export; de lege fotoplek is alleen nog in de editor zichtbaar.
    • Een witregel is een witregel, in de beschrijving en in de tekst van Text blocks.

    Fixes

    • In fullscreen verdwijnen de countdown-knoppen samen met de presenter-balken en komen terug bij een muisbeweging of Tab. De knoppen zijn ook groter.
    • Duplicate in het slidemenu kopieert de slide met zijn subslides, zoals het contextmenu en Cmd+D al deden.
    • Importfouten staan bij het formulier. Een JSON-, Markdown- of plakimport die geweigerd wordt (leeg bestand, parsefout, geen bestand gekozen) meldt dat naast het veld in plaats van in een toast.
    • Voor forks en eigen thema’s: het themarecord draagt nu elk veld van core- en forkthema’s zonder verlies (merk-, grafiek- en achtergrondkleuren, alternatief logo en payoff-logo), en een thema met een onbekend veld wordt bij naam geweigerd.

    Geen databasemigraties tussen 1.40.0 en 1.41.0. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.41.0-release op GitHub.

  80. v1.40.0

    Beveiligingsrelease

    Een securityfix voor deck-tags, je eigen SSO-label en logo op de inlogkaart, en elke mail, ook de weekdigests, in de taal van de ontvanger.

    Deze release dicht een gat in hoe deck-tags worden gecontroleerd, laat de inlogkaart het eigen SSO-label en logo van je installatie dragen en stuurt elke mail in de taal die de ontvanger koos. Update als er meer dan één persoon inlogt op je installatie.

    Security

    • Deck-tags zijn alleen te lezen en te wijzigen door wie het deck mag bewerken. Tot deze versie controleerden de tag-routes van een deck de rechten op het deck zelf niet.

    Je eigen inlogkaart

    • De SSO-knop zegt wat jij wilt. Zet SSO_BUTTON_LABEL, bijvoorbeeld Inloggen met Acme ID, en de knop en het uitnodigingsverslag dat nieuwe leden ernaar verwijst gebruiken die woorden. Zie Authentication.
    • Je logo op elke inlogkaart. APP_LOGO_URL zet je logo boven de inlogkaart en in plaats van het Deckyard-logo in de bovenbalk van het overzicht. Zie Environment.
    • Beide zijn optioneel; niet ingesteld ziet de inlogkaart eruit als voorheen.

    Mail in de taal van de ontvanger

    • Elke mail volgt nu de taal die de ontvanger in Voorkeuren koos: uitnodigingen, gastmails, commentnotificaties en de weekdigests. Wie nooit een taal koos, zoals een gast zonder account, krijgt de standaardmailtaal van de installatie.
    • De digest-instelling in Voorkeuren wordt gerespecteerd. Wie de digest uitzette, krijgt hem niet meer, en de weekdag in de digest klopt in elke tijdzone.

    Fixes

    • Foutmeldingen in gewone woorden in plaats van een upstream-fout. Als ImageKit, Notion, Giphy, Unsplash of een datasource-provider hapert, zie je nu één zin over wat er misging, niet het ruwe antwoord van de dienst.
    • Een custom slidetype dat nog in gebruik is, laat zich niet verwijderen, en de melding zegt in hoeveel decks het zit.
    • De themategel op Home toont de eigen achtergrond van het thema.
    • Op een installatie zonder mail zegt de melding na een uitnodiging hoe de genodigde binnenkomt, en blijft staan tot je hem sluit.
    • Een revisieconflict noemt wie het laatst opsloeg. Handig voor API- en MCP-clients die een 409 krijgen.
    • De prullenbak-hint noemt de echte bewaartermijn van de server.
    • Op de publieke sandbox delen gasten niet meer met elkaar en de interface zegt waarom; de sandboxbanner noemt de echte bewaartermijn.

    Geen databasemigraties tussen 1.39.0 en 1.40.0; een gewone upgrade volstaat. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.40.0-release op GitHub.

  81. v1.39.0

    Feature-release

    Beelden uit de ImageKit-kiezer weghouden met een tag, zonder ze te verwijderen, en geen AI-actie meer in de taalwisselaar als AI uit staat.

    Een kleine release met één nieuwe instelling voor beheerders die een ImageKit-archief koppelen. Bij het updaten hoef je niets te doen.

    ImageKit

    • Beelden verbergen in de kiezer met een tag. Zet IMAGEKIT_HIDDEN_TAGS op een of meer tags, gescheiden door komma’s, en bestanden met zo’n tag verschijnen niet meer in de ImageKit-kiezer, de zoekresultaten of de tagsuggesties. Slides die zo’n beeld al gebruiken blijven werken. Handig voor een archief dat dubbele of ongesorteerde beelden markeert in plaats van ze te verwijderen. Niet ingesteld, dan verandert er niets. Zie Media Services.

    Fixes

    • Met AI uitgeschakeld heeft ook de taalwisselaar geen AI-actie meer. Hij volgt de andere AI-knoppen die 1.38.2 al weghaalde.

    Geen databasemigraties tussen 1.38.2 en 1.39.0. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.39.0-release op GitHub.

  82. v1.38.2

    Onderhoudsrelease

    Een tabel uitbreiden werkt zoals je verwacht, het canvas en de mail spreken jouw taal, AI-knoppen verdwijnen als AI uit staat, en het venster sluiten tijdens een AI-conversie of Notion-import stopt het werk.

    Een patch met alleen fixes; bij het updaten hoef je niets te doen. De fix die als gebruikersmelding binnenkwam: een rij toevoegen aan een tabel zette de knop op de verkeerde plek.

    Bewerken

    • Een tabel uitbreiden werkt zoals je verwacht. De + voor een nieuwe rij stond op de onderrand van de slide in plaats van onder de laatste rij, en heette “Add item”. Hij staat nu onder de tabel, en kolommen groeien mee op het canvas.
    • Het canvas spreekt de taal van de editor. De spookvelden (”+ Caption”) en de wisknoppen stonden in het Engels op een Nederlands canvas; ze gebruiken nu de vertaalde veldnaam.
    • Met AI uitgeschakeld zijn er geen AI-knoppen meer. Convert in het slidemenu, “Fill slide…” en de AI-knoppen per veld verdwijnen, in plaats van uit te komen op een fout.
    • Aftel-, video-, KPI- en teamkaart-slides met server-gerenderde markup werken nu ook in de editor.

    Mail in de taal van de ontvanger

    • Inlog-, wachtwoordreset- en export-klaar-mail gaan in de taal van de ontvanger. Een Nederlands account kreeg een Engelse resetmail, en de exportmail had helemaal geen Nederlandse tekst (en een Engelse zin die “1 presentation have been exported” zei).
    • Voor beheerders: de instellingen voor e-mailsjablonen tonen alleen nog een taaltab voor talen die de server echt heeft, Engels en Nederlands, in plaats van negen tabs waarvan er zeven stil op Engels terugvielen.

    Weglopen stopt het werk

    • Sluit je het venster tijdens een AI-conversie of Notion-import, dan stopt de server. Tot deze versie ging hij door en maakte hij een presentatie aan die niemand zou zien, en verbruikte hij daar AI-tegoed voor.

    Bibliotheken en zoeken

    • Zoeken op tags vindt wat je typt. Een getypte % of _ is een teken, geen wildcard, en namen als İstanbul worden gevonden.
    • Opslaan in de bibliotheek gebeurt helemaal of niet. Een mislukte collectie-update laat geen halve hernoeming achter, en twee mensen die tegelijk dezelfde nieuwe tag aanmaken krijgen geen serverfout meer.
    • De bulk-export neemt je favorieten mee in de beeldbibliotheek.
    • De voorbeeldslide met de piramide heeft een Nederlandse titel.

    Export

    • De PPTX-exportoptie zegt wat hij doet: elke slide behalve video wordt één afbeelding, geen bewerkbare PowerPoint-slide.

    Geen databasemigraties tussen 1.38.1 en 1.38.2. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.38.2-release op GitHub.

  83. v1.38.1

    Onderhoudsrelease

    De presentatorweergave spreekt de taal van de sessie en de Q&A-knoppen volgen de server, kopieën in de bibliotheek houden hun vertalingen en tags, en een opslag die halverwege misgaat laat niets half gewijzigd achter.

    Een patch met alleen fixes. Eén daarvan verandert wie wat ziet: een editor op een deck die geen workspace-beheerder is, ziet nu de promote-knoppen bij Q&A. Bij het updaten hoef je niets te doen.

    Presenteren

    • De presentatorweergave spreekt de taal van de sessie. De status open of gesloten van een poll of Likert-vraag op het podium stond altijd in het Nederlands, en vier veldlabels in de Engelse interface waren half Nederlands.
    • De Q&A-knoppen in de notitieweergave volgen de regel van de server. Add next slide en Add to end verschijnen nu voor iedereen die het deck mag bewerken, de eigenaar en collaborators met editorrecht; tot deze versie zagen alleen workspace-beheerders ze, terwijl de server meer toestond. Remove blijft voor workspace-beheerders. Zie Q&A.

    Bibliotheken

    • Een gekopieerd bibliotheekitem neemt het hele item mee, inclusief vertalingen en tags, die een kopie eerst kwijtraakte.
    • De bibliotheek toont de juiste datums en formaten van haar items.
    • De tags van een item of de inhoud van een collectie vervangen gebeurt in één stap. Gaat het halverwege mis, dan blijft er niets half gewijzigd achter.
    • Een te lange tagnaam geeft een duidelijke foutmelding in plaats van een serverfout.

    Nederlandse kopij

    • Eén spelling per woord in de Nederlandse interface. Zes samenstellingen in de kopij van de slidetypes stonden los geschreven, en de ster in de beeldbibliotheek had twee namen.

    Geen databasemigraties tussen 1.38.0 en 1.38.1. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.38.1-release op GitHub.

  84. v1.38.0

    Feature-release

    Het deelvenster krijgt tabs per publiek, met de embedcode naast de publieke link; de Node-installatie noemt en handhaaft haar PostgreSQL-eis; en een ronde fixes voor AI, export, de editor en de API.

    Een deck delen begint nu bij met wie je het deelt, en wie Deckyard zonder Docker installeert, hoort vooraf wat er nodig is in plaats van achteraf te zien dat het misgaat. De rest zijn fixes. Update als je op Node installeert zonder Docker, of AI uitzet met AI_ENABLED=false.

    Delen per publiek

    • Het deelvenster heeft drie tabs: Team, Gasten en Openbaar. Elke tab is de plek voor dat publiek, dus je hoeft niet meer te weten welk venster welke link heeft.
    • De embedcode staat naast de publieke link. De tab Openbaar toont de paginalink en de embedspeler van een gepubliceerd deck als twee gelijke rijen, met de iframe- en SDK-snippets eronder en één taalkeuze voor allemaal. Eerst zat hij weggestopt achter de publieke link.

    Installeren op Node: PostgreSQL wordt genoemd en gehandhaafd

    • Deckyard weigert te starten zonder bereikbare, gemigreerde PostgreSQL, en zegt welke verbinding hij probeerde en wat je moet doen. Tot deze versie eindigde een ontbrekende database in een onleesbare fout, en een database zonder schema was erger: de server startte, opende de browser en beantwoordde elk verzoek met een fout.
    • npm run db:migrate hoort bij installeren. De installer op één regel draait het voordat hij iets start, en noemt de PostgreSQL-eis voordat hij minutenlang npm install draait. Het Docker-pad brengt een eigen database mee en is niet veranderd. Zie de quickstart.

    Fixes

    • AI_ENABLED=false haalt nu elke AI-ingang weg, niet de meeste.
    • Een AI-analyse annuleren stopt hem op de server. Tot deze versie stopte alleen de browser met wachten; de analyse liep door en kon nog suggesties als opmerkingen toevoegen.
    • De videoplaceholder in een PPTX-export spreekt de taal van het deck. Hij was altijd Nederlands, ook in een Engels deck.
    • De bovenbalk van de editor past op elke breedte. Hij liep over onder ongeveer 870 pixels en net boven elk breekpunt; hij houdt het nu tot 341 pixels.
    • Een onmogelijk id in de API of via MCP geeft 404, geen 500. Een presentatie-, collaborator-, versie- of opmerking-id dat niet kan bestaan, komt nu terug als “niet gevonden”.
    • Sandbox-instances: een gast is een echte gebruiker en is eigenaar van de decks die hij maakt, de opruiming bij de eerste bezoeker lekt geen gastsessies meer, en de voorbeelddecks zijn herschreven. Alleen van belang als je een sandbox draait.

    Geen databasemigraties tussen 1.37.0 en 1.38.0. Draai op het Node-pad na elke update npm run db:migrate, zoals altijd: vergeet je het, dan weigert de server nu te starten. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.38.0-release op GitHub.

  85. v1.37.0

    Feature-release

    Bewerk een slide in de slidebibliotheek met het volledige slideformulier in plaats van alleen de naam; favorieten in de bibliotheek worden onthouden, per gebruiker; en een beveiligingsfix voor tags in de bibliotheek.

    Een slide in de slidebibliotheek bewerken betekende tot nu toe de naam en beschrijving aanpassen, of hem in een wegwerpdeck zetten om de rest te wijzigen. Nu opent Edit het volledige slideformulier. Deze release repareert ook de favorieten in de bibliotheek en dicht een gat in de controle op tags. Update als er meer dan één persoon op je installatie inlogt.

    Een bibliotheekslide bewerken met het volledige formulier

    • Edit opent hetzelfde formulier als in een deck, voor het type van die slide: geneste kaarten en leden, beelden via de gewone kiezer, achtergrond, de Layout-chip en de toegankelijkheidsvelden, met Undo en Redo. Opslaan schrijft terug naar hetzelfde bibliotheekitem; een tijdelijk deck is niet meer nodig.
    • Mag je een gedeeld teamitem niet wijzigen, omdat je niet de maker of een beheerder bent, dan blijft Edit grijs met de reden erbij, en maakt Duplicate to my library een persoonlijke kopie en opent de editor daarop.
    • Slaan twee mensen hetzelfde item tegelijk op, dan krijgt de tweede een conflict naast Save in plaats van de eerste te overschrijven, en sluit je de editor met niet-opgeslagen wijzigingen, dan vraagt hij het eerst.

    Favorieten worden onthouden

    • De ster in de slidebibliotheek blijft nu staan. Tot deze versie leek hij aan te staan en was hij na herladen weg. Favorieten zijn per gebruiker: de jouwe zijn van jou, een collega heeft eigen sterren.

    Beveiliging: tags volgen de rechten van het item

    • Tot deze versie kon een ingelogde gebruiker de tags wijzigen van een bibliotheekitem van iemand anders. Dat is dicht. Tags volgen nu dezelfde regel als de rest van het item: alleen wie het item mag wijzigen, kan de tags wijzigen, en het persoonlijke item van een ander is via de API helemaal niet bereikbaar.
    • Tags zijn alleen-lezen in het voorbeeld van de bibliotheek als je het item niet mag bewerken, net als de beschrijving.

    Geen databasemigraties tussen 1.36.1 en 1.37.0; een gewone upgrade volstaat. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.37.0-release op GitHub.

  86. v1.36.1

    Beveiligingsrelease

    Een beveiligingsfix voor de slidebibliotheek: een persoonlijk item kan alleen door de eigenaar worden gewijzigd of verwijderd, en een gedeeld teamitem door de maker of een beheerder.

    Een patch met één wijziging, en dat is een beveiligingsfix. Update als er meer dan één persoon op je installatie inlogt. Zit je nog op 1.35.0 of eerder, lees dan eerst de notities bij 1.36.0: de prullenbak-opruiming die daarin zit, draait bij de eerste start.

    Rechten in de slidebibliotheek worden op de server gecontroleerd

    • Tot deze versie kon een ingelogde gebruiker via de API het persoonlijke bibliotheekitem van een collega wijzigen of verwijderen. Dat is dicht. Elke wijziging aan een bibliotheekitem loopt nu door één controle op de server: je kunt alleen je eigen persoonlijke items wijzigen of verwijderen, en een gedeeld teamitem alleen als je de maker of een beheerder bent.
    • Twee gelijktijdige bewerkingen overschrijven elkaar niet meer stil. De tweede opslag krijgt een conflict in plaats van de eerste te vervangen.
    • Wijzig je de inhoud van een item, dan blijven de andere taalversies bij, in plaats van op de oude inhoud te blijven staan.
    • Een custom-HTML-slide in de bibliotheek opslaan volgt de regel van de editor: alleen wie custom HTML mag maken, kan er daar een aanmaken of wijzigen.

    Voor koppelingen

    • Naam, beschrijving of inhoud van een bibliotheekitem wijzigen via de API vraagt om de revisie. Elk item heeft nu een revision; stuur die mee in If-Match. Zonder antwoordt de server met 428, met een verouderde met 409. Een update met een veld dat de bibliotheek niet kent, wordt geweigerd met 400. De app zelf doet dit al.

    Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.36.1-release op GitHub.

  87. v1.36.0

    Feature-release

    De prullenbak verwijdert nu wat hij zegt te verwijderen, na een bewaartermijn die je zelf instelt; een beeld uit ImageKit wordt eerst eigen media voordat het op een slide komt; en beeldblokken, tekstblokken en de editor volgen de leesvolgorde.

    De prullenbak zegt altijd al dat weggegooide presentaties na 30 dagen worden verwijderd, en tot deze release verwijderde niets ze. Nu wel. Dat is de wijziging die je leest voordat je update; de rest is een ImageKit-kiezer die decks niet langer aan een extern CDN vastknoopt, en een ronde fixes in lay-out en editor.

    Kijk in je prullenbak voordat je update. Vanaf deze versie verwijdert een dagelijkse opruiming elke presentatie die langer dan TRASH_RETENTION_DAYS (standaard 30 dagen) in de prullenbak staat definitief, inclusief thumbnails. De opruiming draait ook meteen bij het opstarten van de server, dus de eerste start na de upgrade ruimt de hele achterstand in één keer op: alles wat op jouw installatie al langer dan de termijn in de prullenbak staat, is binnen enkele minuten na het opstarten weg. Wil je die achterstand bewaren, herstel dan eerst wat je nodig hebt, of zet TRASH_RETENTION_DAYS hoger voordat je deployt. Er is geen waarde die de opruiming uitzet; 0, een negatief getal of alles wat geen getal is, valt terug op 30.

    De prullenbak houdt zich aan zijn belofte

    • Weggegooide presentaties worden na de bewaartermijn verwijderd. De opruiming is dezelfde verwijdering als Delete permanently, presentatie voor presentatie, inclusief thumbnails. Hij draait eens per dag, dus een presentatie kan tot een dag na de termijn nog bestaan.
    • Herstellen zet de klok stil. Een presentatie die je voor het einde van de termijn herstelt, blijft; gooi je hem opnieuw weg, dan begint een nieuwe termijn.
    • De prullenbak noemt de ingestelde termijn, in elke taal. Een installatie met TRASH_RETENTION_DAYS=7 zegt 7 dagen. Zie Trash & Recovery en de instellingen voor dataretentie (Engelstalig).
    • Definitief verwijderen kan alleen voor een presentatie in de prullenbak. De app weigert een presentatie definitief te verwijderen die niet eerst is weggegooid, en een verzoek om een presentatie te herstellen die niet in de prullenbak staat geeft nu 409 not_trashed in plaats van 400.

    Een keuze uit ImageKit wordt eigen media

    • Kies je een beeld uit ImageKit, dan wordt het eerst gekopieerd naar de eigen media van je installatie, en de slide verwijst naar die kopie. Een deck breekt niet meer als het bestand in ImageKit wordt verplaatst, hernoemd of verwijderd. Mislukt het kopiëren, dan blijft de kiezer open met de reden naast “Use this image” en blijft de slide zoals hij was. Decks die al ImageKit-URL’s bevatten worden niet aangepast.
    • Het kopiëren is een upload, dus het heeft uploads nodig. Op een installatie met DISABLE_UPLOADS=1, of in demo- of sandboxmodus, meldt de kiezer dat in plaats van het beeld te plaatsen.

    Lay-out en bewerken

    • Beeldblokken gebruiken de ruimte die ze hebben. Op een beeldblokkenslide die elke afbeelding in zijn oorspronkelijke verhouding laat, krijgen de beelden de maat van de ruimte onder de kop: vier liggende foto’s passen weer op één rij, een tweede rij duwt de inhoud niet meer over de kop, en de titels onder de beelden staan op één lijn.
    • Een collectie onder een kop centreert in de ruimte eronder. Tekstblokken met een paar rijen laten geen lege strook meer onderaan de slide, en een tabel centreert onder zijn bijschrift; inhoud die te lang is, begint nog steeds onder de kop. De kop van tekstblokken staat standaard gecentreerd, links uitlijnen zit nog in de Layout-chip.
    • Opmaak is zichtbaar terwijl je typt. De opmaakbalk verschijnt bij de cursor zodra je een tekstveld met opmaak bewerkt, ook een leeg veld, zodat je vet of cursief kunt aanzetten voordat je typt. Een link vraagt nog steeds om geselecteerde tekst.
    • De velden van tekstblokken staan in leesvolgorde: rijkop en kleur, de blokken, dan de pijl naar de volgende rij, met de subkop onderaan na alle rijen. De eerste rij krijgt ook een chip voor zijn kop.

    Kleinere wijzigingen

    • Importeer je een bestand dat geen .deck-bundle is, dan krijg je een gewone reden (“the file is not a zip archive”) in plaats van een foutmelding uit een bibliotheek, en een bundle met een kapotte manifest.json of deck.json noemt het kapotte bestand.
    • Bibliotheektegels in de slidekiezer houden hun eigen inhoud als je de weergave of de achtergrond van het voorbeeld verandert.

    Geen beveiligingsfixes in deze release; 1.36.1, dezelfde dag uitgebracht, is er wel een, dus update meteen daarheen. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.36.0-release op GitHub.

  88. v1.35.0

    Feature-release

    Een .deck-bestand draagt het hele deck, inclusief elke taal, het thema en eigen slidetypes; de leesexport leest als een document met echte lijsten, citaten, kaders en figuren; en een genummerde lijst die je in de editor typt toont niet langer 1, 1, 1.

    Eén dag na 1.34.0 landen twee sporen tegelijk: de tweede helft van het portabele deck, en de leesprojectie die van een deck een document maakt. Eén breaking change, in de vorm van de deck-export, en één fix die op zichzelf al een update waard is.

    Controleer je koppelingen voordat je update. De JSON-export en de .deck-bundle dragen nu elke taal van een deck, dus ?lang= op de JSON-export kiest er geen meer; content is de dominante taal. /api/v1/schema/deck.json beschrijft die export in plaats van het opgeslagen model: format, version en title zijn verplicht, id, schemaVersion, created, modified, settings en description zijn weg, en slides dragen geen id. Een import weigert een deck met een taal, of een vertaaltag, die de installatie niet kent, of waarvan lang het request tegenspreekt, in plaats van het stil te repareren. Twee kleinere reparaties die stil gebeurden zijn ook gestopt: een actieknop met een kale domeinnaam (example.com) of een tel:-link, en een LinkedIn-link zonder https://, worden niet meer getoond; de editor geeft een hint naast het veld zodat je de waarde kunt herstellen. Deckyard is in beta, dus dit komt in een minor-versie.

    Genummerde lijsten nummeren goed

    • Een genummerde lijst die je in de editor typt is één lijst. 1. Eerste, Enter, 2. Tweede typen liet losse alinea’s staan tot je het veld verliet, en een opgeslagen lijst met lege regels tussen de items werd getoond als drie lijsten die elk “1.” zeiden. Enter aan het eind van een regel die met 1. of - begint maakt er nu direct een lijstitem van en opent het volgende, lege regels tussen items splitsen een lijst niet meer, en een lijst die bij 3 begint toont 3. Decks die al in de gesplitste vorm zijn opgeslagen worden zonder aanpassing goed getoond.

    Een .deck-bestand draagt het hele deck

    • Exporteer en importeer een .deck vanuit de app. Het exportmenu heeft onder Data & bundle een .deck-rij, en het nieuw-presentatie-dialoog heeft een tab Import .deck, de standaard. Als iets niet meekwam blijft het dialoog open met de reden en een knop Open presentation; een kapotte bundle geeft een foutmelding bij het bestand.
    • Elke taal, de notities, de timing en de zichtbaarheid reizen mee. De JSON- en .deck-export dragen alle taalversies plus sprekersnotities, duur en zichtbaarheid per slide; een import zet de vertalingen terug als taalversies.
    • Het thema en de eigen slidetypes van het deck reizen ook mee. Een deck op een organisatiethema draagt dat thema: theme.json, de logo’s en de gecureerde Google-fonts als bestanden (Adobe-, Monotype- en geüploade fonts alleen op naam, met de reden erbij). Slidetypes uit Settings > Slide Types die het deck gebruikt gaan mee. Wie thema’s en slidetypes mag beheren ziet één vinkje om ze te installeren, standaard uit; een bestaand thema of type wordt nooit overschreven, een bezette slug krijgt -2. Zonder installeren landt het deck op het standaardthema en importeren die slides als placeholder die zegt dat de definitie in de bundle zit. Exporteren, importeren, exporteren levert byte voor byte dezelfde bundle.
    • Een slide op een eigen database-slidetype komt via JSON weer als zichzelf terug, en zijn vertalingen reizen mee in de JSON- en .deck-export.

    De leesweergave leest als een document

    De leesweergave (/p/…/reader) en de reflowable HTML-export volgen nu de structuur die elk slidetype vastlegt, in plaats van te raden op veldnamen.

    • Lijsten, citaten, kaders en voetregels zijn wat ze zeggen. Een genummerde list-slide is een genummerde lijst met zichtbare nummers; poll- en likert-opties zijn regels, geen tussenkoppen; een citaat is een <blockquote> met naam en functie in een <footer>; notities, tips en waarschuwingen zijn een <aside> met het soortwoord in de taal van het deck; een byline of logonaam is een <figcaption> onder het beeld; de eerste kolom van een tabel is een rijkop voor schermlezers.
    • Copy leest in de taal van het deck. Een callout zonder label wordt naar zijn soort genoemd (“Kernpunt”, “Let op”), ook in de inhoudsopgave, en de datatabel van een chart krijgt een samenvatting in de deck-taal (“Lijndiagram met 5 punten. Min: 25. Max: 85.”), die schermlezers ook op de slide zelf krijgen.
    • Waarden lezen als waarden. Een KPI leest “98%”, een countdown-duur is een <time> (1:30), een likert-slider noemt zijn schaal (1 “Nutteloos” tot 10 “Essentieel”), een actie- of kaartlink springt naar zijn dia (“Dia 3”), een social link is een echte link met het label als tekst, en het e-mailadres van de eindslide is een mailto:.
    • Een custom-HTML-slide leest als zijn inhoud, niet als codeblok met HTML en CSS. De eerste kop in de markup wordt de naam in de inhoudsopgave; inline styles en het CSS-veld blijven op de canvas en vallen in de leesweergave weg.
    • Beelden lezen echt of niet. Een beeld krijgt alleen een echte alt-tekst, expliciet of de naam van een logo of portret, nooit een bijschrift of bestandsnaam; een beeldset of galerij is één figuurgroep met één onderschrift; een decoratieve set verbergt al zijn beelden.
    • Publiceren weigert een betekenisvol beeld zonder alt-tekst, inline naast Publiceren, met slide en veld erbij (API v1: 422 missing_alt met details). Dat was een “toch publiceren”-bevestiging voor twee slidetypes.
    • De geprinte hand-out is de leesprojectie: dezelfde inhoud en structuur, inclusief figuren, kaders en lijsten, in de taal van het deck. De print-wrapper heet nu reader-slide; de oude print-slide en de print-klassen per type zijn weg, dus eigen print-CSS die daarop leunt moet mee.

    Kleinere veranderingen

    • Een beeld kiezen op een installatie met meer dan één bron (bibliotheek, gradiënten, ImageKit) toont per bron een kaart met omschrijving; ImageKit is de primaire keuze, en het achtergrondveld zegt waar het beeld voor is.
    • Elke HTML-uitvoer (presenter, export, embed, print, leesweergave) markeert de slide-wrapper met data-slide-type, de leesweergave markeert elk blok met data-field, en de variant van een callout, lijst of vergelijking en de toon van een matrixcel staan als attribuut, voor wie de HTML met CSS of een script leest.
    • deckyard-mcp --help noemt elke tool en prompt die de server registreert, ook die van een fork, zodat de lijst nooit achterloopt op de code.

    Voor forks en slidetype-auteurs

    • Nieuwe optionele declaraties: markup: true op een code-veld, nameKey op een beeldveld, unitKey, hrefKey, headingKey, duration: { secondsKey }, scale, de veldtypes url en email, orderedWhen, rowHeader: 'first', role: 'aside' met kindKey, role: 'attribution', termWhen, defaultFromOption met copyKey, een datasetSummary-functie en semantic: true op een enum. Zie docs/developer/slide-types.md en docs/reference/reflowable-html-export.md in de core.
    • De .deck-bundle is bundleVersion 3 (docs/reference/deck-bundle.md); een bundle met een onbekende versie wordt geweigerd in plaats van half gelezen. Een importantwoord zegt bundledTheme en bundledSlideTypes als iets meekwam maar niet is geïnstalleerd.

    Geen beveiligingsfixes in deze release. Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.35.0-release op GitHub.

  89. v1.34.0

    Feature-release

    Eigen slidetypes zijn nu te zien via deellinks, bij meekijken en in de voorbeelden van slidetypes, exports zetten beeldrijen en emoji neer zoals de editor, en de leesexport geeft elke slide een echte kop.

    Een release met één nieuw gedrag voor de leesexport en een reeks fixes voor slidetypes die je eigen installatie toevoegt. Je hoeft niets te doen behalve updaten.

    Eigen slidetypes zijn overal te zien

    Een slidetype dat je installatie zelf toevoegt, of een type uit de slidetype-bouwer, wordt door de server getekend. Op een paar plekken werd die tekening nooit opgevraagd en stond er een lege placeholder.

    • Deellinks, meekijken en de sprekersnotities-weergave tonen die slides nu ook aan kijkers die niet zijn ingelogd. Bij een link met wachtwoord verschijnen ze zodra het wachtwoord is ingevoerd.
    • De instellingen voor slidetypes en de kiezer bij Slide invoegen tonen er een miniatuur van, waar eerst een lege tegel stond.

    Exports kloppen met de editor

    • Beeldblokken met afbeeldingen in hun oorspronkelijke verhouding blijven op één rij in PNG-, PPTX-, PDF- en printexports. Tot nu toe konden vier liggende afbeeldingen over twee rijen vallen en de titel bedekken.
    • Emoji verschijnen in kleur in exports vanuit de Docker-image, in plaats van als lege vakjes.

    Elke slide in de leesexport heeft een kop

    • De zichtbare kop van een sectie is het titelveld van de slide, per slidetype vastgelegd. Een quoteslide maakt van het citaat geen kop meer, en een beeldslide gebruikt de titel, niet het bijschrift.
    • Een slide zonder titel krijgt toch een kop voor schermlezers, vernoemd naar de slide, zodat de structuur van het document compleet blijft. Alleen zichtbare koppen krijgen een nummer.
    • Eigen slidetypes krijgen een zichtbare kop zodra ze vastleggen welk veld de kop is. Zonder dat krijgen ze de verborgen kop.

    Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.34.0-release op GitHub.

  90. v1.33.5

    Onderhoudsrelease

    Opgeslagen slides in je slidebibliotheek tonen weer hun volledige inhoud, ook slides die zijn bewaard voordat het slideformaat veranderde.

    Een fix voor de slidebibliotheek. Je hoeft niets te doen behalve updaten.

    Oudere opgeslagen slides tonen weer hun inhoud

    • Een slide die in de bibliotheek is bewaard voordat een slidetype van vorm veranderde, toont nu alles wat erin staat. Tot nu toe kon zo’n item alleen titel en subtitel laten zien, bijvoorbeeld een teamslide zonder de mensen, zowel in het voorbeeld in de bibliotheek als na invoegen in een deck.
    • Voeg je zo’n item in, dan krijg je de huidige vorm van de slide, zodat je hem bewerkt als elke andere slide van dat type.
    • Decks waarin zo’n slide al eerder is ingevoegd, krijgen bij het openen de inhoud terug, zolang ze sindsdien niet zijn opgeslagen.

    Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.33.5-release op GitHub.

  91. v1.33.4

    Onderhoudsrelease

    De "+ Subtitle"-knoppen op een slide werken weer op je eigen slidetypes: een klik maakt het veld aan en zet de cursor erin.

    Een fix voor installaties met eigen slidetypes. Je hoeft niets te doen behalve updaten.

    De ”+“-knoppen op je eigen slidetypes maken het veld weer aan

    • Op een eigen slidetype maakt een klik op ”+ Subtitle”, ”+ Meta” en dergelijke nu dat veld aan en zet de cursor erin. Tot nu toe deed de klik niets op elk slidetype dat je installatie zelf definieert, ook je eigen versie van een ingebouwd type, omdat de slide nog van de server aan het laden was toen de editor het nieuwe veld zocht.
    • Tekstvelden en opgemaakte tekstvelden werken allebei, en getypte tekst blijft na opslaan staan.
    • Klik je ergens anders terwijl de slide nog laadt, dan blijft er niets achter op de slide waar je begon.

    Voor installaties die Deckyard in code uitbreiden: het DOM-event slide-server-rendered bestaat niet meer. Wacht je op een server-gerenderde slide, gebruik dan slideRendered(el) uit client/lib/slide-runtime/slide-render.js; die geeft true zodra de markup erin staat en false als die nooit komt.

    Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.33.4-release op GitHub.

  92. v1.33.3

    Onderhoudsrelease

    Een gedeeld deck openen blokkeert je collega's niet meer: een slide gaat pas op slot als je er echt iets aan wijzigt, en het slot gaat eraf als je stopt.

    Een fix voor teams die samen in hetzelfde deck werken, met live samen bewerken uit (de standaard). Je hoeft niets te doen behalve updaten.

    Een slide gaat op slot als je hem bewerkt, niet als je ernaar kijkt

    • Een deck openen of door de slides klikken zet niets meer op slot. Tot nu toe hield wie een gedeeld deck als eerste opende slide 1 vast zolang het tabblad openstond, dus iedereen daarna zag “This slide is being edited by someone else” en las dat als “je mag hier niet bewerken”.
    • De eerste wijziging die je aan een slide doet zet hem op slot. De titel of de instellingen van het deck aanpassen doet dat niet.
    • Het slot gaat er vanzelf af: twee minuten na je laatste wijziging, zodra je naar een ander tabblad of venster gaat, en als je naar een andere slide gaat. Wat nog niet was opgeslagen, wordt eerst opgeslagen. Ga je weer typen, dan komt het slot ongemerkt terug.
    • Bewerkt iemand anders de slide, dan blijft jouw wijziging niet staan: je ziet wie hem vasthoudt, en de slide toont weer zijn of haar versie, sprekersnotities inbegrepen.
    • Een slot dat achterbleef door een dichtgeklapte laptop of een gecrasht tabblad blokkeert de slide niet meer tot je herlaadt. Zodra het op de server verlopen is, is de slide binnen een halve minuut weer bewerkbaar.

    Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.33.3-release op GitHub.

  93. v1.33.2

    Onderhoudsrelease

    Tekst naast een beeld staat in het midden van zijn kolom, zodat een korte titel en alinea in balans zijn met het beeld in plaats van bovenaan te hangen.

    Eén layoutfix, de derde release van vandaag. Je hoeft niets te doen behalve updaten; bestaande slides nemen het vanzelf over.

    Tekst naast een beeld staat verticaal in het midden

    • Op een image-text-slide staat de tekst nu in het verticale midden van zijn kolom: evenveel ruimte boven de titel als onder de laatste regel, de aside meegerekend. Dat geldt voor elke beeldbreedte en met het beeld links of rechts. Korte tekst naast een illustratie laat de onderste helft van de kolom niet meer leeg.
    • De image-set-slide doet hetzelfde in de layout met de beelden ernaast, waar de beelden als stapel naast de tekst staan.
    • Te lange tekst begint nog steeds bovenaan, dus de titel valt nooit van de slide.
    • De corner-layout en de image-set-layouts met een rij beelden houden de tekst bovenaan. Daar hoort de tekst bij het beeld erboven of ernaast, en de open ruimte eronder is onderdeel van het ontwerp.
    • Dit is de standaard, geen nieuwe instelling. Zet je fork in zijn eigen CSS een verticale uitlijning op de tekstkolom, dan blijft die waarde gelden.

    Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.33.2-release op GitHub.

  94. v1.33.1

    Onderhoudsrelease

    Fullscreen op de gepubliceerde pagina en in de presenter: geen scrollbar, en beide balken komen als overlay terug als je de muis beweegt.

    Eén fix, op dezelfde dag uitgebracht als 1.33.0. Verder is er niets veranderd en hoef je niets te doen behalve updaten. De reden om überhaupt op 1.33.x te zitten staat in 1.33.0.

    Fullscreen vult het scherm

    • Op de gepubliceerde pagina verbergt fullscreen beide balken. Met F bleef de bedieningsrij onder de slide hangen, met een scrollbar om erbij te komen. Nu zijn de titelbalk en de bedieningsrij weg, vult de slide het scherm, en schuiven beide balken als overlay in zodra je de muis beweegt, zonder dat de slide verschuift. Na een paar seconden verdwijnen ze weer.
    • Een venster dat het scherm vult telt ook als fullscreen. De groene knop van Safari en F11 gebruiken de fullscreen-modus van de browser niet, dus de balken bleven staan. De pagina behandelt een schermvullend venster nu hetzelfde.
    • Pijltjestoetsen, spatie en een clicker halen de balken niet terug, dus ze flitsen niet meer bij elke slide in beeld. Met Tab in een balk komen ze wel, en een balk blijft staan zolang de muis erop rust.
    • De presenter volgt dezelfde regels. In fullscreen komt de bovenbalk nu samen met de voortgangsbalk terug, en de slide gebruikt de volle hoogte in plaats van ruimte over te laten voor een balk die verborgen is.
    • ?ui=min is ongewijzigd: daar zijn geen balken, en F werkt er nog steeds.

    Het aantal ingebouwde slidetypes blijft 35.

    Zie voor de volledige lijst op commitniveau de 1.33.1-release op GitHub.

  95. v1.33.0

    Feature-release

    Een nieuw slidetype voor twee of drie beelden, speaker notes en een thema-template in de PowerPoint-export, countdowns die starten als je erop aankomt en lopen op de gepubliceerde pagina, en één breaking change in chartdata.

    Tien dagen werk, grotendeels op twee fronten. De PowerPoint-export neemt meer van het deck mee: speaker notes, en een template dat uit je thema wordt opgebouwd. En de slides waarmee je presenteert kregen een reparatieronde uit het echte gebruik, van countdowns tot een stemstand die wie later aansloot niet te zien kreeg.

    Controleer je charts voordat je update. De eerste rij van de data van een chart is voortaan altijd de kop en wordt nooit geplot. Een opgeslagen chart waarvan de eerste rij data was, leest die rij nu als kolomnamen en verliest hem als punt. Draai node scripts/scan-chart-headers.js (leest Postgres via .env, of deck-JSON met --dir <pad>) en bekijk elke treffer: een jaartallenkop die eerder verkeerd gelezen werd, hoeft niets; data die echt geen kop heeft, krijgt in de grid-editor één koprij erbij. Deckyard is in beta, dus deze breaking change komt in een minor-versie.

    Een nieuw slidetype voor meerdere beelden

    • Beelden + tekst (image-set-slide) zet twee of drie beelden naast, boven of onder de tekst. De layouttegels “Rij boven”, “Rij onder” en “Naast de tekst” wisselen nu naar dit type.
    • image-text-slide is één beeld. Decks die er meerdere beelden op hadden opgeslagen, worden bij het lezen omgezet; er is geen migratie om te draaien. Een API-client die images[], imageFit of textColumns naar dat type schreef, schrijft voortaan een image-set-slide.

    PowerPoint-export

    • Speaker notes gaan mee in het PPTX, als PowerPoint-notities bij elke slide. Eerder kwamen ze alleen apart mee als notes.md of notes.docx in de handoff-zip. Het document staat bovendien op naam van je app.
    • Een nieuwe exportrij, “PPTX template”, downloadt een leeg .pptx met layouts uit het thema van het deck: achtergrond, fonts, tekstkleuren en logo, per slide ingesteld. Het is geen master die een bestaande presentatie herstijlt.

    Charts

    • Balken landen op de rasterlijn die hun waarde noemt. Een staafdiagram gebruikt één as per plot, dus een 7 staat niet meer op de lijn van 8; rasterlijnen van een lijndiagram blijven binnen het plot, en een negatieve balk verschijnt waar hij eerder wegviel.
    • Plakken in de cel linksboven van de grid leest de eerste rij als kolomnamen, en de AI schrijft kale jaartallen weer als serienamen.
    • Live-databindingen en de bronvermelding bij een quote schrijven naar een veld dat ook echt getoond wordt.

    Countdowns en live sessies

    • Een countdown die automatisch start, begint als je op zijn slide aankomt, niet bij het openen van de presentatie. Eerder liepen alle timers in het deck vanaf het moment dat je begon te presenteren. Weggaan van de slide pauzeert hem niet.
    • Countdowns lopen op de gepubliceerde pagina en in de embed, met Start, Pauze en Reset. Eerder bleven ze op hun starttijd staan.
    • De cijfers staan in het midden van de slide, met of zonder titel, in het kopfont en -gewicht van het thema. De preview in de editor flikkert niet meer tussen twee maten.
    • Een scherm of telefoon die midden in een stemming aanhaakt, ziet de stand die er al is in plaats van “Totaal: 0” tot de volgende stem.

    Kleinere reparaties

    • De ImageKit-bibliotheek toont de nieuwste bestanden eerst, ook in de tag-chips. Een grote bibliotheek liet tot nu toe alleen de oudste zestig zien.
    • Een backup-export is compleet: met de auteursfoto’s op quote-slides, zonder call-to-action-links als beeld, en met de uploads als UPLOADS_DIR is ingesteld.
    • Een eigen slidetype uit Instellingen krijgt dezelfde achtergrond-, toegankelijkheids- en logo-instellingen als een ingebouwd type, en is nu aan te maken via de publieke API en de MCP-tools in plaats van te falen met Unknown slide type.
    • De deeldialoog houdt één hoogte terwijl hij laadt. De tegels voor chart, KPI en Likert in de slidekiezer tonen een echt voorbeeld, en een Engelse countdown zegt “Time!”.
    • De leesweergave noemt een KPI-item naar zijn label en toont een videoslide als “Video” met een link in plaats van een video-ID.

    Voor forks en integratoren

    • create_presentation_from_slides weigert een sleutel die het type niet declareert (unknown_field) in plaats van hem te laten vallen, en accepteert elk example uit get_slide_types. update_slide met een type weigert een typewissel die hij niet kan omzetten.
    • Elke slide ontstaat in één fabriek, dus een deck uit een import, de AI of een agent krijgt dezelfde standaardwaarden als een invoeging in de editor, per taal; een pollslide van een agent krijgt nu een pollId.
    • Een slidetype declareert hoe getrouw het exporteert (fidelity: { pptx }); een type uit een bestand zonder die declaratie geeft bij het opstarten een waarschuwing. Zie docs/reference/slide-type-fidelity.md in core.
    • Nieuwe optionele velddeclaraties: itemLabelField op een items-veld, mediaRef op een string-veld, foldUnofferedTo op een enum. Een thema kan de achtergrond declareren waarop zijn slides beginnen (defaultBackground).

    Geen security-fixes in deze release. Het aantal ingebouwde slidetypes gaat van 34 naar 35.

    De volledige lijst op commit-niveau staat bij de release 1.33.0 op GitHub.

  96. v1.32.0

    Onderhoudsrelease

    Een fork die eigen MCP-tools toevoegt, krijgt de storage scope aangereikt die hij nodig heeft, in plaats van vier regels core-logica te kopiëren en te zien verlopen.

    Een release met één item, en dat item is voor wie een fork draait. In de editor, in een presentatie of in een export verandert er niets; draai je Deckyard zoals hij komt, dan is deze update optioneel.

    Voor forks en integratoren

    • De custom-tools-naad reikt storageScopeOf(context) aan. Elke facade onder server/storage/ neemt sinds 1.4.0 een storage scope aan en weigert een kale repoRoot-string, maar de enige bouwer van die scope zat binnen core en stak de registerCustom-naad nooit over. Een fork-tool die storage wilde bereiken, kon dus ctx.repoRoot doorgeven en falen voor elke caller met een sleutel, of de logica van core naar de fork kopiëren en bij de volgende merge opnieuw kopiëren. storageScopeOf staat nu op de ctx van de naad, naast repoRoot en niet in plaats daarvan: repoRoot blijft het schijfpad voor thema’s en uploads, het is alleen geen storage-argument. De docs/reference/mcp-server.md van core laat de aanroep zien.

    Geen breaking changes en geen security-fixes in deze release. Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.32.0 op GitHub.

  97. v1.31.0

    Feature-release

    Een thema kan een licht en een donker logo meegeven en Deckyard kiest per slide de zichtbare; en een vertaling die sinds mei de verkeerde slide toonde, wordt door een migratie hersteld.

    Twee dagen na 1.30.0, een release over dingen die een deck van zichzelf weet. Een thema kan nu meer dan één logo meegeven en Deckyard laten bepalen welke leesbaar is op de slide in kwestie. De beeldbibliotheek opent op het uploaden en niet op het raster. En een vertaling die in mei stilletjes achterbleef bij zijn bron, komt weer in de pas.

    Draai npm run migrate na het bijwerken. Migratie 081 brengt het schema van 12 naar 13 en herstelt taalversies die een migratie uit mei oversloeg: een vertaling die een archived slide toont waar de hoofdtaal een tijdlijn heeft, is weer een tijdlijn. Decks worden ook op elke read hersteld, dus er blijft intussen niets kapot, maar de migratie is wat het vastlegt.

    Een thema kan twee logo’s meegeven

    • logoOnDark en logoOnLight naast assets.logo, plus titleLogoOn* voor de titelslide. Deckyard leest de ondergrond van de slide zelf - achtergrondkleur, of een achtergrondfoto - en zet daar de mark neer die er zichtbaar is. Een thema met één mark gedraagt zich precies als voorheen, dus dit kost je niets tot je het wilt.

    De beeldbibliotheek en de slides

    • De picker begint bij het uploaden. De dropzone en het URL-veld staan bovenaan op één rij, met het raster eronder. Een URL die je plakt, schuift niet meer onder je vingers weg.
    • Een kaart over een foto krijgt een echte scrim. Tekst op een card-stack over een achtergrondbeeld lag op een glazige tint; die heeft nu een scrim die hem leesbaar maakt.

    Vertalingen komen bij

    • Elke taalversie migreert, niet alleen de dominante. De migratie uit mei raakte de bron aan en liet de vertalingen staan; daarom kon één taal een archived slide tonen waar de andere een tijdlijn hebben. Migratie 081 herstelt het opgeslagen deck, en een read repareert het in de tussentijd.
    • Een oude slidetype-naam wordt op elke read herschreven. Een deck dat nog een teruggetrokken typenaam draagt, laadt zonder dat iemand een script hoeft te starten, op elke backend en in elke taalversie.
    • De vertaalprompt behandelt een ongedeclareerde tekstsleutel als proza. Zo’n veld werd overgeslagen; het wordt nu in elke taal vertaald.

    Kleiner herstelwerk

    • De standaardtaal voor e-mail in de instellingen rolt terug naar wat de server heeft als het opslaan mislukt, in plaats van een waarde te tonen die nooit is bewaard.
    • OpenAI-compatibele providers krijgen het tokenbudget van de aanroeper, zodat een lange generatie niet meer op een vaste standaard wordt afgeknipt.

    Voor forks en integratoren

    • err.details heeft per foutcode een vaste vorm. Een API-consument kan op code schakelen en weet welke velden details draagt.
    • In MCP hoort de gate van een tool bij zijn naam. Een fork-registrar die een core-tool alleen omwikkelt, houdt de permission en de readOnly-vlag van die tool in plaats van ze te laten vallen. Een expliciete permission: null op een gegate tool gooit nu bij het opstarten in plaats van hem stil open te zetten. Dit raakt je alleen met een eigen custom/mcp-tools.js.
    • Er breekt niets: geen breaking change en geen security-fix in deze release.

    Het aantal ingebouwde slidetypes blijft 34.

    Voor de volledige lijst op commitniveau, zie de 1.31.0-release op GitHub.

  98. v1.30.0

    Feature-release

    Elke weigering in Deckyard verschijnt nu op de plek waar hij ontstond - bij het veld, naast de knop, waar de rijen hadden gestaan - en alt-tekst in de beeldbibliotheek volgt de talen van het deck zelf.

    Een kleine release, drie dagen werk aan één idee: een melding over iets wat jij nog moet herstellen hoort geen toast te zijn die verdwijnt terwijl je hem leest. 1.29.0 begon daarmee bij de opslaan-knop; 1.30.0 maakt het af in de editor, de instellingenschermen en de inlogpagina’s. En de beeldbibliotheek gaat er niet langer van uit dat jouw deck Nederlands en Engels is.

    Er is geen reden om hier haast mee te maken. Deze release repareert niets wat in 1.29.0 stuk is, en voor een fork verandert er geen vorm.

    Een weigering blijft staan waar je hem veroorzaakte

    • Een formulier dat nee zegt, zegt dat bij het veld. Een lege naam, een ongeldige kleur, het verkeerde bestandstype: de melding staat bij het veld, met de focus erop, in plaats van in een hoek van het scherm.
    • Een API die een opslag weigert, zegt dat naast de Save-knop. Instellingen-tabs, e-mailtemplates, de font- en thema-editor en het opslaan in de bibliotheek houden de weigering zichtbaar tot je volgende poging, zodat je hem kunt lezen terwijl je herstelt wat hij noemt.
    • Inloggen, wachtwoord resetten, een gedeeld deck openen en als gast binnenkomen doen hetzelfde. Dit waren de laatste schermen die nog een toast gebruikten voor iets waar de lezer wat mee moet.
    • Een lijst die niet laadt, zegt dat op zijn eigen plek. De deel-modal, de reacties, de prullenbak en de slide-bibliotheek tonen de fout waar de rijen hadden gestaan, en stelen daarvoor je focus niet.

    Alt-tekst volgt de talen van het deck

    • Eén alt-tekstveld per taal die het deck heeft, in het beelddetail én bij het uploaden, in plaats van een vast paar Nederlands en Engels. De AI-generator vult precies die talen, en een gekozen beeld zaait elke taalbuffer in plaats van één.

    Voor forks en integratoren

    • Er breekt niets. createInlineError() en de doctrine in docs/reference/feedback-surfaces.md zijn nu de enige manier om een weigering te tonen, en een guard-test weigert een zelfgeschreven *-error-klasse. Dit raakt je alleen als je fork eigen editor-panelen meelevert.

    Het aantal ingebouwde slidetypes blijft 34.

    Voor de volledige lijst op commitniveau, zie de 1.30.0-release op GitHub.

  99. v1.29.0

    Feature-release

    Een deck heeft geen twee talen meer maar een lijst, waarin elke taal een versie is die je bewerkt, presenteert en deelt; en elke embed sinds 1.0.0 negeerde zijn eigen instellingen, wat deze release herstelt.

    Dit is de release waarin een deck ophoudt “de Nederlandse of de Engelse” te zijn en een deck met een lijst taalversies wordt. Eén menu in de editor-topbalk laat zien welke versie je bewerkt, welke andere versies er zijn, en hoe ver elke versie vertaald is. Het is ook de release die de embed repareert: de instellingen die je aan een ingesloten deck meegeeft, kwamen sinds 1.0.0 niet aan.

    Neem deze update als je ergens een embed hebt draaien. De boot-payload die de embedpagina aan de speler doorgeeft, ging via HTML-escaping een raw-text scriptblok in en parste dus nooit, waardoor elke embed op standaardwaarden terugviel. Slideteller, taalwissel, start, loop, ui en een ingestelde allowedOrigins-lijst doen nu wat jij hebt ingesteld. Een lege origin-lijst laat nog steeds alle origins toe, zoals gedocumenteerd.

    Neem hem ook als je de MCP-server aan hebt staan. Een aanroep over SSE is nu gescopet op de organisatie van de API-sleutel waarmee hij zich aanmeldde, en toolaanroepen worden getoetst aan de rechten en het quotum van die sleutel.

    De talen van een deck zijn een lijst

    • Eén taalmenu, één versie per taal. Het vaste paar NL|EN in de editor-topbalk is weg. Daarvoor in de plaats noemt één knop de versie die je bewerkt, in de eigen taal (“Nederlands”), en opent op elke versie die het deck heeft plus de talen die je kunt toevoegen. Een deck met één taal toont één regel; een deck met vijf toont er vijf.
    • De bronversie blijft staan terwijl je een vertaling bewerkt. Overschakelen naar een vertaling schuift de bron van het deck niet meer onder je vandaan, en je kunt vanuit hetzelfde menu een andere versie tot bron maken zodra die de versie is die je bijhoudt.
    • De vertaalmodals noemen hun bron en doel, zodat je vóór het starten ziet welke richting je op gaat, en per taal krijg je een vertaalvoortgang die uit het deck zelf volgt in plaats van uit een schatting.
    • Geneste itemteksten worden nu ook vertaald. Tekstblokken met rijen van blokken (rows[].blocks[]) sloeg de vertaler over, waardoor ze in de brontaal terugkwamen.

    De viewer en de volgcodes volgen de versies

    • /p/ en de embed tonen één taalknop per bestaande versie, in plaats van een vast paar dat een taal kon aanbieden die het deck niet heeft.
    • Een sessie munt één volgcode per versie, zodat iemand die in zijn eigen taal meekijkt, ook in die taal binnenkomt.
    • De presentatorconsole rendert de thumbnail van de volgende slide in de decktaal, waar die eerder de interfacetaal aanhield.

    Nieuw op een slide

    • callout-slide, de admonition-familie. Note, tip, warning en de rest, als eigen slidetype.
    • Vergelijkingsslides hebben subvarianten: versus, before-after, pros-cons en tradeoff, zodat de opmaak volgt wat je werkelijk vergelijkt.
    • Aside-insets zetten een contrastblok binnen een slide, op de tekst-, lijst- en beeld-met-tekst-types, zonder dat er een aparte slide voor nodig is.
    • De titelslide heeft een eigen typografische trede (een maat boven de rest van de schaal), en de cover stapt vanzelf een maat terug als de tekst niet past, in plaats van eruit te lopen.

    Herstelwerk dat je merkt

    • Deck-thumbnails laden weer, en ze zijn content-addressed: een deck dat je zojuist wijzigde toont een actuele thumb en niet een oude uit de cache.
    • Een geweigerde opslag zegt welk veld weigerde, naast de knop die weigerde, met de focus op dat veld. Lokale formulierweigeringen staan nu inline bij het veld en niet in een toast die verdwijnt terwijl je hem leest.
    • Een fout klinkt als een fout. Een foutmelding wordt als zodanig aan een schermlezer doorgegeven, Escape sluit een melding, en een melding met een knop blijft staan tot je die knop hebt gebruikt.

    Voor forks en integraties

    • ⚠ Twee CSS-klassen hernoemd. .slide-title-universal wordt .slide-title en .slide-lijstje wordt .slide-list op het titel- en lijsttype, en .sfi-card-kicker wordt .sfi-card-title op het feedback- en follow-invite-type. De eigen stylesheets van Deckyard en de kernthema’s gaan mee; alleen een fork met eigen regels op de oude namen moet hernoemen. De families tsu-* en .lijst* blijven ongewijzigd. Deckyard blijft op 1.x zolang de bètabadge er staat, dus een minor-release met breaking changes is de bedoelde vorm en geen fout.
    • Definities van eigen slidetypes worden gevalideerd, en scaffold schrijft alleen definities die daar doorheen komen. Een slidetype uit de database krijgt zijn CSS gescopet op de eigen root, er is een vastgelegde scoping-conventie voor JS-types uit bestanden, en een gedeelde partials-bibliotheek voor eyebrows, badges en highlights.
    • Een ingelogde maar onbevoegde API-aanroep krijgt 403 in plaats van 404. Een weigering uit de opslag draagt nu details met field, index, itemIndex en reason, zodat een client kan aanwijzen wat er mis was.

    Het aantal ingebouwde slidetypes gaat van 33 naar 34 met callout-slide.

    Voor de volledige lijst op commitniveau, zie de 1.29.0-release op GitHub.

  100. v1.28.0

    Feature-release

    Eén commando rendert je thema over elk slidetype op één vel, Companion heet in alle twaalf talen hetzelfde, en het migratiescript voor achtergronden werkt eindelijk op Postgres.

    De derde release van de dag, en de enige met iets nieuws erin: een contactvel voor thema’s. Beheer je een thema, dan rendert npm run theme:preview <thema-id> nu elk slidetype tegen elke achtergrond die dat thema aanbiedt, op één HTML-pagina die je kunt doorscrollen. Zo ontdek jij waar een thema stukgaat, en niet je publiek.

    Een heel thema in één oogopslag

    • npm run theme:preview <thema-id> schrijft een contactvel. Eén tegel per combinatie van slidetype en achtergrond, gegroepeerd per type, plus een contrasttabel voor de vlakke achtergrondvarianten van het thema. Tot nu toe was de enige voorvertoning die van de themabewerker, die een databaseconcept over een handjevol types rendert; een fork die zijn huisstijl als bestandsthema in custom/themes/ versiebeheert had helemaal geen voorvertoning, en niemand zag wat een thema deed met de ruim dertig types die het paneel weglaat.
    • Een tegel is wat een export oplevert. Elke tegel gaat door hetzelfde renderpad als een PDF- of PNG-export, in plaats van een gelijkende namaak die de regressies zou blijven doorlaten waarvoor het vel bestaat. Er is geen draaiende server en geen database voor nodig.
    • Het vel loopt de matrix af die de editor aanbiedt, inclusief de achtergronden die een thema bovenop de eigen achtergronden van een slidetype legt, en het slaat een themagebonden type over onder een thema dat het niet kan gebruiken. De contrasttabel scoort wat eerlijk meetbaar is: een variant op een vlakke of gradiëntgrond krijgt een verhouding, artwork-gronden worden gemeld als niet gemeten in plaats van gescoord als een fout die ze niet hebben.

    Vertalingen kiezen één woord

    • “Companion” is in alle twaalf talen één productnaam. Negen talen hadden het vertaald - “Följevy”, “Begleitansicht”, “Acompañante”, “Compagnon”, “Asystent” en de rest - waardoor dezelfde weergave per taal op een andere functie leek. Het kernwoord is nu overal het leenwoord, terwijl de bepaling vertaald blijft, dus het Duits leest “Publikums-Companion” en het Frans “Companion du public”.
    • Het Italiaans spreekt je overal informeel aan. De taal stond al ongeveer twee op één in de tu-vorm, maar een eerdere ronde had de klikwerkwoorden naar het formele Lei geduwd (“Faccia clic”); ongeveer 260 strings lezen nu als één register, inclusief beleefdheidsbezittelijken en clitica. Een paar Italiaanse termen zijn tegelijk vastgelegd, waaronder de follow-along-uitnodiging, die het leenwoord gebruikt zoals het Engels en het Nederlands dat doen.
    • Het Pools en het Fins krijgen een handvol herschrijvingen waar de eerdere ronde iets leesbaars maar niet idiomatisch had achtergelaten. Sleutelverzamelingen, sleutelvolgorde en plaatshouders blijven in alle 27 bestanden ongemoeid; alleen de woorden veranderden.

    Voor wie zelf host

    • De migratie van oude achtergrondafbeeldingen werkt op Postgres en neemt taalversies mee. Het script liep één map met deck-JSON af, dus een Postgres-installatie migreerde niets en meldde een keurige nul, en de vertaalde versies van een deck werden in beide opslagvormen overgeslagen - in één productiedataset zaten daar meer oude slides dan in de decks zelf. Het accepteert nu --backend auto|file|postgres|both en loopt decks, taalversies en bibliotheekitems per constructie af. Draaide je de migratie eerder op een bestandsopslag, dan hoef je niets te doen; sloeg je ‘m over, dan werkt hij nu in beide opstellingen. Versiemomentopnamen blijven met rust tenzij je --include-versions meegeeft, want die vouw is verliesgevend en oude inhoud rendert toch correct tot de eerste bewerking na een herstel.

    Het aantal ingebouwde slidetypes blijft 33.

    De volledige lijst op commit-niveau staat bij de release 1.28.0 op GitHub.

  101. v1.27.2

    Onderhoudsrelease

    Een thema dat je uitzette is nu echt uit in elke kiezer, het beeldenveld springt niet meer weg onder je cursor, en een handvol Engelse labels kiest één spelling.

    Drie reparaties, dezelfde dag geknipt als 1.27.1. De belangrijkste is de thema-allowlist: die stond gedocumenteerd als de zichtbare deelverzameling van thema’s, maar gedroeg zich als een etiket, zodat een thema dat je had teruggetrokken nog steeds bereikbaar was vanuit twee van de drie kiezers die er een aanbieden.

    Een teruggetrokken thema is ook echt weg

    • De enabledThemes-allowlist wordt server-side afgedwongen, in elke kiezer. GET /api/themes gaf eerst elk thema terug en merkte de thema’s buiten de allowlist als uitgeschakeld; alleen het aanmaakraster las dat merkteken, en een schakelaar “Toon alle thema’s” maakte het met één klik ongedaan. De themakeuze in de deckinstellingen en de rij “begin met een thema” op Home negeerden het volledig. Het endpoint filtert nu, dus geen enkele kiezer kan aanbieden wat de allowlist weglaat, en de zachte schakelaar is verdwenen.
    • Een deck dat ouder is dan de terugtrekking houdt zijn eigen thema. De kiezers geven het thema mee waar het deck op staat, en het opgeloste standaardthema blijft altijd in de lijst, zodat een organisatie zichzelf niet buiten het thema kan sluiten waarmee haar eigen nieuwe decks worden gemaakt.
    • Thema’s die je beheert blijven zichtbaar waar je ze beheert. Het instellingentabblad Thema’s vraagt om de ongefilterde lijst, want het kan geen vinkje aanbieden voor een thema dat het niet mag zien, en de vinkjes lezen nu de allowlist die daadwerkelijk geldt.
    • Nieuwe omgevingsvariabele ENABLED_THEMES, naast DEFAULT_THEME en met dezelfde volgorde: de app-instelling wint, dan de kommagescheiden variabele, dan helemaal geen allowlist.

    Opgelost

    • De lijst “Geselecteerde afbeeldingen” ververst ter plekke. Een vinkje aanzetten in een beeldenveld schreef de waarde weg, maar de lijst bleef de vorige tonen, en de twee paden die wél opnieuw tekenden bouwden het hele formulier op, waarmee de focus van het vinkje verdween dat je net had gebruikt. De lijst werkt zich nu ter plekke bij, en een selectie die over het maximum van het veld heen loopt zet het vinkje uit van de afbeelding die afviel, in plaats van ‘m geselecteerd te laten lijken.
    • Eén Engels per label. Vier sleutels droegen een ander Engels in het slidetype-register dan in de interface: “Centre label” tegenover “Center label”, een “Title (optional)” voor een veld dat sowieso niet als optioneel wordt gemarkeerd, een Nederlands voorbeeld in een Engelse hulptekst, en een paar aria-labels die hun eigen label herhaalden. Ze zijn het nu eens, wat betekent dat een paar Engelse labels in de inspector net anders lezen dan in 1.27.1; het Nederlands en de tien andere talen blijven zoals ze waren.

    Het aantal ingebouwde slidetypes blijft 33.

    De volledige lijst op commit-niveau staat bij de release 1.27.2 op GitHub.

  102. v1.27.1

    Beveiligingsrelease

    Een thema kan de PDF-export niet meer het netwerk op sturen, een tweetalig deck houdt beide talen vast bij een samenwerkbewerking, de foto-achtergrond van een themavariant haalt de PDF, en de editor toont één achtergrondregelaar per slide.

    Een patchrelease vol reparaties, en één ervan gaat over werk niet kwijtraken. Een tweetalig deck met een text-blocks-slide kon stilletjes zijn tweede taal verliezen zodra iemand het in een samenwerksessie opende; dat is opgelost, samen met een PDF-export die thema-artwork liet vallen en een inspector die dezelfde achtergrondkiezer twee keer toonde.

    Neem deze update als iemand anders dan jij een thema kan bewerken. Een externe URL in een themavariabele bereikte tijdens een PDF-export headless Chrome, waarmee vrije CSS in de themabewerker een route werd voor server-side request forgery naar alles wat je exporthost kan bereiken. De export haalt externe URL’s nu uit themawaarden voordat het document wordt gerenderd.

    En neem ‘m vóór de volgende samenwerkbewerking als je tweetalige decks bewaart. De dominante taal werd bij een rondgang in beide versies geschreven, en niets waarschuwde je.

    Tweetalige decks overleven samenwerking

    • Verborgen proza is nog steeds proza. De samenwerkcodec behandelde elk verborgen veld als één machinewaarde die talen delen, maar de text-blocks-slide bewaart 38 verborgen spiegels van door mensen geschreven tekst, dus een rondgang vouwde ze samen tot één taal. Acht modules hielden er elf net verschillende opvattingen op na over wat vertaalbare tekst is; ze delen nu één definitie - een veld is tekst als zijn type dat zegt, op elk nestniveau - en de spiegels vertalen als het proza dat ze zijn.

    Exports renderen het artwork van het thema, en alleen dat

    • De beeldachtergrond van een themavariant komt aan in de PDF. Twee losstaande fouten maakten hem leeg: een lokale beeld-URL in een themavariabele ging nooit door de inbedpas die elk ander beeld neemt, en de gradiëntrasterizer plette een foto met leesbaarheidswaas tot zijn terugvalkleur. Goed in de editor, leeg in de export - nu in beide hetzelfde.
    • Themawaarden kunnen de export niet het netwerk op sturen. Dezelfde pas haalt nu elke externe URL uit themavariabelen voordat het document headless Chrome bereikt, en sluit daarmee een route voor server-side request forgery via vrije CSS in de themabewerker.
    • Twee sluimerende exportfouten gingen mee: een klassennaam die als deeltekst matchte en gradiënten als pixel-voor-pixel-arcering de PDF in duwde - seconden per pagina - en een stylesheetvolgorde waardoor het basisthema alleen in exports de eigen tekstkleur van een variant oversloeg.

    Een donkere achtergrond krijgt leesbare voorgrond

    • Een achtergrondvariant verklaart nu hoe donker zijn grond is. Wie de tekstkleur van een variant instelt, zegt dat al; de slide draagt nu dezelfde contrastklasse die het beeldachtergrondpad afgeeft, zodat behandelingen per slidetype op de helderheid selecteren in plaats van achtergrondnamen te herkennen. Een donkere variant levert geen witte kaarten met witte tekst meer op.

    Eén achtergrondregelaar per slide

    • De dubbele kiezer “Achtergrondafbeelding” is weg. Een half afgemaakte samenvoeging vouwde het oude beeldveldenpaar per type alleen voor één slidetype in de gedeelde regelaar; elk type dat de ontwikkelaarsdocumentatie volgde kreeg ze allebei. De vouw draait nu voor elk type, heelt een opgeslagen deck bij de eerste bewerking, en een achtergrond wissen zaait niet stilletjes de foto terug die je net weghaalde.

    De editor spreekt overal je taal

    • Keuzeopties en gedeelde veldlabels zijn vertaald in alle twaalf talen. Zesenzestig optielabels en de achttien gedeelde veldlabels - de knopvelden, tekstgrootte, het sluitgedrag van poll en schaal, de uitlijnregelaars - toonden rauw Engels in elke taal; ze dragen nu de woorden die elke taal elders in de interface al gebruikt.

    Het aantal ingebouwde slidetypes blijft 33.

    De volledige lijst op commit-niveau staat bij de release 1.27.1 op GitHub.

  103. v1.27.0

    Beveiligingsrelease

    Een instance-beheerder heeft geen stille macht meer in een werkruimte waar hij alleen lid is: de server scopet de vijf resterende omwegen nu naar de actieve organisatie.

    Draai je Deckyard met meer dan één organisatie, dan is dit een release om te nemen. Een instance-beheerder die overschakelde naar een werkruimte waar zijn lidmaatschap “lid” zegt, hield zes mogelijkheden die de interface hem al niet meer aanbood, want de server volgde de client nooit. Die zijn nu dicht.

    Neem deze update als je met meerdere organisaties werkt. In een instance met één werkruimte verandert er niets: de regel valt terug op de controle die hij altijd al deed.

    De macht van een beheerder stopt bij de grens van de werkruimte

    • De server scopet de vijf resterende beheerdersomwegen naar de actieve organisatie. De vorige release verborg tien beheerdersknoppen die de instance-brede rol lazen in plaats van de rol in de werkruimte waar je daadwerkelijk in zit, maar de verzoeken erachter slaagden nog steeds. In die werkruimte kon een instance-beheerder een publieksvraag verwijderen, een beeld uit de bibliotheek weggooien, andermans reacties oplossen en bewerken, de zichtbaarheid van elk deck wijzigen inclusief van organisatie naar privé, en slides vergrendelen of ontgrendelen op een deck dat hij niet had gemaakt. Alle zes controles vragen nu of je beheerder bent van de organisatie waar je in zit.
    • De tien knoppen in de client volgen de actieve werkruimte ook, dus de knop en het verzoek erachter beantwoorden eindelijk dezelfde vraag. Een geweigerde bevoegdheid rendert bovendien als een gewone weigering in plaats van een kop “Er ging iets mis” boven een stacktrace.
    • De voorbeeldweergave van e-mailsjablonen rendert in een gesandboxte frame. Door een beheerder geschreven opmaak met ingevulde velden werd rechtstreeks in de instellingenpagina geschreven, in dezelfde origin als je sessie. Het was nooit een rechtenescalatie, want schrijver en lezer hebben dezelfde bevoegdheid, maar het was de laatste plek waar dat argument iets overeind hield. Meegenomen: de voorbeeldweergave toont nu de echte mail, want de omhulling met het lettertype, de kleur en de breedte van 600 pixels van de mail zelf werd onderweg weggegooid, waardoor je de opmaak van de instellingenpagina zat te bekijken.

    Opgelost

    • ?limit=abc leegt de pagina niet meer. De publieke v1-API had een eigen kopie van de paginatieparser zonder controle op een waarde die geen getal is, dus een onzinnige limiet leverde een leeg resultaat op en een null als limiet in de envelop. Beide kopieën zijn nu één functie, die terugvalt op de standaardwaarde.
    • Alle drie de Q&A-weergaven lezen hetzelfde veld. De volgpagina, het notitiepaneel van de presentator en de moderatieroute hadden elk een eigen kopie van de vragenlijst, en die waren uit elkaar gelopen op het veld dat de tekst van de vraag draagt. Ze zijn het vandaag eens, dus er was niets zichtbaar mis, maar de moderator was één schemawijziging verwijderd van het verwijderen van een vraag waarvan hij de tekst nooit had gezien. Er is nu één accessor, één feed en één set mutaties.
    • en/ is weer een superset van elke locale. Tweeënzestig keys bestonden alleen in het Nederlands, en de globale slidevelden hadden een aparte key per slidetype in plaats van één gedeelde key per veld. Beide zijn opgelost en vertaald naar alle tien de aanvullende talen, samen met een tekstronde door zes daarvan.

    Breaking, voor wie meebouwt

    Deckyard blijft op 1.x zolang de betabadge erop staat, dus een minor release met breaking changes is de bedoelde vorm en geen vergissing. Deze twee raken de vertaalscripts in de repository, niet een draaiende instance:

    • npm run i18n:validate bestaat niet meer. Elke controle die het deed is nu een test.
    • De i18n-scripts delen één vlagvocabulaire. --dry-run en --report en het kale taalargument zijn vervangen door --apply en --json, met lezen als standaard, zodat een script alleen schrijft als je dat zegt.

    Het aantal ingebouwde slidetypes blijft 33.

    De volledige lijst op commit-niveau staat bij de release 1.27.0 op GitHub.

  104. v1.26.0

    Feature-release

    De interface is nu compleet in twaalf talen, en een poll of schaal bewaart zijn antwoorden in één array in plaats van tien genummerde velden.

    Deckyard leverde tien vertalingen die maar half vertaald waren: de taal was te kiezen, maar ergens tussen een derde en twee derde van elk scherm viel terug op het Engels. Alle tien zijn nu af, dus de interface is compleet in twaalf talen. Daarnaast zijn de laatste genummerde velden uit het deckformaat verdwenen.

    Schrijf je decks via de API of MCP in plaats van via de editor, dan is de poll- en likertwijziging hieronder degene om te lezen; bestaande decks migreren vanzelf.

    De interface is compleet in twaalf talen

    • Duits, Frans, Spaans, Portugees, Italiaans, Pools, Fins, Deens, Zweeds en Noors zijn af. Elk ging van zo’n 1.200 keys, met de rest terugvallend op het Engels, naar de volle set van ongeveer 3.400. Engels en Nederlands waren al compleet, dus twaalf talen tonen nu elk scherm in de taal die je koos, niet alleen de menu’s.

    Polls en schalen bewaren hun antwoorden in één lijst

    • De antwoorden van een poll en de punten van een schaal zijn één options-array. Het waren option1 tot en met option4 op een poll en option1 tot en met option10 op een likertslide, de laatste genummerde veldfamilie in het formaat. Schemastap v8 naar v9 vouwt ze elk samen tot één lijst van { text }-items. Bestaande decks migreren automatisch, en al uitgebrachte stemmen blijven wijzen naar het antwoord waarop ze zijn uitgebracht. Genereer je decks via de API, MCP of de AI-catalogus, schrijf dan voortaan options: [{ text: '...' }].
    • Een antwoord leegmaken tijdens een lopende poll verlegt de stemmen niet meer. Omdat de genummerde vorm gaten kon hebben, telden beide lezers stemmen tegen de ingedikte lijst, dus het tweede antwoord van een lopende poll leegmaken verschoof stilletjes elke stem die op het derde was uitgebracht. Een echte lijst heeft geen gaten, dus dit gebeurt niet meer.
    • Een schaal leest als een geordende lijst, een poll als een ongeordende, in de leesweergave en in exports, want de likertarray verklaart dat zijn volgorde betekenis draagt.

    De leesweergave projecteert structuur, geen configuratie

    • Tabel- en datasetslides volgen hun structuurcontract. Een bijschrift beslaat de sectie in plaats van de breedte van de tabel, en een markdowncel rendert inline in plaats van in een eigen alinea.
    • Configuratie verscheen niet langer als proza. Een iconnaam, een id uit de mediabibliotheek, de doelslide van een poll en een blok zoomcoördinaten zijn allemaal tekenreeksen, dus de leesweergave drukte ze af als tekst. Een veld verklaart nu zelf of het leesbare tekst is. Het zichtbare effect: een raster met iconkaarten had “rocket” als kop in plaats van de eigen titel.
    • Alt-tekst wordt niet meer twee keer gezegd. Het beeld van een item vouwt nu in zijn eigen figuur, zoals beelden op slideniveau altijd al deden, dus de alt-tekst van een teamkaart is de beschrijving van de foto en niet ook de kop van de kaart.

    Opgelost

    • Een deck met een eigen slidetype bewaart weer. De bouwer in de instellingen zet een eigen type in de database, maar het opslagpad controleerde slides tegen de bestandsgebaseerde registry, waar een databaserij nooit in kan staan. De editor voegde de slide dus gewoon toe en elke autosave erna antwoordde 400, waardoor het deck onbewaarbaar was tot je de slide verwijderde. Opslaan valideert nu tegen de registry van de organisatie zelf, dezelfde die de viewers en exports al lazen.
    • Het images-veld is af als uitbreidingspunt, zodat de eigen slidetypes van een fork het meervoudige beeldveld kunnen gebruiken; het dode alt-pad is weg.

    Het aantal ingebouwde slidetypes blijft 33.

    De volledige lijst op commit-niveau staat bij de release 1.26.0 op GitHub.

  105. v1.25.0

    Feature-release

    Een deellink werkt eindelijk voor de mensen voor wie hij bestaat: wie geen account heeft krijgt het deck, het thema erbij, en een antwoord als de verificatie mislukt.

    Het hele publiek van een deellink bestaat uit mensen die niet ingelogd zijn, en voor hen was de viewer op drie manieren tegelijk stuk. Deze release repareert ze alle drie, en zet een CSP-header op de app-shell zelf.

    Stuur je deellinks naar mensen buiten je organisatie, neem deze update dan. Een anonieme bezoeker met een volstrekt geldige link kreeg “Presentatie laden mislukt”.

    • Het deck laadt. De viewer haalde het op via een route die op id wordt aangesproken en achter de inlogpoort zit, dus wie geen account had kreeg een 401. Het rijdt nu mee op de ene aanroep die de link bewijst, POST /api/share/:token/verify, en dat is meteen de enige plek waar een wachtwoord gecontroleerd kan worden. Slides die voor kijkers verborgen zijn verlaten de server nooit, en eigenaarsstempels, organisatie en zichtbaarheid ook niet.
    • Het eigen thema van het deck komt mee. Een eigen thema is een databaserij die via een route achter de inlogpoort wordt opgelost, dus elk anoniem oppervlak liep daar tegen een 401 aan, slikte die in en rendeerde het deck op een neutraal terugvalthema: stilletjes zonder huisstijl. Het thema reist nu mee op de payload waar de bevoegdheid al voor is verleend, en dat dekt de deellinkviewer, het meekijkende publiek en de notitiecompagnon. Ingebouwde thema’s zijn statische bestanden die de client zelf laadt.
    • Een mislukte verificatie zegt iets. Een gast van wie de verificatielink faalde werd teruggestuurd en kreeg helemaal niets te zien. Er is nu een banner tussen de deckchrome en de slide, want de link is geldig en het deck is leesbaar; alleen de identiteitsstap mislukte. Hij draagt de knop om een nieuwe link aan te vragen in plaats van te beschrijven waar die te vinden is. Eén geval krijgt zijn eigen antwoord: een verificatietoken is na één gebruik op, dus wie dezelfde mail twee keer aanklikt terwijl hij al een lopende sessie heeft, krijgt te horen wat er gebeurde en verder niets, in plaats van het advies een link aan te vragen die hij niet nodig heeft.

    Typografie schaalt met de slide

    • De typografische schaal van een slide volgt uit de slide zelf. Het waren tien letterlijke pixelwaarden, en de themavermenigvuldiger die het commentaar erboven aankondigde was nooit gebouwd. Elke stap is nu een aantal referentiepixels dat door de breedte van de slide een lengte wordt, en --t-slide-text-scale werkt. Op het referentiedoek van 1600x900, wat vandaag elk pad is, komt elke stap precies uit op de waarde die hij had; op elk ander formaat is hij evenredig.

    Beveiliging

    • De app-shell stuurt een CSP-header, waarmee het werk af is dat de vorige twee releases voor de renderpaden deden.

    Opgelost

    • Plakken onder een bovenliggende slide landt achter zijn kinderen, niet ertussen. De nesting rendeerde goed, maar de deckvolgorde raakte verweven, dus de nummering las 1 Ouder, 3 Kind, 4 Kind, 2 Geplakt. Dupliceren via het menu in de formulierkop had dezelfde fout.
    • De foutteksten bij deelname als gast hangen aan de machinecode, en de dubbele e-mailcontrole is weg.
    • De auth-omweg voor ontwikkelaars gebruikt een geldig adres (dev@local.test).

    Het aantal ingebouwde slidetypes blijft 33.

    De volledige lijst op commit-niveau staat bij de release 1.25.0 op GitHub.

  106. v1.24.0

    Beveiligingsrelease

    Lead capture is met wortel en tak verwijderd, de CSP wordt een echte header op gepubliceerde pagina's en embeds, en 21 API-foutcodes vallen samen tot één.

    Het slidetype lead capture is weg, samen met alles wat eraan hing. Het was een formulier dat je op een slide kon zetten maar nooit kon versturen: de marketingtoestemming waar het op wachtte is nooit aangesloten, dus het verzamelde niets. De betahouding van Deckyard zegt dat een half gebouwde functie gestript wordt in plaats van geparkeerd, en het plan om bezoekersgegevens fatsoenlijk te verzamelen vervangt de code straks in plaats van hem te bewaren.

    Het aantal ingebouwde slidetypes gaat van 34 naar 33. Een deck met een opgeslagen lead-capture-slide laadt, presenteert en exporteert nog gewoon; de slide rendert als gearchiveerde placeholder die het type noemt en elk veld zichtbaar houdt. Een scan van opgeslagen decks op 22 augustus vond er geen enkele die hem gebruikte.

    Wat er mee weg is

    • De CSS-klassen .slide-lead-capture en .lead-capture-* worden niet meer uitgeschreven. Stileer je slidetypes in een fork, dan bestaan die namen niet meer.
    • De endpoints onder /api/leads zijn verwijderd, samen met de leadopslag, de AVG-tokenopslag en de notificatiemail aan de eigenaar met zijn twee templates.
    • De webhook lead.submitted is weg, en zijn rij in de admin ook. Er blijven zeven instelbare events over.
    • De instelling leads.retentionDays, de mailvoorkeur voor leads en de adminkaart “Lead capture” zijn verwijderd, net als /my-data en het leads-tabblad in analytics.
    • Een migratie verwijdert de tabellen lead_submissions en gdpr_verification_tokens. Niets anders las ze: gasten via een deellink dragen hun eigen verificatiekolommen en het wispad van analytics heeft zijn eigen token, allebei onaangeroerd.

    Dit is geen major release: /api/leads hoorde nooit bij /api/v1, en sinds het type weg is kon geen enkel deck nog een lead opleveren.

    De CSP wordt een header

    • Gepubliceerde pagina’s (/p/) en embeds (/embed/) sturen de document-CSP als echte HTTP-header, niet alleen als meta-tag. Een aantal directives wordt in meta-vorm genegeerd, dus een beleid in een header is het beleid waar een browser volledig naar kan handelen.
    • hls.js zit nu in de repository, waarmee het laatste CDN op het renderpad dicht is. Video afspelen hangt niet meer af van een externe host die het doet.

    Eén code voor verkeerde invoer

    Vertakt jouw API-client op een invalid_<iets>-foutcode, dan moet die aangepast worden. Eenentwintig ervan vallen samen tot error: "invalid" plus details.field, dat het invoerveld noemt dat de code eerder in zijn achtervoegsel verstopte. De status blijft gelijk: overal 400. Weg zijn invalid_category, invalid_colors, invalid_contact, invalid_email, invalid_fonts, invalid_format, invalid_label, invalid_level, invalid_new_owner, invalid_order, invalid_permission, invalid_permissions, invalid_presentation, invalid_registration_mode, invalid_role, invalid_slide_index, invalid_slug, invalid_source, invalid_style, invalid_usage en invalid_weight.

    De vier 401-codes blijven: invalid_password, invalid_token, invalid_or_expired en invalid_or_revoked zeggen dat de credential niet houdt, en dat is een ander antwoord op een andere status.

    Opgelost

    • Zeggenschap over een deck leest het eigenaarsstempel, niet eigenaar-of-maker. Wie een deck maakte en het daarna overdroeg zonder samenwerker te blijven, kon er nog steeds in schrijven, het verwijderen, het opnieuw delen en de samenwerkers beheren. Zo iemand krijgt nu een alleen-lezen editor. Dit was alleen bereikbaar na een eigendomsoverdracht waarbij de vorige eigenaar geen samenwerker bleef.
    • De nooit getoonde cookiebanner is verwijderd. Hij stond in de code en verscheen nooit.

    Het aantal ingebouwde slidetypes gaat van 34 naar 33.

    De volledige lijst op commit-niveau staat bij de release 1.24.0 op GitHub.

  107. v1.23.0

    Beveiligingsrelease

    Elk gerenderd document draagt nu een Content-Security-Policy, de mediaprovider heet S3 in plaats van Scaleway, en mensen worden bij hun naam genoemd in plaats van bij hun adres.

    De vorige twee releases haalden third-party scripts van het renderpad af. Deze vertelt het de browser: elk document dat Deckyard rendert draagt een Content-Security-Policy die de hosts noemt waar hij code van mag laden. Het is de eerste van de drie uitspraken over externe herkomst die de machine die het document draait ook echt kan weigeren.

    Gebruik je opslag op afstand voor media, dan worden je omgevingsvariabelen hernoemd. De oude namen blijven werken tot de eerste release na 2026-11-01, elk met een waarschuwing bij het opstarten. Details hieronder.

    Een beleid dat de browser afdwingt

    • Elk renderpad zendt een CSP uit, op één plek samengesteld en uitgezonden vóór alles wat kan laden. Het is een hostlijst voor code en stijlen, geen XSS-verdediging, en dat staat er ook bij: de renderpaden zetten hun eigen runtime inline, dus script-src en style-src hebben 'unsafe-inline' nodig. Wat hij weigert is een script van een host waar niemand voor gekozen heeft, en default-src 'none' laat elk nieuw soort verzoek dichtvallen.
    • De laatste CDN-ladingen zitten nu in de repository. pdf.js kwam van cdnjs een headless Chrome in; Prism en KaTeX worden op elk renderpad uit de meegeleverde kopie geserveerd, niet alleen in de app.
    • Provider-id’s voor analytics worden gevalideerd in plaats van ge-escaped.

    De mediaprovider heet S3, niet Scaleway

    De mediaprovider op afstand was naar één leverancier vernoemd terwijl hij eronder gewoon S3-compatibel is.

    • MEDIA_STORAGE_MODE=scaleway wordt =s3
    • SCW_ACCESS_KEY / SCW_SECRET_KEY / SCW_BUCKET / SCW_REGION / SCW_ENDPOINT / SCW_CDN_URL worden S3_ACCESS_KEY / S3_SECRET_KEY / S3_BUCKET / S3_REGION / S3_ENDPOINT / S3_PUBLIC_URL

    De oude namen worden gelezen tot de eerste release na 2026-11-01, alleen als hun S3_*-tegenhanger leeg is, en elke naam die gelezen wordt drukt bij het opstarten een waarschuwing af met zijn vervanger erin. S3_ENDPOINT is verplicht onder de nieuwe namen: MEDIA_STORAGE_MODE=s3 weigert zonder te starten. Een onaangeroerde oude installatie is de ene uitzondering, waar een lege endpoint nog steeds wordt afgeleid als https://s3.<regio>.scw.cloud. Een half ingevulde set waarschuwt nu bij het opstarten in plaats van stilletjes op lokale opslag te blijven.

    Mensen hebben een naam, geen adres

    Het identiteitswerk dat in 1.16.0 begon rondt af op de oppervlakken die naar andere mensen wijzen.

    • Reacties en slidevergrendelingen noemen mensen met een id en een weergavenaam. Een reactie draagt een auteurspaar in plaats van een adres plus een naam, en de AI-auteur wordt door de server gemarkeerd in plaats van doordat de client adressen vergelijkt.
    • Stempels voor maker en weggooier zijn ook paren, en de terugval op het e-mailadres in identiteitsherkenning is opgeruimd.
    • /api/v1/slide-library geeft createdById terug in plaats van createdBy. Dat oude veld was het e-mailadres van de maker, dat werd prijsgegeven aan elke API-sleutel met leesrecht op de bibliotheek. De rest van het publieke v1-oppervlak gaf al alleen id’s terug.

    Verwijderd

    • De vergrendeling op presentatieniveau en zijn wachtrij met toegangsverzoeken zijn weg, samen met de routes /api/presentations/:id/lock/*, de tabellen presentation_locks en lock_requests en de variabele USE_DB_LOCKS. De client had vergrendeling op slideniveau vast ingebouwd; dit pad werd nooit bereikt. Vergrendeling op slideniveau blijft zoals hij was, en één echte fout daarin is opgelost: bij het vrijgeven van een vergrendeling werd de rij zonder vervalfilter gelezen, waardoor een verlopen vergrendeling van iemand anders 409 antwoordde op een slot dat niemand vasthield.

    Een eigendomsoverdracht is definitief

    • Wie een deck overdroeg kan het niet terugnemen. POST /api/presentations/:id/transfer-ownership antwoordt 401 voor iemand die alleen het makersstempel heeft; de beslissing hangt aan het eigenaarsstempel in plaats van aan eigenaar-of-maker. Je houdt de vermelding als maker, niet de zeggenschap.

    Voor API-clients

    • Elke opslagfout antwoordt met de status die zijn eigen register noemt, in plaats van standaard 400. parent_not_found is 404, own_question is 403, en de codes voor interne fouten zijn 5xx. Acht codes zijn hernoemd naar snake_case.
    • De synoniemen voor foutredenen vallen samen tot één schrijfwijze elk.

    Opgelost

    • Een download heet naar het deck. De <title> van een print-, PDF-slides- of PNG-exportdocument is nu alleen de decktitel; wat bij jou op het oude achtervoegsel matchte, matcht niet meer.
    • Escape pelt één overlay per keer af en geeft de besturing netjes terug, in plaats van meer te sluiten dan je vroeg.
    • Gekopieerde slides houden hun nesting en krijgen verse instance-id’s.
    • Het meer-menu koppelt elk item één keer, en sluit voordat het handelt, zodat een menu-item niet twee keer kan afgaan.
    • “Toevoegen als tweede slide” zet de uitnodiging op plek twee.
    • De importknoppen voor markdown zeggen niet langer “Importeer JSON”.
    • Codeblokken krijgen op elk renderpad kleur, en de CSS-naad voor forks serveert custom/styles/ en forklettertypes.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.23.0 op GitHub.

  108. v1.22.0

    Onderhoudsrelease

    Het ingebouwde thema "Deckyard" heet voortaan "Amethyst", en nog maar één ingebouwd thema draagt het Deckyard-merkteken.

    Een kleine release met één hernoeming erin, het nakijken waard als je decks op het violette ingebouwde thema hebt staan.

    Het ingebouwde thema-id deckyard is nu amethyst, met het label “Amethyst”. Er is geen alias voor het oude id. Een deck dat is opgeslagen met "theme": "deckyard" laadt en rendert nog gewoon, in het standaardthema (brand, Forest), maar valt bij de volgende bewaring door de validatie tot je opnieuw een thema kiest. Eigen thema’s in custom/themes/ merken er niets van.

    • Amethyst draagt het neutrale placeholder-logo, net als de andere archetypethema’s. brand (Forest) is nu het enige ingebouwde thema met het Deckyard-merkteken, en zo hoort een archetype dat als vertrekpunt bedoeld is er ook uit te zien.
    • Het standaardthema wordt door de server bepaald, niet aan de clientkant gekozen. Het samenstelpad van de slidebibliotheek koos er eerder zelf een.

    Verwijderd

    • Twee ongedocumenteerde AI-wizard-endpoints zijn weg. POST /api/ai/wizard-v2 en /api/ai/wizard-v2/outline zijn verwijderd; het streaming-endpoint /api/ai/wizard-v2/stream is het ene pad en blijft zoals het was. Geen van beide stond in de OpenAPI-documentatie, dus dit valt alleen op als je ze rechtstreeks aanriep.

    Opgelost

    • Markdown rendert nu echt in MCP-previews en -exports. Het MCP-proces zette zijn sanitizer nooit op, dus wie een slide via de MCP-server previewde of exporteerde zag lijsten en opmaak als zichtbare <ul>-tekst. Dat is nu opgelost, en ontbreekt er ergens een sanitizer, dan staat er één waarschuwing op stderr in plaats van niets.
    • De follow-API antwoordt 404 op een onbekende presentatie en 503 op een onbereikbare store, waar allebei eerder een 400 was. Matchte je op 400, dan moet dat aangepast.
    • De gaten in de vertaling van de descriptortabellen zijn gevuld, en de dekkingscontrole ziet ze nu, zodat het volgende gat de build laat falen in plaats van als Engels in een Nederlandse interface mee te gaan.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.22.0 op GitHub.

  109. v1.21.0

    Feature-release

    Uit Notion geïmporteerde afbeeldingen verlopen niet meer, uitgaande webhooks kunnen ondertekend worden, en een datavraag heeft geen account meer nodig om af te ronden.

    Twee dingen hier repareren beloftes die maar half werden waargemaakt: een geïmporteerd deck waarvan de afbeeldingen een uur later stierven, en een webhook-ontvanger die geen manier had om een echte levering van een vervalste te onderscheiden.

    Draai bij deze update de migraties 075, 076 en 077. Zonder 076 start de slidebibliotheek niet goed, en zonder 077 raakt een ingestelde webhook-URL voor de slidebibliotheek zoek.

    Notion-afbeeldingen overleven de import

    • Afbeeldingen uit Notion worden in je eigen mediabibliotheek opnieuw gehost. Notion geeft ondertekende URL’s uit die na ongeveer een uur verlopen, en zonder geconfigureerde ImageKit bewaarde Deckyard die URL’s letterlijk, dus een geïmporteerd deck raakte kort na de import zijn beeld kwijt. Elke afbeelding wordt nu opgehaald en opgeslagen via je ingestelde mediaprovider, en het blok wijst naar de blijvende kopie. Lukt een losse afbeelding niet, dan blijft de originele URL staan in plaats van dat het beeld verdwijnt. Voor een instance met ImageKit verandert er niets.
    • Die ophaalacties zijn SSRF-beveiligd en houden een maximale grootte aan, want de import doet nu uitgaande verzoeken op een URL uit een document.

    Webhooks

    • Leveringen kunnen ondertekend worden. Zet webhooks.signingSecret en elke levering draagt x-sb-signature: sha256=<hmac-van-de-body> naast de bestaande x-sb-event-header. Zonder secret ontbreekt hij, dus er verandert niets tot je ervoor kiest. Er is een adminveld voor.
    • actor.id draagt het vaste gebruikers-id, niet het adres. Het adres blijft beschikbaar als actor.email, als contactgegeven en niet als identiteit. Ging jouw ontvanger uit van actor.id als adres, dan moet die aangepast worden.
    • Het event slide.added_to_team_library heet nu slide.added_to_organization_library, in de payload en in de x-sb-event-header. Er is geen alias, dus een ontvanger die op de oude tekst matcht herkent hem stilletjes niet meer.
    • De user-agent is Deckyard-Webhook/1, in plaats van presentation-system-webhook/1.

    Datavragen zonder account

    • De zelfbedieningsroutes voor eigen data zijn publiek, met een landingspagina en een blijvende tokenopslag erachter, zodat iemand een inzage- of wisverzoek kan afronden zonder te kunnen inloggen. In 1.20.0 begon de verificatiemail uit te gaan; dit is de andere helft.
    • leads.retentionDays staat in het instellingenscherm van de admin, in plaats van alleen in een configbestand.

    Voor API-clients

    • Publieke API v1 antwoordt met één foutenvelop. Elke route op het v1-oppervlak geeft nu dezelfde foutvorm terug.
    • Publiceren draait op één gedeelde kern, zodat het interne publicatiepad en het v1-endpoint niet uit elkaar kunnen lopen.
    • Het filterargument in MCP heet ownership, niet scope. Het geldt voor list_presentations en list_recent_comments, ook in het antwoord; de waarden blijven gelijk (owned, shared, all). Een oude aanroep valt stilletjes terug op de standaard in plaats van te falen.
    • De slidebibliotheek spreekt van een shelf. De API neemt shelf: 'personal' | 'organization', en de ZIP-entry bij een bulkexport heet slide-library/organization.json waar dat team.json was.

    Opgelost

    • Een lijst in twee kolommen stopt bij zes items wanneer een tussenkop samenvalt met titels van drie regels, in plaats van de slide uit te lopen.
    • Overzichten van de teambibliotheek komen voorbij een sluimerende limiet van 100 rijen, en de autorisatiecontrole erop is opgelost.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.21.0 op GitHub.

  110. v1.20.0

    Feature-release

    Functieschakelaars staan allemaal dezelfde kant op: `AI_ENABLED` in plaats van `DISABLE_AI`. De oude namen blijven tot november werken.

    Drie schakelaars waren als ontkenning gespeld, dus iets uitzetten betekende een variabele op true zetten, en een configuratiebestand lezen betekende een dubbele ontkenning ontrafelen. Ze staan nu in de aanzet-vorm, standaard aan.

    Gebruik je een van deze, plan dan een hernoeming vóór 2026-11-01.

    • DISABLE_AI wordt AI_ENABLED
    • DISABLE_UPLOADS wordt UPLOADS_ENABLED
    • DISABLE_IMAGE_LIBRARY wordt IMAGE_LIBRARY_ENABLED

    Alle drie staan standaard aan. De oude spellingen worden nog gehonoreerd, omgekeerd, tot de eerste release na 2026-11-01, en elke ingestelde oude naam drukt bij het opstarten een waarschuwing af met zijn vervanger en de verwijderdatum erin. Staan beide spellingen ingesteld, dan wint de nieuwe. docs/reference/feature-flags.md legt de regel vast, zodat een toekomstige schakelaar ook in de aanzet-vorm aankomt.

    AVG-zelfbediening levert nu echt

    • De verificatielink voor een datavraag wordt per e-mail verstuurd. Het endpoint maakte een token aan en bezorgde het nooit, dus het zei mensen “je ontvangt een verificatielink” terwijl er niets uitging; de zelfbediening voor inzage en wissing was in productie onbereikbaar, precies waar het juridisch telt. Een niet-geconfigureerde mailopzet antwoordt nu een eerlijke 501 in plaats van te doen alsof.

    Verwijderd

    • De verversmodus “bij bekijken” is weg. Hij stond in de instellingen van databronnen en was nooit gebouwd, dus hem kiezen deed niets.

    Opgelost

    • Schrijfacties van MCP-tools gaan langs de onderhoudspoort. Een instance in onderhoudsmodus was via MCP nog steeds beschrijfbaar.

    Beveiliging

    • De onbevoegde datasource:refreshed-uitzending is weg. Een ververs-event ging via SSE naar luisteraars die geen recht op die databron hadden.
    • Wijzigingen aan analytics-rapporten blijven bij hun eigen presentatie. Een rapportmutatie werd niet gecontroleerd tegen het deck waar hij bij hoorde.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.20.0 op GitHub.

  111. v1.19.0

    Feature-release

    Elke knop in een thema is nu een roltoken. De tokens per slidetype zijn weg, en dat is het lezen waard als je een eigen thema beheert.

    Een thema kon vroeger tot in losse slidetypes reiken: er waren tokens voor KPI-tegels, voor tabelvarianten, voor het icoonkaartraster, voor citaattekst. Daarmee kon een thema één slidetype stileren en niets zeggen over het volgende, dus een nieuw slidetype arriveerde ongestileerd en elk thema moest worden bijgewerkt om bij te blijven. Thema’s zetten nu rollen, en elk slidetype leidt zijn uiterlijk daaruit af.

    Beheer je een eigen thema, lees dan de lijst hieronder. Onbekende tokens in een bestaand thema zijn onschuldig (ze doen simpelweg niets), dus er breekt niets, maar een thema dat op een verwijderd token leunde rendert voortaan met de opmaak die uit de rollen volgt in plaats van met wat het vroeg.

    Wat er in de tokenwoordenlijst veranderde

    • De KPI-tokens zijn weg. --t-kpi-tile-{1..4}-* en --t-kpi-delta-* bestaan niet meer; tegels krijgen de neutrale standaard, en een gekleurde reeks komt uit --t-chart-*.
    • De tokens voor tabelvarianten zijn weg. --t-table-<variant>-* bestaat niet meer; tabelvlakken volgen --t-color-accent (met zijn contrast) en de mist- en verhoogde vlakken.
    • De tokens voor het icoonkaartraster zijn weg. --t-icon-card-grid-* bestaat niet meer; het icoonvlak volgt uit mist en accent (te overschrijven met --t-color-accent-soft), kaartlichamen lezen --t-color-surface-raised, en koptekst volgt de gradiënt- en op-vlakrollen.
    • De tokens voor citaat- en hoofdstuktekst zijn vervangen. --t-quote-text-color en --t-chapter-text-color worden --t-slide-bg-dark-text; --t-quote-author-color heet nu --t-color-accent-on-dark.
    • --t-list-item-title-letter-spacing is weg.
    • De oude aliassen worden niet meer uitgeschreven. --t-primary, --t-accent, --t-bg-dark en --t-brand-1/-2 zijn weg; de merkplekken --t-color-brand-{1..3} vullen zich uit brandColors.

    Opgelost

    • DELETE /api/leads/my-data komt bij de wisroutine uit in plaats van bij de rij die op id wordt aangesproken. Nam je AVG-wisverzoeken aan, dan landden die op de verkeerde plek.
    • Verse uitnodigingen staan niet meer als “verlopen” in de gebruikerslijst van de admin.
    • Een export in de wachtrij leest zijn type uit de naam van de taak, dus een PDF-taak komt niet in het verkeerde formaat terug.
    • De laatste afwijkende foutmeldingen gebruiken de canonieke envelop, zodat een API-client overal dezelfde foutvorm ziet.
    • Een mislukte sendEmail krijgt een type. Een verkeerde configuratie antwoordt 501 en een fout bovenstrooms blijft 502, zodat “wij kunnen geen mail versturen” en “de mailserver weigerde het” niet meer op elkaar lijken.
    • De ongebruikte transitieve afhankelijkheid image-size is uitgeschakeld, waarmee een ongepatcht pakket uit de boom verdwijnt.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.19.0 op GitHub.

  112. v1.18.0

    Feature-release

    Eén woord per betekenis: een deck heeft een zichtbaarheid, de huurder is een organisatie, en de API zegt dat ook. Toegang intrekken wordt nu gelogd en aan de betrokkene gemeld.

    Deckyard gebruikte het woord “scope” voor drie verschillende dingen en “workspace” voor twee. Deze release kiest één woord per betekenis en past de wire, de databasewaarden en de documentatie daarop aan. Gebruik je de API, dan wordt één veld hernoemd; de rest hier is gedrag.

    Gebruik je de publieke API, dan wordt scope voortaan visibility. De waarden zijn private en organization; workspace bestaat niet meer als waarde. De interne PATCH /api/presentations/:id/scope wordt /:id/visibility, en het webhook-event presentation.moved_to_workspace wordt presentation.moved_to_organization, met fromVisibility en toVisibility erin. “Workspace” blijft als woord in de interface staan; het is geen woord meer in de data.

    • Capaciteitenlijsten van API-sleutels heten permissions, precies wat het instellingenscherm er al van maakte.

    Toegang kwijtraken is nu zichtbaar

    • Het toegangslogboek is symmetrisch. Het legde toekenningen vast maar intrekkingen niet, dus een lijst met samenwerkers kon spoorloos veranderen. Intrekkingen en rechtenwijzigingen worden gelogd, en wie zijn toegang verliest krijgt bericht in plaats van het te ontdekken door te klikken.

    Voor API-clients

    • Tag-updates op de slidebibliotheek nemen alleen { tags: [...] }. De andere geaccepteerde vormen zijn weg; stuurde jouw client een kale array of een losse tekst, dan moet dat nu het object worden.
    • Eén JSON-ingang voor elke request body, wat ook betekent dat een body die geen object is overal op dezelfde manier geweigerd wordt in plaats van per route.

    Onder de motorkap

    • Deckversies, slidevergrendelingen en de live SSE-stroom hangen aan het gebruikers-id, in het verlengde van het identiteitswerk uit 1.16.0 en 1.17.0. De prullenbak en de slidebibliotheek lopen met hun autorisatie langs dezelfde identiteitscontrole.
    • Het deckschema gaat naar v6. Uitlijningssleutels per veld die niets meer deden zijn opgevouwen. De migratie draait bij het lezen van een deck en wordt bij de volgende bewaring vastgelegd, dus je hoeft niets te doen.

    Opgelost

    • Analytics houdt zich aan de bewaartermijn, en de dode analytics-tabellen zijn verwijderd.
    • Apparaatlabels werken in bootmodi zonder secret, door een vluchtige sleutel af te leiden in plaats van te falen.
    • De tussenkop van een vergelijkingsslide staat één stap boven de kolomtekst, zoals altijd de bedoeling was.
    • Een lijstslide meet zijn capaciteit opnieuw tegen de actuele maten, zodat items niet meer wegvallen of geperst worden na een maatwijziging.
    • Eén canonieke lijst met e-mailtemplatetypes, en een dood export-klaar-pad is weg.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.18.0 op GitHub.

  113. v1.17.0

    Feature-release

    Eigenaarschap wordt bepaald op het gebruikers-id in plaats van op het e-mailadres, anonieme kijkers kunnen hun eigen analytics-data wissen, en de analytics-API deelt geen identifiers meer uit die daar niet horen.

    Het identiteitswerk dat in 1.16.0 begon wordt hier echt: eigenaarschap, werkruimtetoegang en instellingen per gebruiker worden nu bepaald op het vaste gebruikers-id in plaats van op het adres waarmee iemand toevallig inlogt. Wijzig je adres en je houdt je decks.

    Er zitten twee privacyfixes in die het lezen waard zijn, allebei op het analytics-oppervlak, allebei hieronder.

    Identiteit is nu het gebruikers-id

    • Eigenaarschap van een deck vergelijkt gebruikers-id’s. De API draagt ownerId als identiteit en de client vergelijkt die, in plaats van adresteksten naast elkaar te leggen.
    • Een werkruimterecht wordt afgemeten aan de eigen organisatie van de handelende gebruiker, niet afgeleid.
    • Instellingen per gebruiker hangen aan het gebruikers-id, dus ze overleven een adreswijziging.
    • De migratie controleert en vult zichzelf aan, zodat een bestaande instance met alle stempels gevuld eindigt in plaats van halverwege omgezet. Na de upgrade bevestigt node scripts/verify-identity-migration.js dat hij op elke rij geland is.
    • Versiesnapshots dragen geen e-mailadressen van eigenaren meer, en een migratie wist ze ook uit de rijen die je al had.

    Analytics

    • Anonieme kijkers kunnen hun eigen data wissen. Wie een deck bekeek zonder account kan nu wissing van de eigen sessie vragen, door bezit van het sessietoken aan te tonen in plaats van een account nodig te hebben. Presenteer je voor publiek dat nooit inlogt, dan is dit het oppervlak dat een AVG-verzoek van zo iemand beantwoordt.
    • De schakelaar tussen interne en externe tracking is weg. analytics.enabled is de enige schakelaar; de tweede beloofde een onderscheid dat de data nooit droeg. Had je tracking uitstaan via die tweede schakelaar, dan moet je nu analytics.enabled uitzetten, anders begin je weer te verzamelen.
    • De sessielijst geeft het sessietoken niet meer terug. Het zat in het antwoord en niemand las het.
    • Een apparaatlabel per deck vervangt het ruwe apparaat-id. Het dashboard laat zien “dit is dezelfde bezoeker” zonder de identifier waarmee twee decks aan elkaar te knopen zouden zijn.

    Presenteren

    • Via de deelnamelink kunnen de sprekersnotities van de sessie bewerkt worden. Wie de deelnamelink heeft kan tijdens de sessie notities schrijven, en niet meer alleen lezen.

    Opgelost

    • Een mislukte uitnodiging voor een samenwerker antwoordt 500, niet 400. Een opslagfout werd gemeld alsof jij iets verkeerds had gestuurd.
    • DATABASE_URL wint van de losse DATABASE_*-variabelen in db:migrate, net als in de server zelf. Had je allebei ingesteld, dan draaiden migraties op een andere database dan de app.
    • Exports in de wachtrij laden hun thema goed, dus een export op de achtergrond krijgt dezelfde opmaak als een interactieve.
    • Een mislukte uitnodiging kijkt naar de foutcode, niet naar de tekst van de melding.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.17.0 op GitHub.

  114. v1.16.0

    Feature-release

    Mensen worden voortaan herkend aan een vast gebruikers-id in plaats van aan hun e-mailadres, en de laatste publieksdata verdwijnt van de schijf.

    Een stille release met één langlopend thema eronder: wie iemand is houdt op zijn e-mailadres te zijn. Deckyard gebruikte het adres als identiteit bij eigenaarschap, samenwerkersrijen en audit-stempels, wat betekende dat je adres wijzigen je identiteit wijzigde. Deze release zet het vaste gebruikers-id ernaast; de releases erna schakelen elk oppervlak erop over.

    Identiteit krijgt een vaste sleutel

    • Decks dragen een eigenaar, maker en laatste bewerker als gebruikers-id, naast de adressen die er al stonden. Voor jou verandert er nog niets; het lezen schakelt in 1.17.0 om.
    • Samenwerkersrijen dragen een gebruikers-id naast het adres.
    • Een eigendomsoverdracht wordt vastgelegd in plaats van het oude stempel te laten staan.

    De rest van de publieksdata gaat naar Postgres

    • Vragen, interacties en feedback zijn databaserijen. Nu 1.15.0 de bestandsopslag heeft verwijderd, sluit dit het laatste pad dat publieksinvoer naar schijf schreef.

    Opgelost

    • Samenwerkersrijen horen bij het deck, niet bij de sessie. De verkeerde afbakening kon een lijst met samenwerkers tonen die bij een andere context hoorde.
    • Een mislukte taalwissel zegt dat ook. De taal van een deck wisselen deed stilletjes niets als het misging; nu meldt hij de fout.

    Beveiliging

    • De publieke wachtwoordcontrole van een deellink heeft een snelheidslimiet. Een met wachtwoord beveiligde link kon worden aangevallen in het tempo dat het netwerk toestond. Publiceer je links met wachtwoord, dan is dit de reden om deze update te nemen.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.16.0 op GitHub.

  115. v1.15.0

    Feature-release

    PostgreSQL wordt het enige opslagsysteem. Een instance die zijn decks nog als JSON op schijf bewaart moet ze eerst importeren voordat hij start.

    Deckyard kon alles opslaan als JSON-bestanden in een datamap, met Postgres als optie. Die optie is nu de enige: de bestandsopslag is verwijderd, en elk deck, elke instelling, elke live sessie en elke e-mailtemplate staat in de database.

    Dit is de release waar je een plan voor nodig hebt voordat je update. Draait jouw instance nog op bestandsopslag, dan weigert hij na deze update te starten, in plaats van je een lege werkruimte voor te zetten naast data die hij niet meer kan lezen. De weg erdoorheen is één commando, en die staat hieronder.

    Importeren voordat je herstart

    De bootcheck telt de decks in je datamap. Vindt hij ze terwijl de database leeg is, dan stopt hij en drukt hij allebei de uitwegen af in plaats van te starten.

    • Draai npm run db:import. Die leest de oude datamap en schrijft hem naar Postgres. De bestandsdata wordt alleen gelezen, nooit verplaatst of verwijderd, dus de import kan opnieuw en de oude map blijft je terugvaloptie.
    • Maak een databasebackup en bewaar de datamap tot je een paar decks hebt geopend en hebt gezien dat ze kloppen.
    • STORAGE_MODE heeft nu één schrijfwijze per backend. postgresql was een stille alias voor postgres, en een onbekende waarde viel terug op bestandsopslag. Allebei zijn nu bootfouten, dus je kunt niet meer op een backend belanden waar je niet om vroeg.

    Postgres zit in de stack

    • De compose-stack bevat een Postgres-service, dus een verse installatie heeft geen aparte database-inrichting nodig. .env.example beschrijft het databaseblok als gewone configuratie in plaats van als iets waar je voor kiest.
    • De installer faalt meteen op een verouderde DATABASE_HOST in plaats van te starten en later stuk te gaan.

    Wat er naar de database is verhuisd

    Vier dingen die nog als JSON op schijf stonden zijn nu rijen, en dat is wat een deployment met meerdere instances of in containers laat werken:

    • Vragen, interacties en publieksfeedback.
    • Live sessies en volgcodes.
    • Instellingen van de instance, zodat een adminwijziging niet meer afhangt van een schrijfbaar configbestand.
    • E-mailtemplates.

    Ook de TTL-opruiming en het quotum van de sandbox draaien op Postgres. De compose-sandbox-stack is de ene uitzondering: die heeft geen databaseservice en leest deck-JSON nog van schijf, dus daar staat STORAGE_MODE=file expliciet vastgezet.

    Verder in deze release

    • De interface wordt in twaalf talen aangeboden, waarvan Nederlands en Engels de twee zijn die op volledigheid worden bewaakt; de andere tien zijn best-effort en vallen terug op Engels waar een tekst ontbreekt.
    • Beeldgebruik wordt in de database opgezocht, dus de beeldbibliotheek meldt een afbeelding niet langer als ongebruikt omdat hij op schijf zocht.
    • Zeven CSS-klassen van slidetypes worden niet meer uitgeschreven: team-cards-group-left, kpi-note, quote-author-text, poll-results-main, sfi-header, sfi-card-code, sfi-card-qr. Geen enkel ingebouwd thema gebruikte ze, dus de thema’s van Deckyard zelf merken er niets van. Beheer je een fork die op zo’n naam stileerde, verplaats die regels dan naar de klasse die op hetzelfde element overblijft.
    • De nummering blijft in 1.x. Er is kort een 2.0.0 voorbereid en weer teruggedraaid; de betahouding van Deckyard houdt breaking changes voorlopig op een minor, en daarom is een release als deze geen major.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.15.0 op GitHub.

  116. v1.14.0

    Beveiligingsrelease

    De laatste twee bibliotheken die de app bij een CDN ophaalde worden nu door je eigen instance geserveerd, en thema's krijgen een eerste set roltokens.

    De vorige release haalde DOMPurify van een CDN af. Deze maakt dat werk af voor de twee overgebleven third-party scripts, zodat een instance achter een firewall of op een afgesloten netwerk niet langer de server van iemand anders nodig heeft om een codeblok te kleuren of een formule te zetten.

    Syntax highlighting en formules komen van je eigen instance

    Prism (code-highlighting) en KaTeX (wiskundige notatie) werden bij het laden van de pagina van een publiek CDN gehaald. Ze zitten nu in de repository zelf en worden door je eigen instance geserveerd, lazy geladen door de app-shell in plaats van bij elke pagina.

    • Een offline of CDN-geblokkeerde installatie rendert code en formules gewoon goed, waar dat eerder terugviel op ongestileerde tekst.
    • Ze laden alleen als een deck ze nodig heeft. Voor een deck zonder codeblok of formule wordt er niets opgehaald.

    Thema’s krijgen roltokens

    De eerste fase van een langer traject op het themasysteem: slides gaan tokens lezen die een rol benoemen (een vlak, een accent, tekst op een donker vlak) in plaats van een slidetype. Visueel verandert er niets en geen enkel bestaand thema breekt; dit is het voorwerk voor de consolidatie die in 1.19.0 landt.

    • docs/reference/slide-roles.md beschrijft de woordenlijst, als je eigen thema’s schrijft en wilt zien waar dit heen gaat.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.14.0 op GitHub.

  117. v1.13.0

    Beveiligingsrelease

    Deckyard vraagt zijn sanitizer niet meer aan een CDN, de meegeleverde lettertypes blijken al die tijd de verkeerde te zijn geweest, en er is nu een beeldbron zonder licentie eraan.

    Twee van de drie dingen in deze release zijn hetzelfde ding: een instance hoort de server van iemand anders niet nodig te hebben om goed te werken. De sanitizer kwam van een CDN, en de lettertypes die zelf gehost heetten te zijn bleken bij elke installatie opnieuw bij Google opgehaald te worden, zonder pin, en met de verkeerde bytes.

    Dit is een reden om te updaten. Blokkeert jouw instance third-party requests, of zit hij achter een firewall die cdn.jsdelivr.net stilletjes niet ophaalde, dan laadde de sanitizer van de editor helemaal niet. En los daarvan: vrijwel zeker heeft elk deck tot nu toe in een fallback-letter gerenderd in plaats van in de letter die het thema noemt. Allebei hieronder.

    De sanitizer wordt door je eigen instance geserveerd

    De app-shell laadde DOMPurify van cdn.jsdelivr.net, waarmee een derde partij een afhankelijkheid werd van twee dingen tegelijk: de beveiliging, en of de app überhaupt startte. Hij komt nu uit de npm-kopie die de server-side sanitizer al gebruikte, vastgezet met de integrity-hash uit package-lock.json.

    • Een air-gapped of CDN-geblokkeerde installatie krijgt een werkende sanitizer, waar hij eerder kreeg wat de browser deed als het script niet laadde.
    • Browser en server draaien nu dezelfde DOMPurify. De CDN-tag hing op 3.2.2 terwijl de server al op 3.4.12 zat.

    De lettertypes waren de verkeerde bytes

    Deze is het lezen waard, ook al staat hij als fix in de lijst. Google levert elke lettertypefamilie opgesplitst in subsets per schrift, en verwacht dat de browser er via unicode-range tussen kiest. De installer nam de @font-face die als eerste terugkwam, en dat was cyrillic-ext. Elke gecureerde letter op schijf bevatte dus geen enkele Latijnse glief, en alles wat erom vroeg, slides, exports, de themakiezer en de interface van de app zelf, rendeerde stilletjes in een fallback-letter. Alle vier de Inter-gewichten waren byte-identiek aan hetzelfde Cyrillische bestand.

    • Elk gewicht wordt nu geleverd als latin plus latin-ext, met een echte unicode-range op elke gegenereerde @font-face. Je decks gaan renderen in de letter die het thema daadwerkelijk noemt, wat voor de meeste installaties een zichtbare verandering is.
    • De download is vastgezet. scripts/google-fonts.lock.json legt van elk bestand de exacte URL, SHA-256 en bytegrootte vast, en de installer weigert wat daar niet mee overeenkomt. Tot nu toe was de inhoud van assets/fonts/google/ een functie van Googles releaseschema in plaats van van de versie die jij installeerde.
    • Exports verliezen ruwweg twee derde van hun lettertypegewicht. De meeste gecureerde families zijn variabele fonts waarbij elk gewicht naar hetzelfde bestand wijst, maar elk gewicht werd apart gedeclareerd, en een export base64-inlinet elke regel. Het standaardthema verscheepte zo’n 930 KB aan fonts waar ongeveer 253 KB uniek is, in elk standalone HTML-bestand en elke PDF- of PNG-render.
    • Twee ingebouwde thema’s exporteerden een fallback-letter waar hun CSS om een gewicht vroeg dat het thema niet noemde: Corporate miste Archivo 500, Midnight miste JetBrains Mono 500 en 700. Alle zes de thema’s zijn opnieuw gegenereerd, en een test faalt voortaan als een lijst weer afdrijft.
    • Namen van lettertypefamilies worden nu goed ge-escaped richting CSS. Een naam die op een backslash eindigt kon het sluitende aanhalingsteken van zijn eigen declaratie ontsnappen, en familienamen komen daar binnen via geüploade fonts en custom thema-JSON; het was dus bereikbare invoer en niet alleen een lint. Vijf plekken zetten namen en URL’s in CSS-strings, en op drie daarvan gebeurde helemaal geen escaping.

    Een beeldbron zonder licentie eraan

    Er is een derde beeldbron in de kiezer: 30 abstracte gradiënten, gerenderd uit de paletten van de zes ingebouwde thema’s. Geen API-sleutel, geen naamsvermelding, geen rate limit, geen extern verzoek.

    De reden dat hij bestaat is de licentievraag, niet de esthetiek. Stockbeeld komt van een API van een derde partij met voorwaarden eraan, en dat is ongemakkelijk op een publieke of gasttoegankelijke instance waar uploads uitstaan en stock de enige bron is die iemand heeft.

    • De schakelaar is stockMedia.bundled.enabled, en staat standaard uit. Er is een adminvinkje voor. Op een instance die hem laat staan verandert er niets.
    • Een gekozen gradiënt overleeft de export. De bestanden staan onder assets/gradients/, en dat is het voorvoegsel dat de exporteur inlinet, dus het werkt in PDF- en PNG-exports, gepubliceerde pagina’s en embeds zonder aparte behandeling.

    Het aantal ingebouwde slidetypes blijft 34.

    De volledige lijst op commit-niveau staat bij de release 1.13.0 op GitHub.

  118. v1.12.1

    Onderhoudsrelease

    Twee afgeschreven slidetypes verlaten het register, een pagina zonder video laadt geen videospeler meer, en links blijven leesbaar op donkere themavarianten.

    Een kleine release op dezelfde dag als 1.12.0, met één opruiming die het lezen waard is: de twee slidetypes die al een tijd waren afgeschreven, zijn nu echt weg. Er breekt niets, en er is niets te draaien.

    Twee slidetypes met pensioen

    content-columns-slide en card-stack-slide zijn uit de ingebouwde set. Het aantal ingebouwde slidetypes gaat van 36 naar 34.

    • Opgeslagen decks breken niet. Een slide van een van beide types rendert als gearchiveerde placeholder met alle inhoud nog zichtbaar, dus er gaat niets verloren en er crasht niets.
    • Card stack heeft een opvolger. De placeholder noemt icon-card-grid als doel om naar te herbouwen; dat type neemt dezelfde items[]-vorm, en scripts/migrate-slides.js doet de conversie voor je als je het in bulk wilt.
    • Content columns heeft geen opvolger. Bouw die slides opnieuw met het type dat past; er is geen automatische conversie, omdat er geen type is dat hetzelfde betekent.

    Een pagina zonder video doet nul third-party requests

    Bunny’s player.js werd op elke pagina van de live app geladen, of er nu een video in het deck zat of niet. Hij laadt nu lazy, en alleen als er daadwerkelijk een videoslide is. Voor een deck zonder video zijn dat nul third-party requests, wat zowel privacywinst als een snellere eerste laadbeurt is.

    Een themavariant met een eigen slide-achtergrond erfde de basiskleur voor links, die tegen die achtergrond kon wegvallen. De linkkleur wordt nu per variant afgeleid, dus een omgekeerde of donkere variant krijgt een leesbare link zonder handmatige override.

    Bij het upgraden

    • Afgeschreven slidetypes verwijderen in een 1.x-release is de bedoelde vorm. Deckyard blijft de hele beta op 1.x, dus zo’n opruiming wordt niet bewaard voor een major-versie.
    • Niets te draaien. Het migratiescript is optioneel en bestaat alleen voor wie zijn card stacks liever omzet dan als placeholder laat staan.

    De volledige lijst op commit-niveau staat bij de release 1.12.1 op GitHub.

  119. v1.12.0

    Feature-release

    De slide-editor is herbouwd op één generieke motor, dus elk type bewerkt hetzelfde, en `?lang=` wordt de enige manier waarop een URL een taal aanwijst.

    Bijna elk handgebouwd slideformulier in de editor is weg, vervangen door één editor die de declaratie van elk type leest. Je merkt het als consistentie eerder dan als een nieuwe functie: items toevoegen, verwijderen en herordenen werkt nu op elk slidetype identiek, omdat het letterlijk dezelfde code is.

    Deel je links met ?locale= erin, dan moeten die ?lang= worden. De oude alias is in deze release verwijderd; zie de URL-sectie hieronder.

    De editor is herbouwd

    De formulieren per type waren het oudste deel van de editor en het minst consistent: zeven verschillende collectieformulieren, elk met een eigen idee van hoe een toevoegknop eruitziet.

    • Eén generieke collectie-editor vervangt alle zeven. Lijsten, kaarten, matrix en de rest voegen toe, verwijderen en herordenen nu op dezelfde manier.
    • Grafieken en tabellen worden een gesloten vocabulaire per veld. Elk veld is een gedeclareerde control in plaats van een eigen formulier, en daarom gedragen ze zich nu als de rest van de editor.
    • De afbeeldingsformulieren werden ook declaraties, die één gedeelde elementkaart gebruiken.
    • Nieuwe items krijgen standaardwaarden in de taal van het deck. Item-defaults worden per deck-taal opgelost, dus een rij toevoegen aan een Nederlands deck zet er geen Engelse voorbeeldtekst meer in.
    • De slidelijst leest de labelField van elk type, zodat het label in de linkerlijst het veld is dat de slide daadwerkelijk herkenbaar maakt.

    Een URL die een taal noemt, wordt gevolgd

    • ?lang= is nu de enige URL-parameter voor de interfacetaal. De alias ?locale= is verwijderd. Binnen de app gebruikte niets hem, maar een link die je iemand hebt gestuurd misschien wel: die links moeten worden bijgewerkt, anders openen ze in de opgeslagen taal van de ontvanger in plaats van de taal die jij bedoelde.
    • ?lang= gaat boven de opgeslagen interfacetaal voor die sessie, dus een link die een taal noemt opent daar ook in, ook bij iemand die normaal in een andere taal werkt.

    Opgelost

    • Quoteslides springen niet meer terwijl je typt. De editor-canvas herschikte zich zodra het tekstveld focus kreeg, waardoor de tekst onder je cursor wegliep terwijl je erin klikte. Een gedelegeerde control op dezelfde slide zag er ook niet langer kapot uit.

    Voor wie zelf host

    • De retentie-opruimingen staan nu echt ingepland. Alle drie draaiden alleen als iets ze aanriep, en dat deed niets. Ze hangen nu in een dagelijkse job, die ACTIVITY_RETENTION_DAYS respecteert (standaard 180). Draai je je instance al een tijd, verwacht dan dat activiteitsdata ouder dan het retentievenster verdwijnt bij de eerste nachtelijke run na het upgraden; dat is wat de instelling altijd al hoorde te doen.

    Het aantal ingebouwde slidetypes blijft 36.

    De volledige lijst op commit-niveau staat bij de release 1.12.0 op GitHub.

  120. v1.11.0

    Feature-release

    Een slidetype heeft nu precies één schrijfwijze op de lijn, de schrijf-API weigert types die hij niet kent, en de PDF-export stopt met bestanden maken die niemand wilde versturen.

    Deze release beslecht iets waar het formaat vaag over was: hoe het type van een slide eigenlijk heet. Tot nu toe kon hetzelfde type je in twee schrijfwijzen bereiken, afhankelijk van welke deur het uit kwam, en kon een write elke willekeurige string in dat veld zetten. Allebei zijn hier opgelost. Daaromheen werden organisaties bruikbaar voor de mensen die erin zitten, en kreeg de PDF-export een ronde reparaties.

    Leest er iets dat jij draait slides[].type uit een export of een API-antwoord, lees dan de eerste sectie voordat je update. Opgeslagen decks migreren zichzelf, dus een instance hoeft niets; een integratie die op de oude schrijfwijze matcht wel.

    Eén schrijfwijze voor het type van een slide

    Export en elke lees-API schrijven nu de canonieke reverse-DNS-id, eu.deckyard.slide.title, en niets anders. Daarvoor kon ook de kale registersleutel op de lijn verschijnen, dus moest een consument beide schrijfwijzen kennen en raden waar hij naar keek.

    • Wat de kale sleutel las, moet om. Er is nu één schrijfwijze, en dat is de reverse-DNS-vorm.
    • Het slideTypes-manifest is uit de deck-envelope. Het beschreef de types die in het deck voorkwamen, werd door niets gelezen, en herhaalde een feit dat al op elke slide stond.

    De schrijf-API valideert het slidetype

    Een onbekend slides[].type is nu een 400 op elk schrijfpad. Op Postgres-installaties glipte voorheen elke string er stilletjes doorheen, waardoor een typefout in een integratie een deck opleverde vol slides die nooit konden renderen, zonder dat iets dat meldde tot iemand het opende.

    Schrijf je decks via de API, dan mislukt een onbekend type nu op het moment van schrijven in plaats van op het moment van lezen.

    Opgeslagen decks migreren vanzelf naar schema v4

    Decks die al op schijf staan met een oude typeschrijfwijze worden bij de eerstvolgende read of write naar de canonieke vorm gevouwen. Er is geen script om te draaien en geen downtime; een beheerder hoeft hier niets voor te doen.

    Organisaties: uitnodigen, en een profielscherm

    1.10.0 gaf multi-organisatie-installaties hun eerste schermen en liet twee voor de hand liggende gaten open. Die zijn hier gevuld.

    • Mensen uitnodigen in een organisatie vanuit de interface, met terugkoppeling over welke uitnodigingen er daadwerkelijk uit zijn gegaan.
    • Leden komen bij de ledenlijst, niet alleen admins, zodat een gewoon lid kan zien wie er verder in de organisatie zit.
    • Een organisatieprofiel-scherm, inclusief verwijderen voor de eigenaar.
    • Het beheren van de organisatie waar je op dat moment in zit gedraagt zich correct, wat het niet altijd deed als je bij meerdere hoorde.

    De PDF-export krijgt een ronde reparaties

    Vijf verschillende manieren waarop een PDF verkeerd kon uitpakken, allemaal verholpen:

    • Afbeeldingen worden gecapt op hun weergavegrootte in plaats van hun bronresolutie, wat het grootste deel verklaart van waarom geëxporteerde PDF’s zo groot waren.
    • Gradiënt-achtergronden worden gerasterd, en gradiënt-pseudo-elementlagen ook, zodat een verloop niet meer verdwijnt of gaat banden in de PDF.
    • Blurred shadows belanden niet meer als luminosity-masks in de PDF, wat een zachte schaduw in een grijze rechthoek veranderde.
    • Het slidelettertype is verankerd aan het thema, zodat het interfacelettertype van de app niet meer in het geëxporteerde bestand lekt.
    • Lokale url()-assets worden ge-inlined, en een afbeelding die niet op te halen is wordt leeggelaten in plaats van als kapot vakje achtergelaten.

    Nederlandse veldlabels voor acht slidetypes

    Vergelijking, tijdlijn, aftelklok, custom HTML, embed, lead capture, matrix en proces hadden Engelse veldlabels binnen een Nederlandse interface. Die zijn vertaald, dus een Nederlandse bewerksessie wisselt niet meer halverwege het formulier van taal.

    Voor wie zelf bouwt

    Het spec-werk van deze cyclus is zichtbaar in de referentiedocumentatie: het gepubliceerde JSON Schema is open en de structure-facet is normatief, type-id’s zijn reverse-DNS met -slide eraf, en de catalogus draagt nu drie tiers plus een fallback-facet die zegt wat een reader doet met een type dat hij nooit eerder zag.

    Het aantal ingebouwde slidetypes blijft 36.

    Bij het upgraden

    • Een breaking change in een minor-versie is de bedoelde vorm. Deckyard blijft de hele beta op 1.x; 2.0.0 is gereserveerd voor het verlaten van de beta, niet voor een opruiming die toevallig iets breekt. De ene-schrijfwijze-wijziging en de strengere schrijfvalidatie zijn precies zo’n opruiming.
    • Niets te draaien. Opgeslagen decks migreren bij gebruik; het werk zit in je integraties, als je die hebt.

    De volledige lijst op commit-niveau staat bij de release 1.11.0 op GitHub.

  121. v1.10.0

    Feature-release

    Organisaties krijgen een echte interface, een geëxporteerd deck verliest ongeveer de helft van zijn gewicht, en één slidetype verdwijnt - met de hernoeming die bij het upgraden vanzelf gebeurt.

    De kop van deze release staat niet op een slide: een installatie die meer dan één organisatie draait, heeft er eindelijk een interface voor. Daaromheen werden geëxporteerde decks fors lichter, en verdween een slidetype dat altijd al alleen een tweede naam voor een ander type was.

    Draai je op de file-store, dan heeft de upgrade één handmatige stap. Opgeslagen decks worden automatisch hernoemd door databasemigratie 056, maar een file-store-installatie draait eenmalig node scripts/migrate-lijstje-slide.js. Verderop staat het precies.

    Organisaties krijgen een interface

    Multi-organisatie-installaties hadden het datamodel al een tijd, en geen enkele manier om het te zien. Deze release voegt de schermen toe.

    • Een organisatieschakelaar in het gebruikersmenu, zodat je ziet in welke organisatie je werkt en ertussen kunt wisselen.
    • Adminschermen volgen nu je rol binnen de actieve organisatie, niet meer de instance-brede adminvlag. Wie admin is in organisatie A en gewoon lid in B, ziet in B geen adminschermen meer.
    • De Users-tab wordt in multi-org de ledenlijst van de actieve organisatie, en is nu ook een plek waar je iets doet: een rol wijzigen, iemand verwijderen, zelf vertrekken, eigendom overdragen. De lijst heeft paging, dus een grote organisatie blijft werkbaar.
    • Onderweg zijn verschillende rechtencontroles rond eigendom en organisatie-instellingen aangescherpt.

    Wat er nog niet is, dus reken er niet op: uitnodigen vanuit de interface, en het organisatieprofiel-scherm. Multi-organisatie blijft in ontwikkeling.

    Eén slidetype minder, en het hernoemen gebeurt voor je

    lijstje-slide is met pensioen. Het was een tweede naam voor list-slide en nooit een tweede type, waardoor dezelfde slide onder twee namen opgeslagen kon zijn, afhankelijk van hoe hij was gemaakt.

    • Opgeslagen decks worden automatisch hernoemd bij het upgraden, door databasemigratie 056.
    • File-store-installaties draaien eenmalig node scripts/migrate-lijstje-slide.js na de upgrade.
    • Wat er toch nog doorheen glipt, rendert als gearchiveerde slide die naar list-slide wijst, niet als een kapotte slide.

    Ook split-partner-title-slide verlaat in deze release het register. Het was al een paar versies gearchiveerd en dus niet meer te kiezen bij het bouwen van een deck; slides die het type nog dragen, vallen terug op een gearchiveerde slide. Samen brengt dat het aantal ingebouwde slidetypes van 38 naar 36.

    Een geëxporteerd deck sleept de editor niet meer mee

    Een standalone HTML-export verscheepte de volledige stylesheet van de editor: modals, inspectors, de slidetype-kiezer, instellingen, waar een geëxporteerd deck allemaal niets mee kan. De export verscheept nu alleen viewer-CSS. Dat scheelt ruwweg 92% op de stylesheet in het bestand, wat bij een echt deck neerkomt op ongeveer de helft van het totale gewicht.

    Visueel verandert er niets aan de export, en ?ui=min klapt de chrome nog steeds op dezelfde manier weg.

    Een groen-messing standaardthema

    Er is een nieuw ingebouwd thema, Forest: bosgroen met messing, warm papier en salie als vlakken, en een grafiekreeks die afwisselt in tint én helderheid, zodat twee categorieën naast elkaar meer verschillen dan alleen van kleur. Het is nu het standaardthema.

    Bestaande decks veranderen niet. Een deck slaat zijn thema-id op, dus alleen nieuwe decks en decks die expliciet op default staan verhuizen. Het paarse deckyard-thema houdt zijn id en zijn naam; het is nu een van de zes stijlen in plaats van degene die iedereen erft.

    Kleinere wijzigingen

    • Videoslides: de kijklink die in exports getoond wordt, stel je zelf in. Een video speelt niet af in een PDF, dus toont de export een link; waar die heen wijst mag je nu zeggen.
    • KPI-tegels halen hun kleuren uit het thema via tokens, in plaats van ze zelf mee te dragen.
    • De poster van een videoslide wordt nu gerenderd in de PDF- en PNG-placeholders.
    • AI-suggesties in reacties worden herkend aan de effectieve auteur, zodat een suggestie die namens iemand is gedaan het juiste label krijgt.

    Voor wie zelf host

    • Onderhoudsmodus voor deploys. De instance tijdens een deploy in onderhoud zetten betekent dat een opslag die midden in de deploy landt zichtbaar mislukt in plaats van stilletjes; dat is het verschil tussen opnieuw proberen en werk kwijt zijn.
    • Een gedeeltelijke write wist geen deck-kolommen meer. Een deel van een deck wegschrijven kon velden leegmaken die er niet bij hoorden.
    • Het gepubliceerde JSON Schema draagt geen legacy-velden meer, zodat een tweede implementatie die ertegen valideert niet wordt opgedragen velden te ondersteunen die Deckyard heeft laten vallen.
    • De editor werd rustiger. Deck-thumbnails worden gerenderd bij het opslaan in plaats van bij het kijken, en de slidelijst bouwt zichzelf niet meer opnieuw op bij elke lock- of reactie-gebeurtenis.

    De volledige lijst op commit-niveau staat bij de release 1.10.0 op GitHub.

  122. v1.9.0

    Feature-release

    Deck-thumbnails worden niet meer bij elke bewerking een grijs vlak, een tabel kan één kleur over zijn hele bovenste rij dragen, en AI-verfijnen accepteert de nieuwe vorm van tekstblokken.

    De tweede release van dezelfde dag, na 1.8.0, en de reden om te updaten staat bovenaan: het deckoverzicht flikkert niet meer terug naar grijs zodra je een deck opent.

    Thumbnails laden niet meer opnieuw na elke bewerking

    De kaart van een deck op het startscherm laat een plaatje van de eerste slide zien. Dat plaatje werd gecachet op het revisienummer van het deck, en dat verandert bij elke opslag - dus slide negen bewerken, of een deck alleen maar openen en weer sluiten, gooide het plaatje weg. En een weggegooid plaatje kost ongeveer tien seconden flikkerende placeholder voordat de kaart weer gevuld is.

    De cache gaat nu op waar het plaatje daadwerkelijk uit bestaat: slide 1 en het opgeloste thema. Een bewerking elders in het deck maakt dus niets meer ongeldig. Terwijl een nieuw plaatje wordt gerenderd, wordt het vorige geserveerd, zodat een kaart nooit leeg is puur omdat slide 1 één bewerking achterloopt.

    Eén kleur over de bovenste rij van een tabel

    De cel linksboven in een tabel nam altijd de kleur van de labelkolom, dus een soft-tabel laat een licht getinte hoek zien die net losstaat van de koprij. Dat is een prima look, en nu is het een keuze: een nieuwe instelling Top-left cell bepaalt of de hoek bij de labelkolom hoort (zoals eerst) of bij de koprij, zodat de hele bovenste rij als één band leest.

    Hij combineert met elke tabelstijl in plaats van een vierde stijl te zijn, dus je bestaande tabel houdt de stijl die hij heeft. Het verschil is zichtbaar bij soft; bij plain en panel verandert er niets, omdat de koprij en de eerste kolom daar al dezelfde kleur hebben.

    AI-verfijnen accepteert tekstblokken met vier rijen

    Sinds tekstblokken een array werden (rows[]) eiste het schema achter AI-verfijnen nog steeds de oudere genummerde velden, dus wees het elke array-vormige tekstblokken-slide af - ook verse, en elke slide die de vierde rij uit 1.8.0 gebruikt. Verfijnen valideert nu de array-vorm, met de genummerde velden optioneel en ongemoeid doorgegeven.

    Voor wie zelf host

    • server/data/deck-thumbs/ wordt opgeruimd. De map groeide met één bestand per bewerking aan een eerste slide en er ruimde nooit iets op. Oudere rasters van een deck worden nu verwijderd zodra het verse binnen is.
    • Een 500 in de log wanneer twee mensen dezelfde slide openden is weg. Het claimen van een slidelock is nu atomair; de editor ving die botsing altijd al stil op, dus dit was nooit zichtbaar in de interface, alleen in de serverlog.

    De volledige lijst op commit-niveau staat bij de release 1.9.0 op GitHub.

  123. v1.8.0

    Feature-release

    Een lijstslide houdt de tekstgrootte die je koos en vult de slide, tekstblokken mogen een vierde rij, en quote-slides typen zichzelf niet meer uit.

    Drie wijzigingen aan hoe slides eruitzien terwijl je ze leest, en geen ervan vraagt iets van je. Bestaande decks worden niet gemigreerd en er breekt niets; twee van de drie zorgen er simpelweg voor dat slides die je al hebt eruitzien zoals je ze bedoelde.

    Een lijstslide houdt de grootte die je koos

    Tekstgrootte “Large” kiezen op een lijst van zeven korte bullets deed niets: de slide kwam er op de standaardgrootte uit, in twee kolommen, met de onderste helft leeg. Twee losse oorzaken, allebei nu verholpen.

    • Een expliciet gekozen tekstgrootte wint. Vanaf zeven items werd die grootte weggegooid, in de veronderstelling dat de lijst nog één kolom was. Bij zeven items zijn het er twee, waar ongeveer twee keer zoveel tekst in past. Grootte en kolomaantal worden nu samen bepaald, tegen een opgemeten capaciteitstabel. Het enige geval dat nog terugschakelt - een lijst die zo lang en zo woordrijk is dat hij over twee kolommen heen loopt - zegt dat ook, in de inspector onder “Text size”, in plaats van stilletjes niets zichtbaars te doen.
    • De rijen benutten de overgebleven hoogte. Ze stapelden zich tegen de bovenkant van het lijstvak en lieten de rest van de slide leeg. Ze groeien er nu in mee, zodat de scheidingslijnen gelijkmatig over de slide verdeeld staan in plaats van samen te dringen in de bovenste helft.

    Nagemeten over 1512 combinaties van aantal items, titellengte, tekstlengte, subkop, kolommen en tekstgrootte: er loopt niets over, 628 ervan zijn voller, en geen enkele is leger.

    Decks die uit markdown zijn geïmporteerd profiteren mee. lijstje-slide, dat de importer nog steeds uitschrijft, was een volledige kopie van de definitie van list-slide die naar een veel oudere lay-out was afgedwaald; het is nu een echte alias, dus dezelfde inhoud rendert allebei de kanten op hetzelfde.

    Tekstblokken mogen een vierde rij

    Het maximum op een tekstblokken-slide gaat van drie rijen naar vier. Voor een slide met drie of minder verandert er niets - die renderen byte voor byte hetzelfde - en bij vier rijen wordt de lay-out een tandje strakker, zodat die extra rij past zonder over de titel heen te lopen.

    De vierde rij bestaat alleen in de canonieke rows[]-vorm, en dat is wat de editor schrijft. De oudere genummerde velden (row1, row2, row3) blijven bewust op drie staan, zodat handgeschreven of geïmporteerde inhoud zijn betekenis houdt.

    Quote-slides typen zichzelf niet meer uit

    Een quote-slide typte zijn citaat teken voor teken uit, en deed dat ongeacht de instelling “Builds” van het deck: builds uitzetten bereikte dit ene effect nooit. Hij schokte bovendien, omdat het quote-blok de hele groep centreert - citaat, naamregel en portretten - zodat het blok verschoof terwijl de tekst groeide.

    Het effect is weggehaald in plaats van bijgesteld; het kan later netjes terugkomen. De typemachine per bullet is een ander effect en werkt gewoon door: de onthulstijl “Typemachine” in de deck-instellingen is ongemoeid gelaten.

    De volledige lijst op commit-niveau staat bij de release 1.8.0 op GitHub.

  124. v1.7.1

    Onderhoudsrelease

    Eén fix: de stappen op een horizontale processlide staan weer op één bovenrand.

    Eén fix, op dezelfde dag uitgebracht als 1.7.0. Verder is er niets veranderd en hoef je niets te doen behalve updaten. De reden om überhaupt op 1.7.x te zitten staat in 1.7.0, waar PPTX-export stopte met stil kapot zijn na een PDF-import.

    Processlides staan niet meer scheef

    Op een horizontale processlide werd elke stap verticaal gecentreerd tegen de hoogste, dus een stap met een kortere beschrijving zakte als geheel omlaag: nummer, titel en al. Beschrijvingen zijn zelden even lang, dus de rij stond meestal een paar pixels scheef, op een manier die lastig te benoemen en makkelijk te zien was.

    De stappen delen nu één bovenrand, terwijl de groep als geheel gecentreerd blijft in de slide, zodat een deck dat er al goed uitzag niet ineens omhoog schuift. Ook nagemeten over meerdere rijen, bij zes stappen.

    Bestaande decks zien er na de update simpelweg beter uit.

    De volledige lijst op commit-niveau staat bij de release 1.7.1 op GitHub.

  125. v1.7.0

    Feature-release

    De veldenlijst die een agent krijgt komt nu uit de code die hem definieert, PPTX-export gaat niet meer stuk na een PDF-import, en het herkenningsteken van het formaat draagt de productnaam.

    Drie wijzigingen: een die repareert wat een AI in een slide schrijft, een die een bestand repareert waarvan bleek dat je het niet kon vertrouwen, en een hernoeming die niets van je vraagt.

    Gebruik je PPTX-export en bestandsimport op dezelfde instance, dan is dit een reden om nu te updaten. Op 1.6.0 en ouder leverde een PowerPoint-export na een PDF-import een deck op met onzin waar de slides hadden moeten staan, en zonder enige foutmelding. Hieronder de details.

    De catalogus die agents lezen wordt gegenereerd, niet bijgehouden

    Een slidetype declareert zijn velden één keer, in de registry. De lijst die een model via MCP kreeg was een tweede kopie daarvan, met de hand bijgehouden, en die was op vijf punten afgedwaald. Twee daarvan waren zichtbaar kapot:

    • video-slide kreeg een veldnaam aangeboden die niet bestaat. Agents kregen te horen dat ze videoUrl moesten vullen; het type leest source. Elke AI-geschreven videoslide viel dus stil terug op de demovideo.
    • payoff-slide kreeg een tagline aangeboden die het type helemaal niet leest.

    Die catalogus komt nu uit de registry, dus dit soort fout kan niet opnieuw ontstaan. Dezelfde wijziging vertelt agents ook over velden die een auteur allang met de hand kon invullen, maar die de catalogus nooit noemde.

    PPTX-export was stil kapot na een PDF-import

    Allebei de exports renderen via headless Chrome, en zodra er in hetzelfde serverproces een PDF-import was gedraaid, gaf Chrome een ander soort bytes terug. De PPTX-bouwer nam die voor lief, dus het bestand dat eruit kwam had onzin waar de slides hadden moeten staan, zonder ergens in de keten een foutmelding.

    Een herstart van de server hielp, en dat is precies wat een bug als deze laat overleven: het lijkt een toevalstreffer, en de volgende export gaat goed. Het is gefixt, en er staat nu een rooktest die een echte browser start, dus een stille regressie van deze vorm valt voortaan om in CI in plaats van in iemands deck.

    Het herkenningsteken van het formaat zegt deckyard.deck

    Het veld format in een draagbaar deck, en het mediatype van een .deck-pakket, zeiden slidecreator - een tijdelijke naam uit december 2025, geschreven voordat dit product zijn naam had. Ze zeggen nu deckyard.deck en application/vnd.deckyard.deck.

    Je hoeft niets te doen en er breekt niets. De oude waarden worden bij het lezen blijvend geaccepteerd, dus een deck dat door een oudere versie is geëxporteerd gaat gewoon open. De bestandsextensie verandert ook niet: een pakket downloadt nog steeds als <titel>.deck. Het enige dat aandacht verdient is eigen tooling die op het format-veld matcht; die moet beide waarden accepteren.

    De formaatspecificatie is meegegaan en noemt ze allebei.

    De volledige lijst op commit-niveau staat bij de release 1.7.0 op GitHub.

  126. v1.6.0

    Feature-release

    Een gepubliceerd deck vraagt niet langer dingen op die het niet gebruikt, en een ingesloten deck kan de presentatiebalken eromheen laten vallen.

    Twee wijzigingen, allebei over de pagina die je aan iemand anders geeft. Een gepubliceerd deck laadde syntax highlighting, wiskundeopmaak en een videospeler, of het nu code, formules of video bevatte of niet; nu laadt het die alleen als het ze echt heeft. En een deck in een iframe kun je om een minimale interface vragen, zodat het frame de slide is en verder niets.

    Vijftien verzoeken aan derden, terug naar nul

    Gemeten op een echt deck van negen slides zonder codeblokken, zonder formules en zonder video: vijftien verzoeken aan derden eerst, nu nul. Veertien daarvan gingen naar jsDelivr voor Prism (de core, tien hardgecodeerde taalpakketten en een themastylesheet) plus KaTeX, en één naar mediadelivery.net voor de Bunny-speler.

    Drie dingen die precies moeten:

    • Dit geldt voor elke gepubliceerde pagina, niet alleen de HTML-download. /p/, de embed-route en het geëxporteerde bestand komen uit dezelfde code, dus wie een link deelt heeft er net zoveel aan als wie een bestand opstuurt.
    • De verzoeken zijn voorwaardelijk geworden, niet verwijderd. Een deck met een codeblok laadt nog steeds Prism vanaf jsDelivr, nu de core plus de talen die dat deck echt gebruikt in plaats van tien vaste. Wiskunde laadt nog steeds KaTeX, en een Bunny-video nog steeds zijn speler. Een deck met een codeblok en een formule doet vijf verzoeken.
    • Er is niets gelekt en er is niets gerepareerd. Er werden verzoeken gedaan die niet nodig waren. Dat is iets anders dan een kwetsbaarheid, en het hoort niet als zodanig gelezen te worden.

    Waarom dit de kop is en geen prestatie-voetnoot: Deckyard is software die mensen zelf hosten om hun gegevens in eigen hand te houden, en jsDelivr draait op Fastly in de Verenigde Staten. Een deck dat naar twee Amerikaanse CDN’s belde om negen slides platte tekst te tonen, was een ongemakkelijk ding om aan een publieke instelling te geven.

    ?ui=min voor ingesloten decks

    Zet ?ui=min achter de URL van een gepubliceerd of geëxporteerd deck en de titelbalk en de knoppenrij verdwijnen, waarbij hun layoutrijen naar nul hoogte klappen. Het geschaalde podium van 1600x900 is dan het hele frame, en dat betekent dat een hostpagina een iframe kan maten met een gewone aspect-ratio: 16 / 9 in plaats van een vaste hoogte te compenseren.

    • Het voortgangsbalkje van 3px blijft. Het staat absoluut gepositioneerd, kost dus geen layouthoogte, en het frame blijft precies 16:9.
    • De zichtbare slideteller verdwijnt, want dat was het onderdeel dat op een smal frame afbrak, en de hostpagina kan zijn eigen teller tonen. Schermlezers horen nog steeds “Slide 3 van 9” en de titel van de slide.
    • Pijltjes, spatie, Home, End en F voor volledig scherm blijven allemaal werken.
    • Zonder de parameter verandert er niets, dus bestaande links blijven zoals ze waren.

    Naam en betekenis zijn gelijk aan de ui-optie die de embed-API al had, zodat de twee runtimes één vocabulaire houden.

    En passant kreeg de referentiedocumentatie van de standalone export een sectie over URL-parameters, die er tot nu toe helemaal niet was: loop, autoplay en interval bestonden al, maar stonden nergens opgeschreven.

    De volledige lijst op commit-niveau staat bij de release 1.6.0 op GitHub.

  127. v1.5.1

    Onderhoudsrelease

    Onderhoud aan dependencies, met één ding om vooraf te controleren: de praktische Node-ondergrens ligt nu op 22.13.

    Een onderhoudsrelease: zeven dependency-updates en de ene codewijziging die er één van nodig had. Niets nieuws, en niets gedraagt zich anders. Er is wel één ding dat je beter vooraf doet, en dat staat niet in de release zelf.

    Controleer eerst je Node-versie. Deckyard vraagt al een tijd Node 22 en dat blijft zo, maar twee dependencies in deze release hebben hun eigen ondergrens verhoogd: jsdom (25 naar 29) wil 22.13 of nieuwer, puppeteer-core (24 naar 25) wil 22.12. Draai je Node 22.0 tot en met 22.12, dan zat je op 1.5.0 goed en zit je nu onder allebei. npm handhaaft dat standaard niet, dus het installeert met een waarschuwing in plaats van een foutmelding, en de onderdelen die het zouden merken zijn de HTML-export en de sanitisatie. Precies het soort ding dat je drie weken later pas ontdekt, en daarom staat het hier.

    Wat er verder in zit

    • zod is naar 4 gegaan, en de AI-schemavalidatie is meegegaan: zod 4 haalde ZodError.errors weg en de vijf validators lazen dat veld. Beide zitten in deze release, dus aan de AI-generatie verandert er tussen 1.5.0 en 1.5.1 niets.
    • Chrome 150 onder de export, via puppeteer-core 25. Met de hand nagelopen op een echte render, want geen enkele test start een browser; de uitvoer is ongewijzigd.
    • jsdom 25 naar 29, vier majors onder de HTML-sanitizer. Eenentwintig XSS- en mXSS-vectoren door de vier sanitisatiefuncties geven op beide versies byte-identieke uitvoer. Er is hier niets gerepareerd; er is vastgesteld dat er niets verandert.
    • De RSS-, Atom- en JSON-feeds zijn ongewijzigd na feed 5 naar 6, plus een groep van acht minor- en patch-updates en twee CI-actions die een self-hoster nooit ziet.

    De volledige lijst op commit-niveau staat bij de release 1.5.1 op GitHub.

  128. v1.5.0

    Feature-release

    Deckyard kiest de tekstkleur op een gekleurd vlak nu op gemeten contrast in plaats van op helderheid, en de theme-editor laat het getal zien terwijl je kiest.

    Twee commits, en één ervan verandert hoe decks die je al hebt eruitzien. Deckyard zet zelf lichte of donkere tekst op een gekleurd vlak; die keuze liep op helderheid en loopt nu op een gemeten contrastverhouding, waardoor negen van de twintig paletkleuren in de vijf ingebouwde thema’s van tekstkleur wisselen. Daarnaast heeft de theme-editor een contrast-uitlezing gekregen, zodat het getal dat je voorheen ergens anders moest opzoeken nu naast de kiezer staat die het oplevert.

    Draai je Deckyard, lees dan de updatenotitie voordat het eerste “is er iets stuk?”-bericht binnenkomt. Tekst die gisteren wit was kan vandaag donker zijn, en dat is de herstelde fout, niet een nieuwe.

    De automatische tekstkleur wordt nu gemeten

    Kaarten, accentblokken en achtergrondvarianten krijgen hun tekstkleur van Deckyard en niet van jou. De oude regel splitste op helderheid: donkerder dan het midden, dus lichte tekst. Dat kiest de kleur die logisch oogt, niet de kleur die het beste leest. Beide kandidaten gaan nu door de contrastformule en de hoogste verhouding wint.

    Gemeten over alle vijf de ingebouwde thema’s:

    • Negen van de twintig paletkleuren krijgen een andere tekstkleur.
    • Elke omslag tilt een falend paar naar WCAG AA of beter. Geen enkel paar wordt slechter.
    • Paren onder AA: van negen naar één.
    • Het scherpste geval is het icoonblok van midnight, dat van 2,05:1 ging - wit op lichtblauw, praktisch onzichtbaar - naar 8,16:1.

    Het ene paar dat onder AA blijft is het accent #ea580c van playful op 4,40:1; daar is de accentkleur zelf de grens, niet de keuze van de tekstkleur.

    Omdat contrast niet symmetrisch is rond het midden van de schaal ligt het omslagpunt bij een relatieve luminantie van ongeveer 0,21, dus middel-lichte achtergronden krijgen voortaan donkere tekst. Precies die asymmetrie is de reden dat de oude regel zoveel paren onder AA liet landen.

    De theme-editor laat contrast zien terwijl je kiest

    Bij elk kleurenpaar in de editor staat nu de contrastverhouding en een WCAG 2.2-oordeel: faalt, AA of AAA, gemeten aan de drempel die bij de tekstgrootte van die rol hoort. Knoppen en koppen worden aan de lat voor grote tekst gelegd, bodytekst aan de strengere. Daarnaast staat een APCA Lc-waarde als tweede lezing.

    • Het rapporteert, het blokkeert niet. Een thema met een falend paar kun je gewoon opslaan. Een self-hoster kan een merkreden hebben om een variant met laag contrast te shippen, en een instellingenpaneel is niet de plek om dat te overrulen.
    • De verhouding staat er altijd, of het paar nu slaagt of niet, zodat contrast iets is waar je naartoe kunt sturen in plaats van een alarm dat pas afgaat als je er al overheen bent.
    • WCAG is het oordeel; APCA staat ernaast. WCAG 2.2 is waar EN 301 549 en de European Accessibility Act naar wijzen, dus dat is de claim waar iemand op kan leunen. APCA, kandidaatwerk voor WCAG 3, modelleert waargenomen contrast beter - vooral lichte tekst op donker, waar midnight op gebouwd is - maar beslist nooit.

    De uitlezing gaat over de vier hoofdkleuren en de achtergrondvarianten. Het merkpalet draagt bewust nog geen oordelen: die tokens worden binnenkort opnieuw gedefinieerd, en badges erop zouden bij aankomst al achterhaald zijn.

    Bij het updaten

    • Bestaande decks zien er anders uit, en dat is de bedoeling. Er is niets in te stellen en niets te migreren: de tekstkleur wordt bij het renderen afgeleid, dus een deck openen is genoeg. Het valt het meest op bij midnight en overal waar een icoonblok of accentkaart op een middel-lichte kleur stond. Meldt iemand het als bug, dan mat het paar waar hij naar kijkt vrijwel zeker onder de 4,5:1.
    • Een eigen thema profiteert zonder dat je het bewerkt. De afleiding is gedeeld, dus jouw eigen kleuren gaan door dezelfde meting. Open de theme-editor om te zien waar elk paar nu uitkomt.

    De volledige lijst op commit-niveau staat bij de release 1.5.0 op GitHub.

  129. v1.4.0

    Feature-release

    Een slidetype kan nu de regels dragen die jouw organisatie stelde aan het invullen ervan, en elk geregistreerd type is zichtbaar voor een agent of bewust achtergehouden.

    Wat een AI-agent van een slidetype wist, kwam tot nu toe uit een handgeschreven catalogus in Deckyard: redactionele tekst die zegt welk type je moet kiezen. Deze release zet dat open. Elk geregistreerd type is nu zichtbaar voor agents, ook de types die je eigen instance zelf definieert, en elk type kan de regels dragen die jouw organisatie stelde aan het invullen ervan: uit welke bron de cijfers moeten komen, welke peildatum geldt, wat er verplicht bij vermeld wordt. Het is de eerste feature waarin een self-hoster zelf iets invult, in plaats van dat er achter de schermen iets beter werkt.

    Er zijn die dag twee versies geknipt. 1.4.1 volgde een half uur later met één fix in de streaming-API, beschreven onder Bij het updaten. Installeer 1.4.1.

    Je huisregels reizen mee met het type

    • Elk geregistreerd type bereikt een agent, of wordt bewust achtergehouden. De tool get_slide_types liep tot nu toe de handgeschreven catalogus af, dus een type zonder catalogusregel was onzichtbaar voor agents - en niet te onderscheiden van een type dat met opzet was weggelaten. Hij leest nu de runtime-registry, en types die je zelf in de builder-UI definieert komen er ook in terecht. Van de 38 geregistreerde types worden er 31 aangeboden en dragen er 7 een expliciete opt-out; geen enkele is ongedocumenteerd, en een test laat de build vallen zodra dat verandert.
    • Een type kan zijn eigen gebruiksregels dragen. Naast de tekst die zegt waar een type voor is, kan een type nu de huisregels dragen voor het invullen ervan: de bron waar een grafiek uit moet komen, de peildatum die telt, het voorbehoud dat erbij hoort. Die regels gaan mee in elk antwoord van get_slide_types, na het schema, zodat een agent eerst de vorm leest en daarna jouw regel.
    • Vier plekken om ze te schrijven, afhankelijk van waar het type woont. Op de catalogusregel van een kerntype; als override in een fork, zonder het open-source-bestand te patchen; op een eigen, in een bestand gedefinieerd type; of in de builder-UI voor een type dat in de database staat. Regels zijn begrensd op 1000 tekens per type, want ze vermenigvuldigen zich met elk zichtbaar type in elk antwoord.

    Een verwijderd type houdt zijn inhoud

    Het type freeform-slide is niet langer geregistreerd. Het was al een tijd deprecated en werd nergens meer aangeboden, dus de meeste instances hebben zulke slides niet; staat er toch nog een in een opgeslagen deck, dan gaat er niets verloren. De inhoud blijft in de deck-JSON staan, en de slide toont nu een placeholder die het type benoemt, zegt dat het bewust is verwijderd en naar de opvolger wijst, in plaats van een kaal “Onbekend slidetype”.

    Die placeholder is nu een algemene belofte, niet een pleister voor één type. Op het canvas - editor, presenter, embed, PNG, PDF - is hij begrensd en vertelt hij hoeveel velden hij heeft weggelaten, want een 16:9-kader kan niet meegroeien. In de lees- en reflow-weergave laat hij alles zien, want dat is de plek waar je je inhoud terughaalt. Een deck importeren met een onbekend type bewaart de oorspronkelijke inhoud als markdown in plaats van hem te laten vallen; dat was de enige route waar echt iets sneuvelde. En de editor crasht niet meer op zo’n deck: die gaf voorheen een wit foutscherm in plaats van een placeholder.

    Een kortere inspector-rail

    De titelbalk “INSPECTOR” is weg; het kruisje waarmee je de rail inklapt blijft staan. De achtergrondsectie is gesplitst naar hoe vaak je eraan komt: kleur is een gewoon zichtbaar veld, terwijl de afbeelding met uitsnede, focuspunt en overlay in een ingeklapt blok zit dat een thumbnail toont zodra er een achtergrond staat. Op een titelslide ging de rail van ruwweg 1310 naar 376 pixels, waardoor Toegankelijkheid nu op één scherm past zonder scrollen.

    Opgelost

    • #slide=<n> werkt weer in geëxporteerde HTML. Een geëxporteerd standalone-deck negeerde de deep-link in de URL en opende altijd op slide 1, dus een export delen met een link naar een bepaalde slide deed niets. Het patroon werd uitgeschreven in een template-literal, waar \d inklapt tot een letterlijke d; het matchte dus nooit, en zat er al zolang de export-runtime bestaat.
    • GET /api/v1/image-library gaf altijd een 500. Een gedocumenteerd endpoint dat nooit heeft gewerkt: de route importeerde een functie die de opslaglaag niet exporteert. Hij is nu aangesloten, met de parameters voor zoeken, categorie en paginering daadwerkelijk geïmplementeerd en de OpenAPI-beschrijving gecorrigeerd naar de velden die de bibliotheek echt heeft.
    • Tags schrijven gaf een 400. PUT /api/presentations/:id/tags en POST /api/tags lazen de request-body één niveau te diep, dus tags schrijven via de API was dood bij aankomst.

    Bij het updaten

    • SSE-foutmeldingen hebben een andere vorm gekregen. Dit is de hele inhoud van 1.4.1. Server-sent events op de import-, conversie- en AI-generatiestreams dragen hun fouttekst nu in message in plaats van in error, en bevatten geen ok-veld meer. In de app zelf merk je er niets van; heb je een fork of integratie die op die streams meeluistert, dan is dit één veldnaam om om te zetten.
    • Een breaking change in een minor-versie is de bedoelde vorm. Deckyard blijft de hele beta op 1.x, dus 2.0.0 is gereserveerd voor het verlaten van de beta en niet voor een opruiming die toevallig iets breekt. Het verwijderen van freeform-slide hierboven is die wijziging.

    De volledige lijst op commit-niveau staat bij de releases 1.4.0 en 1.4.1 op GitHub.

  130. v1.3.0

    Feature-release

    Organisaties worden bruikbaar op één instance, uitlijning wordt een eigenschap van het blok, en een cross-user XSS in de slidelijst gaat dicht.

    De organisatie-track landt, en daarmee het antwoord op een vraag die maanden half gebouwd stond: hoe één Deckyard-instance meerdere organisaties bedient zonder dat ze elkaar zien. Er zit ook een beveiligingsfix in die op zichzelf al reden is om te updaten.

    Update als je een multi-user-instance draait. Deze release dicht een DOM-XSS in de slidelijst, onderaan deze pagina beschreven. Een slidetitel wordt door een mens getypt, dus in een deck dat je met collega’s deelt kan de payload uit iemand anders’ slide komen, en hij gaat af zodra je een slide in de lijst versleept. Er valt niets in te stellen: updaten is de fix.

    Organisaties op één instance

    Drie wijzigingen die alleen samen betekenis hebben:

    • Wie je bent hangt niet langer af van waar je bent. Elke authenticatie-lookup filterde op de organisatie die op je account gestempeld stond, terwijl lidmaatschap je bij meerdere kan laten horen. Wie zijn thuisorganisatie niet die van het verzoek was, kwam op niemand uit en kreeg een 401. Daarom is MULTI_WORKSPACE_ENABLED nooit end-to-end aangesloten: aanzetten zou mensen hebben uitgelogd. Identiteit wordt nu los vastgesteld, lidmaatschap is een aparte vraag.
    • Een verzoek draait in de organisatie waar je sessie op uitkwam. Van workspace wisselen veranderde alleen de sessiecookie: lezen, schrijven en lijsten bleven in de standaardorganisatie hangen. De organisatie reist nu mee met het verzoek, en alleen een organisatie waarvan je aantoonbaar lid bent: dat lidmaatschap wordt per verzoek opnieuw gecontroleerd, want een token overleeft een intrekking tot twee weken.
    • Ook de autorisatielaag kent organisaties. De rechtenlaag gaf workspace-brede lees- en schrijfrechten zonder organisaties ook maar te noemen, en leunde erop dat de opslaglaag de query zou afbakenen. In de praktijk hield dat, maar een laag die alleen standhoudt omdat de laag eronder eraan denkt af te bakenen is geen laag. De vier workspace-rechten controleren nu dat beide kanten in dezelfde organisatie zitten; eigenaarschap, auteurschap en toegang als collaborator blijven ongemoeid.

    Installaties met één organisatie, en dat zijn de meeste, gedragen zich precies als eerst en betalen hier niets voor: de organisatie komt uit de configuratie zonder database-lookup, en er komt nergens een query bij.

    Uitlijning hoort bij het blok

    Een titelslide uitlijnen betekende tot nu toe titel, ondertitel en metaregel elk op “gecentreerd” zetten, waarna ze nog steeds gecentreerd stonden op assen die ver uit elkaar liggen, want elk tekstvak zit ergens anders op de slide. Uitlijning is nu een eigenschap van het visuele blok in plaats van van elk veld erin, in één keer in te stellen via de layout-switcher die je al gebruikt. Velden die hun uitlijning niet meer zelf bezitten zeggen dat, in plaats van een knop te tonen die niets doet.

    Opgelost

    • Niets overleeft zijn eigen scherm meer. Een lifecycle-audit van de client vond zes lekken van dezelfde vorm: iets dat bij het openen werd geregistreerd en het sluiten overleefde zonder dat er nog iets was om het te stoppen. Openstaande reconnects bleven streams heropenen die niemand kon sluiten, en opruimacties die zich ná het afbreken meldden verdwenen in een map die niemand nog leegde. De notificatiebel en beide Q&A-streams verbinden nu opnieuw met backoff in plaats van elke 1,2 seconde per kijker aan te kloppen.
    • Een nieuwe deck begint in de taal van je interface. De app in het Engels openen gaf een Engelse interface met de taalknop in “Nieuwe presentatie” nog op de standaardtaal van de workspace. Een taal die je zelf koos wint nog steeds van allebei.
    • Een vastgelopen thumbnail komt altijd tot rust. Een kaart in het deck-overzicht waarvan de thumbnail nooit binnenkwam bleef eindeloos shimmeren. Elke kaart bereikt nu een echte eindtoestand, en schakelt alsnog over op de echte afbeelding als die later arriveert.
    • Card-stack volgt het thema. Het laatste-redmiddel-palet was een hardgecodeerd paars dat bij één thema hoort, dus een eigen thema kreeg kaarten buiten de huisstijl. Het wordt nu afgeleid van de accentkleur van het thema, met een neutrale reeks als allerlaatste vangnet.
    • Conflicten bij gelijktijdig opslaan spreken de standaard-foutvorm. Drie schrijfroutes voor presentaties gaven een zelfgebouwd antwoord terug als je opslaan botste met dat van iemand anders. Ze sturen nu de canonieke envelope, met de vaste codes conflict en locked en de revisiedetails erbij. Statuscodes blijven gelijk en de app merkt er niets van; bouwde je rechtstreeks op de API, dan draagt het veld error nu een machinecode en is de menselijke zin verhuisd naar message.

    Beveiliging

    Een cross-user XSS in de slidelijst. Het sleepbeeld dat ontstaat als je een slide oppakt, zette de titel van die slide rauw in de HTML. Een slide met een stukje markup als titel voerde dat uit zodra iemand hem versleepte, in de browser van degene die sleepte. Omdat slidetitels door mensen worden getypt en decks worden gedeeld, hoeven de schrijver en het slachtoffer op een multi-user-instance niet dezelfde persoon te zijn. Het sleepbeeld bouwt zijn label nu als tekst op, en twee naburige plekken in het JSON-debugvenster en het importpaneel zijn op dezelfde manier herbouwd.

    De volledige lijst op commit-niveau staat bij de 1.3.0-release op GitHub.

  131. v1.2.0

    Onderhoudsrelease

    Een kleine release: interfacetekst die alle talen bereikt, een vertaalde editor-melding, en een ronde hardening voor instances die publiek bereikbaar zijn.

    Een rustige release tussen twee grotere in. Aan het maken van een deck verandert niets; het werk zit in de taal van de interface en in de delen van de stack die aan het open internet grenzen.

    Alle talen krijgen de interface, niet alleen het Engels

    Deckyard komt in 12 talen, maar een label dat rechtstreeks in de code staat heeft geen sleutel om te vertalen, dus verscheen het overal in het Engels zonder dat een test daarover viel. Een audit vond en vertaalde de teksten die nog op het hoofdpad stonden: de melding van de slide-bibliotheek, het voorbeeldblok op een themakaart, de provider-hints en veldlabels in het databronvenster, de autoplay-schakelaar, de bediening van het focuspunt en de alt-tekst van het thema-logo. Een nieuwe controle in CI laat de build vallen op nieuwe hardcoded tekst, zodat de lijst alleen nog korter kan worden.

    De melding “Ongeldige JSON” in het JSON-debugvenster, de laatste rauwe tekst in een verder volledig vertaald venster, loopt nu ook door de vertaallaag.

    Hardening voor instances die publiek openstaan

    Deze ronde is gericht op de anonieme sandbox, en telt voor elke installatie waar onbekenden decks kunnen maken:

    • Rate limiting achter een reverse proxy. Staat Deckyard achter een proxy zonder dat de limiter dat weet, dan telt hij elk verzoek op het adres van de proxy zelf: alle bezoekers delen één bucket en één misbruiker legt de limiet op voor iedereen. Met TRUST_PROXY en TRUSTED_PROXY_COUNT telt hij op het echte adres van de bezoeker.
    • Een quotum per gast. Aantal decks en totaal aantal bytes zijn nu per gast begrensd op elk punt waar een deck ontstaat (aanmaken, importeren, dupliceren), met een kleinere limiet op de request-body die elk daarvan begrenst. Een gast aan het plafond krijgt een duidelijke 429 in plaats van het gedeelde volume vol te schrijven.
    • Nog een SSRF-gat dicht. Externe afbeeldingen liepen bij export al langs de guard; een CSS-background-image: url() die via een geïmporteerde custom-HTML-slide binnenkwam niet. Die wordt nu ingesloten of leeggemaakt voordat de HTML de renderer bereikt.

    De volledige lijst op commit-niveau staat bij de 1.2.0-release op GitHub.

  132. v1.1.0

    Feature-release

    De eerste grote release sinds Deckyard open source werd: live samenwerken, een vernieuwde editor, zelfstandige exports en een steviger self-hostingverhaal.

    Deckyard 1.1 is de eerste flinke release sinds de code openbaar werd. Hij verdiept precies de onderdelen die van Deckyard een platform maken in plaats van een slide-editor: mensen die tegelijk in dezelfde deck werken, exports die je aan iedereen kunt geven, en een self-hostingpad dat tegen een stootje kan.

    Live samenwerken

    • Live presence: zie wie er nog meer in een deck zit, met glijdende naamlabels en focus-chips op de slides die ze bewerken.
    • Conflictvrij samen bewerken op basis van CRDT’s, zodat twee mensen in dezelfde deck kunnen typen zonder elkaar in de weg te zitten.
    • Reacties met @-mentions en autocomplete, leesstatus per persoon, en GitHub-achtige abonnementen die je meenemen naar de threads waaraan je meedoet.

    Een scherpere editor

    • Een inspector die meebeweegt met je selectie en wisselt tussen element- en slide-instellingen.
    • Markdown inline bewerken op het canvas zelf, met een zwevende toolbar.
    • Versleepbare focuspunten op bijgesneden afbeeldingen, volledig met het toetsenbord te bedienen.
    • Kaarten inline herordenen met grip-handles, en beeldinstellingen openen vanaf een chip op de afbeelding zelf.
    • Een datagrid als een spreadsheet voor grafiek-slides, met een CSV-schakelaar om in één keer cijfers te plakken.

    Exports die van jou zijn

    • Eén exportvenster met kleurgecodeerde formaten, zodat het hele menu in één oogopslag leesbaar is.
    • Zelfstandige .deck-bundels die je exporteert en weer importeert met alles er nog in.
    • Losstaande HTML met ingesloten fonts, zodat een deck offline rendert zonder iets te hoeven ophalen.
    • Een semantische, herbruikbare HTML-leesexport, plus kleinere PDF’s dankzij beeldcompressie vóór het insluiten.

    Thema’s en merk

    • Rijkere themaconfiguratie die op het thema zelf wordt bewaard, inclusief achtergrond-presets en titel-slide-layouts.
    • Thema-surface-tokens lopen nu door het slide-ontwerpsysteem, zodat merkkleuren consistent landen over slidetypes heen.

    Self-hosting en beveiliging

    • SSO via één identity provider over OIDC voor zelfgehoste instances.
    • Een installer met één commando en interactieve .env-setup, plus een non-interactieve variant voor agents en CI.
    • Beveiliging over de hele linie aangescherpt: rate limiting en brute-force-throttling op authenticatie, SSRF- en CSRF-bescherming, autorisatie per resource voor live sessies, isolatie tussen workspaces, en security headers.

    Toegankelijkheid

    • Een HTML-semantiekslag door de renderlaag: landmarks, echte lijsten en RTL-ondersteuning.
    • Een kop-overzicht van het document voor visuele export en embed, en een toegankelijkheidspaneel met inklapbare regels.

    De volledige lijst op commit-niveau staat bij de 1.1.0-release op GitHub.

  133. v1.0.0

    Publieke lancering

    Deckyard wordt open source. Het hele platform - maken, presenteren, publiceren, samenwerken - komt op GitHub onder de MIT-licentie.

    De eerste publieke release. Deckyard was al een werkend platform dat dagelijks werd gebruikt; 1.0 is het moment waarop de broncode van jou werd om te lezen, te draaien en aan te passen.

    Wat er live ging

    • Het volledige platform van begin tot eind: 35+ slidetypes, live presenteren, publiceren op het web met één klik, en samenwerken.
    • Self-hosting vanuit één Docker Compose-bestand, Node en Postgres.
    • AI op je eigen voorwaarden: gebruik je eigen sleutel, stel de prompts bij, of stuur het aan via MCP.
    • Exporteren naar PDF, PowerPoint, zelfstandige HTML, PNG en JSON, zodat niets vastzit.
    • MIT-gelicenseerd, GDPR-native, gebouwd om te draaien op infrastructuur die jij beheert.