[{"data":1,"prerenderedAt":4713},["ShallowReactive",2],{"post":3},{"articles":4,"showPagination":4710,"totalItems":4711,"itemsPerPage":3900,"currentPage":4712},[5,456,1244,1980,2596,3084,3870,4080],{"metadata":6,"sys":9,"fields":29},{"tags":7,"concepts":8},[],[],{"space":10,"id":15,"type":16,"createdAt":17,"updatedAt":17,"environment":18,"publishedVersion":22,"revision":23,"contentType":24,"locale":28},{"sys":11},{"type":12,"linkType":13,"id":14},"Link","Space","mqwrag4of3hk","2AYrU6upsgYDbGmOhz9sL4","Entry","2026-02-27T14:28:16.290Z",{"sys":19},{"id":20,"type":12,"linkType":21},"master","Environment",87,1,{"sys":25},{"type":12,"linkType":26,"id":27},"ContentType","post","en-US",{"title":30,"published":31,"slug":32,"heroImage":33,"body":58,"tags":372},"Me and You, and You and Me, so Happy Together","2026-02-27","me-and-you-and-you-and-me-so-happy-together",{"metadata":34,"sys":37,"fields":46},{"tags":35,"concepts":36},[],[],{"space":38,"id":40,"type":41,"createdAt":42,"updatedAt":42,"environment":43,"publishedVersion":45,"revision":23,"locale":28},{"sys":39},{"type":12,"linkType":13,"id":14},"6cFNLIKMKUwqR7wrX4CxTW","Asset","2026-02-27T14:13:40.406Z",{"sys":44},{"id":20,"type":12,"linkType":21},10,{"title":47,"description":48,"file":49},"Hand in hand with Robot","A robot with a fox like appearance is holding hands with a child.",{"url":50,"details":51,"fileName":56,"contentType":57},"//images.ctfassets.net/mqwrag4of3hk/6cFNLIKMKUwqR7wrX4CxTW/a715b027bc6b2f5f41c0523d0ae4e3fd/enchanted-tools-1jgkYcFfwKw-unsplash.jpg",{"size":52,"image":53},67547,{"width":54,"height":55},800,450,"enchanted-tools-1jgkYcFfwKw-unsplash.jpg","image/jpeg",{"data":59,"content":60,"nodeType":371},{},[61,107,141,149,156,163,174,181,188,195,211,218,225,241,248,255,262,269,276,292,299,306,322,329,336,343,350,357,364],{"data":62,"content":63,"nodeType":106},{},[64,69,75,79,84,88,93,97,102],{"data":65,"marks":66,"value":67,"nodeType":68},{},[],"There's a pattern that keeps showing up in software engineering: the tools that ","text",{"data":70,"marks":71,"value":74,"nodeType":68},{},[72],{"type":73},"bold","give",{"data":76,"marks":77,"value":78,"nodeType":68},{},[]," us the most ",{"data":80,"marks":81,"value":83,"nodeType":68},{},[82],{"type":73},"leverage",{"data":85,"marks":86,"value":87,"nodeType":68},{},[]," also ",{"data":89,"marks":90,"value":92,"nodeType":68},{},[91],{"type":73},"demand",{"data":94,"marks":95,"value":96,"nodeType":68},{},[]," the most ",{"data":98,"marks":99,"value":101,"nodeType":68},{},[100],{"type":73},"structure",{"data":103,"marks":104,"value":105,"nodeType":68},{},[],". ","paragraph",{"data":108,"content":109,"nodeType":106},{},[110,114,119,123,128,132,137],{"data":111,"marks":112,"value":113,"nodeType":68},{},[],"Version control unlocked collaboration at scale, but only after teams agreed on ",{"data":115,"marks":116,"value":118,"nodeType":68},{},[117],{"type":73},"branching strategies",{"data":120,"marks":121,"value":122,"nodeType":68},{},[],". Linting and formatting took out a lot of opinions during code reviews, but first we needed to have settled the ",{"data":124,"marks":125,"value":127,"nodeType":68},{},[126],{"type":73},"\"tabs vs. spaces\" debate",{"data":129,"marks":130,"value":131,"nodeType":68},{},[],". CI/CD pipelines sped everything up, but only once contributors agreed upon a ",{"data":133,"marks":134,"value":136,"nodeType":68},{},[135],{"type":73},"definition of done",{"data":138,"marks":139,"value":140,"nodeType":68},{},[],". AI coding tools are following the same arc, and the teams getting the most out of them have already figured this out.",{"data":142,"content":143,"nodeType":148},{},[144],{"data":145,"marks":146,"value":147,"nodeType":68},{},[],"It Starts in Isolation","heading-3",{"data":150,"content":151,"nodeType":106},{},[152],{"data":153,"marks":154,"value":155,"nodeType":68},{},[],"Most developers start their AI journey the same way: alone. Experimenting with prompts, figuring out what works, building a personal workflow that feels productive. That phase is valuable, but it has a ceiling.",{"data":157,"content":158,"nodeType":106},{},[159],{"data":160,"marks":161,"value":162,"nodeType":68},{},[],"What one developer learns stays with that developer. What the AI produces reflects that developer's habits, their slice of the codebase, their framing of the problem, their domain knowledge. Useful! But local. The moment that output lands in a shared codebase, the cracks start to show.",{"data":164,"content":165,"nodeType":173},{},[166],{"data":167,"content":168,"nodeType":106},{},[169],{"data":170,"marks":171,"value":172,"nodeType":68},{},[],"What one developer learns stays with that developer","blockquote",{"data":175,"content":176,"nodeType":106},{},[177],{"data":178,"marks":179,"value":180,"nodeType":68},{},[],"And here's the thing that makes AI different from a junior developer finding their feet: AI doesn't have guardrails! It makes decisions confidently and at speed, every single time. Without any grounding in your conventions and patterns, it doesn't just introduce one person's preferences: it introduces entirely new ones, consistently, at scale. That compounds fast. Too fast for humans to keep up!",{"data":182,"content":183,"nodeType":148},{},[184],{"data":185,"marks":186,"value":187,"nodeType":68},{},[],"Existing Projects Are Actually the Best Starting Point",{"data":189,"content":190,"nodeType":106},{},[191],{"data":192,"marks":193,"value":194,"nodeType":68},{},[],"There's a common assumption that AI tools work best on fresh, greenfield projects. Clean slate, no legacy baggage, lots of room to set things up properly. In my experience, the opposite is true.",{"data":196,"content":197,"nodeType":106},{},[198,202,207],{"data":199,"marks":200,"value":201,"nodeType":68},{},[],"Existing projects already contain most of what you need. The patterns are in the code. The decisions are in the commit history. The conventions exist: they just live in people's heads instead of in writing. ",{"data":203,"marks":204,"value":206,"nodeType":68},{},[205],{"type":73},"That's not a problem; it's actually a great starting point.",{"data":208,"marks":209,"value":210,"nodeType":68},{},[]," The work is extraction and formalization, not invention, a great starting point!",{"data":212,"content":213,"nodeType":106},{},[214],{"data":215,"marks":216,"value":217,"nodeType":68},{},[],"A four-year-old repository with minimal documentation is a perfect example. Nobody's touched it because it works and nobody remembers exactly how. Feed it to an AI agent with the right context and standards in place, and suddenly that dusty codebase is workable again. (Results may vary)",{"data":219,"content":220,"nodeType":148},{},[221],{"data":222,"marks":223,"value":224,"nodeType":68},{},[],"Give the Agent Focus",{"data":226,"content":227,"nodeType":106},{},[228,232,237],{"data":229,"marks":230,"value":231,"nodeType":68},{},[],"When you give an AI agent a task on an undocumented codebase, it will produce something. It will sequence steps, choose libraries, resolve ambiguities, make trade-offs. The question is whether those decisions reflect your team's standards or just... whatever seemed reasonable based on ",{"data":233,"marks":234,"value":236,"nodeType":68},{},[235],{"type":73},"general training data",{"data":238,"marks":239,"value":240,"nodeType":68},{},[]," (which is probably bad in the long run).",{"data":242,"content":243,"nodeType":106},{},[244],{"data":245,"marks":246,"value":247,"nodeType":68},{},[],"The difference becomes really clear with something like a major dependency upgrade. The kind of work that touches core packages, forces decisions about what to modernize and what to preserve, and breaks things in ways you don't always anticipate. Without context, an agent will make those calls based on what's common in the wild. With explicit standards: which package manager the team uses, which test framework is preferred, which platform constraints apply. The output is way more consistent with the rest of the system.",{"data":249,"content":250,"nodeType":106},{},[251],{"data":252,"marks":253,"value":254,"nodeType":68},{},[],"That consistency is what makes the output reviewable. And reviewability is what makes AI-assisted development actually scale. If every contribution needs significant massaging before it can be merged, the productivity gains disappear quickly.",{"data":256,"content":257,"nodeType":148},{},[258],{"data":259,"marks":260,"value":261,"nodeType":68},{},[],"A Concrete Example",{"data":263,"content":264,"nodeType":106},{},[265],{"data":266,"marks":267,"value":268,"nodeType":68},{},[],"I recently ran an experiment on a Vue 2 sideproject that I hadn't touched in years. Outdated dependencies, minimal documentation (actually, only the default \"Readme.md\" file), a couple of environment-specific quirks I hadn't written down anywhere. (Problems for future me!)",{"data":270,"content":271,"nodeType":106},{},[272],{"data":273,"marks":274,"value":275,"nodeType":68},{},[],"Starting with a deliberately vague instruction to my favourite AI assistent (\"upgrade this\"), the agent generated a structured, sequenced plan: which packages to upgrade first, what to do about libraries with limited forward support, which legacy tooling to replace with more current alternatives. It didn't just produce a flat list of tasks: it produced an opinionated sequence that reflected how you'd actually want to approach a migration like this. The list was stored in an \"Agents.md\" file, which makes it part of the codebase.",{"data":277,"content":278,"nodeType":106},{},[279,283,288],{"data":280,"marks":281,"value":282,"nodeType":68},{},[],"It also flagged what it didn't know. The project deployed to two different environments with different constraints, and without documentation on those requirements, ",{"data":284,"marks":285,"value":287,"nodeType":68},{},[286],{"type":73},"the agent surfaced the gap",{"data":289,"marks":290,"value":291,"nodeType":68},{},[]," rather than making the wrong call. ",{"data":293,"content":294,"nodeType":106},{},[295],{"data":296,"marks":297,"value":298,"nodeType":68},{},[],"Feed it back in the requirements, get an updated plan. It's standardization through conversation, not through a big upfront documentation effort.",{"data":300,"content":301,"nodeType":148},{},[302],{"data":303,"marks":304,"value":305,"nodeType":68},{},[],"The Feedback Loop Is the Real Win",{"data":307,"content":308,"nodeType":106},{},[309,313,318],{"data":310,"marks":311,"value":312,"nodeType":68},{},[],"This is the part that I think gets undersold. Standards aren't static: ",{"data":314,"marks":315,"value":317,"nodeType":68},{},[316],{"type":73},"standards evolve as the codebase evolves",{"data":319,"marks":320,"value":321,"nodeType":68},{},[],". And every interaction with an AI agent is an opportunity to refine them.",{"data":323,"content":324,"nodeType":106},{},[325],{"data":326,"marks":327,"value":328,"nodeType":68},{},[],"When an agent flags a gap, that's the standard telling you what it's missing. When output needs correction, the correction is an input for the next version of the guidelines. The standard gets smarter with use, produces better output, which surfaces better refinements. It compounds!",{"data":330,"content":331,"nodeType":106},{},[332],{"data":333,"marks":334,"value":335,"nodeType":68},{},[],"And when you share those standards across projects and teams (there are other tools for that, which are more suited than an \"Agents.md\" file), individual insight becomes collective knowledge. Improvements by one developer propagate to everyone using the same conventions. That's the \"learn once, apply everywhere\" lever that makes standardization worth the investment, especially at scale.",{"data":337,"content":338,"nodeType":148},{},[339],{"data":340,"marks":341,"value":342,"nodeType":68},{},[],"What This Looks Like in Practice",{"data":344,"content":345,"nodeType":106},{},[346],{"data":347,"marks":348,"value":349,"nodeType":68},{},[],"It doesn't have to start big. Write down (or generate) the conventions that already exist. Capture the context that lives only in people's heads. Specify the quality bar that contributions are expected to meet. That foundation is enough to meaningfully improve AI output from day one.",{"data":351,"content":352,"nodeType":106},{},[353],{"data":354,"marks":355,"value":356,"nodeType":68},{},[],"From there, the standard grows through use. Gaps get filled, conventions get refined, context accumulates. The codebase, rather than drifting toward entropy under the weight of well-intentioned but inconsistent contributions, starts to converge.",{"data":358,"content":359,"nodeType":106},{},[360],{"data":361,"marks":362,"value":363,"nodeType":68},{},[],"That convergence is the actual promise of AI-assisted development done well. Not just faster code generation (though that's real). Not just less repetitive work (also real). It's a codebase that stays coherent as it grows, because the standards, the tooling, and the contributors are all pulling in the same direction. You're responsible for adding the guardrails and focus that don't come out of the box.",{"data":365,"content":366,"nodeType":106},{},[367],{"data":368,"marks":369,"value":370,"nodeType":68},{},[],"This is definitely worth the effort!","document",[373,391,407,424,440],{"metadata":374,"sys":377,"fields":388},{"tags":375,"concepts":376},[],[],{"space":378,"id":380,"type":16,"createdAt":381,"updatedAt":381,"environment":382,"publishedVersion":384,"revision":23,"contentType":385,"locale":28},{"sys":379},{"type":12,"linkType":13,"id":14},"1X3B3fZIG1aKUMpZgoNdvV","2024-09-19T12:33:10.314Z",{"sys":383},{"id":20,"type":12,"linkType":21},3,{"sys":386},{"type":12,"linkType":26,"id":387},"tag",{"title":389,"slug":390},"Collaboration","collaboration",{"metadata":392,"sys":395,"fields":404},{"tags":393,"concepts":394},[],[],{"space":396,"id":398,"type":16,"createdAt":399,"updatedAt":399,"environment":400,"publishedVersion":384,"revision":23,"contentType":402,"locale":28},{"sys":397},{"type":12,"linkType":13,"id":14},"uMTBll2e3XbH2Q8NUe4h0","2022-12-12T11:31:23.149Z",{"sys":401},{"id":20,"type":12,"linkType":21},{"sys":403},{"type":12,"linkType":26,"id":387},{"title":405,"slug":406},"Artificial Intelligence","artificial-intelligence",{"metadata":408,"sys":411,"fields":421},{"tags":409,"concepts":410},[],[],{"space":412,"id":414,"type":16,"createdAt":415,"updatedAt":415,"environment":416,"publishedVersion":418,"revision":23,"contentType":419,"locale":28},{"sys":413},{"type":12,"linkType":13,"id":14},"3mtglgsTfKouXT4bWCU7BM","2022-11-30T12:30:06.284Z",{"sys":417},{"id":20,"type":12,"linkType":21},2,{"sys":420},{"type":12,"linkType":26,"id":387},{"title":422,"slug":423},"Tooling","tooling",{"metadata":425,"sys":428,"fields":437},{"tags":426,"concepts":427},[],[],{"space":429,"id":431,"type":16,"createdAt":432,"updatedAt":432,"environment":433,"publishedVersion":418,"revision":23,"contentType":435,"locale":28},{"sys":430},{"type":12,"linkType":13,"id":14},"3ScoBmDnPN0ZwL5sSGeE5u","2022-07-13T14:34:11.474Z",{"sys":434},{"id":20,"type":12,"linkType":21},{"sys":436},{"type":12,"linkType":26,"id":387},{"title":438,"slug":439},"Architecture","architecture",{"metadata":441,"sys":444,"fields":453},{"tags":442,"concepts":443},[],[],{"space":445,"id":447,"type":16,"createdAt":448,"updatedAt":448,"environment":449,"publishedVersion":384,"revision":23,"contentType":451,"locale":28},{"sys":446},{"type":12,"linkType":13,"id":14},"JMDb21nvmyJwXZVsvaO9N","2022-07-13T10:59:27.029Z",{"sys":450},{"id":20,"type":12,"linkType":21},{"sys":452},{"type":12,"linkType":26,"id":387},{"title":454,"slug":455},"Developer experience","developer-experience",{"metadata":457,"sys":460,"fields":472},{"tags":458,"concepts":459},[],[],{"space":461,"id":463,"type":16,"createdAt":464,"updatedAt":465,"environment":466,"publishedVersion":468,"revision":469,"contentType":470,"locale":28},{"sys":462},{"type":12,"linkType":13,"id":14},"34oYXMv3dyy6O0qRRlHSax","2025-12-15T13:10:00.449Z","2025-12-24T12:44:46.448Z",{"sys":467},{"id":20,"type":12,"linkType":21},662,4,{"sys":471},{"type":12,"linkType":26,"id":27},{"title":473,"published":474,"slug":475,"heroImage":476,"body":499,"sidebar":1130,"tags":1211},"2025: Year in Review","2025-12-24","2025-year-in-review",{"metadata":477,"sys":480,"fields":488},{"tags":478,"concepts":479},[],[],{"space":481,"id":483,"type":41,"createdAt":484,"updatedAt":484,"environment":485,"publishedVersion":487,"revision":23,"locale":28},{"sys":482},{"type":12,"linkType":13,"id":14},"2C4yDk4bXXPN16VM8y2zb9","2023-01-03T08:34:30.564Z",{"sys":486},{"id":20,"type":12,"linkType":21},9,{"title":489,"description":490,"file":491},"Fireworks","Photo courtesy of Erwan Hesry @ Unsplash",{"url":492,"details":493,"fileName":498,"contentType":57},"//images.ctfassets.net/mqwrag4of3hk/2C4yDk4bXXPN16VM8y2zb9/9089a0870eb07fe4741d80403b3a1946/erwan-hesry-WPTHZkA-M4I-unsplash__1_.jpg",{"size":494,"image":495},54235,{"width":496,"height":497},720,480,"erwan-hesry-WPTHZkA-M4I-unsplash (1).jpg",{"nodeType":371,"data":500,"content":501},{},[502,509,516,524,531,551,558,565,572,579,586,593,639,664,671,702,709,727,734,753,760,767,774,781,788,807,814,833,840,847,854,861,868,875,882,923,930,937,944,951,958,965,972,979,998,1012,1019,1026,1033,1040,1048,1055,1074,1081,1088,1095,1102,1109,1116,1123],{"nodeType":106,"data":503,"content":504},{},[505],{"nodeType":68,"value":506,"marks":507,"data":508},"By the time you're reading this, the plane that will land our family on Bonaire will have touched down on the tarmac at Flamingo Airport. ",[],{},{"nodeType":106,"data":510,"content":511},{},[512],{"nodeType":68,"value":513,"marks":514,"data":515},"This year felt a bit quieter on the outside, but when I look back at everything that happened it was anything but dull. A conscious decision to chase fewer big highs and lows. More small moments that added up to something meaningful. (And we'll get to that in the end!)",[],{},{"nodeType":517,"data":518,"content":519},"heading-2",{},[520],{"nodeType":68,"value":521,"marks":522,"data":523},"The Book (final update) 📚",[],{},{"nodeType":106,"data":525,"content":526},{},[527],{"nodeType":68,"value":528,"marks":529,"data":530},"My book was published in the beginning of last year and has turned profitable! As stated before, this wasn't even my initial goal, so I'm very proud of that achievement. I see that sales are tapering off now. With the Marvel API (which is used in one of the chapters) having been sunset, it's kind of a sad ending. But that's expected when writing on software. The ecosystem is ever-changing and that was a risk I took at the time, especially with a varied collection of packages each chapter depended on.",[],{},{"nodeType":106,"data":532,"content":533},{},[534,538,547],{"nodeType":68,"value":535,"marks":536,"data":537},"For those who are interested, the book is ",[],{},{"nodeType":539,"data":540,"content":542},"hyperlink",{"uri":541},"https://www.packtpub.com/en-nl/product/building-real-world-web-applications-with-vuejs-3-9781837630394",[543],{"nodeType":68,"value":544,"marks":545,"data":546},"still available as hard copy or a digital version",[],{},{"nodeType":68,"value":548,"marks":549,"data":550},"!",[],{},{"nodeType":517,"data":552,"content":553},{},[554],{"nodeType":68,"value":555,"marks":556,"data":557},"Artificial Intelligence 🧠",[],{},{"nodeType":106,"data":559,"content":560},{},[561],{"nodeType":68,"value":562,"marks":563,"data":564},"While the AI train left the station at speed last year, this year I'm seeing more signals of the AI bubble becoming brittle in some ways. More and more opponents and critics of AI are voicing concerns and I tend to agree with that sentiment. It's still a (sometimes) useful tool, but the cost of training and using it heavily is not sustainable or democratic. I did a talk on this with kids in elementary school!",[],{},{"nodeType":106,"data":566,"content":567},{},[568],{"nodeType":68,"value":569,"marks":570,"data":571},"I have been leading the research for internal AI tools and while the initiative had potential, the practical results fell short of expectations. For common tasks it's usable, and it's pretty good at code assistance (beware pitfalls), but the more complex processes tend to need a lot of handholding and wrangling.",[],{},{"nodeType":106,"data":573,"content":574},{},[575],{"nodeType":68,"value":576,"marks":577,"data":578},"It's not going away, but I hope we'll see the hype fade away some and elevate the things that do work instead of cramming AI everywhere without much purpose.",[],{},{"nodeType":517,"data":580,"content":581},{},[582],{"nodeType":68,"value":583,"marks":584,"data":585},"Different talks 🎤",[],{},{"nodeType":106,"data":587,"content":588},{},[589],{"nodeType":68,"value":590,"marks":591,"data":592},"I didn't attend any conferences as a speaker this year. To be honest, I wasn't that involved in cutting edge and applicable topics to share from a technical point of view. I did something else instead however! I gave three guest lectures this year. 🎓",[],{},{"nodeType":106,"data":594,"content":595},{},[596,600,608,612,617,621,626,630,635],{"nodeType":68,"value":597,"marks":598,"data":599},"Two of which were hosted by ",[],{},{"nodeType":539,"data":601,"content":603},{"uri":602},"https://www.fontys.nl/Over-Fontys/Fontys-ICT.htm",[604],{"nodeType":68,"value":605,"marks":606,"data":607},"Fontys University of Applied Sciences",[],{},{"nodeType":68,"value":609,"marks":610,"data":611},", where I gave a lecture on ",[],{},{"nodeType":68,"value":613,"marks":614,"data":616},"tech career paths",[615],{"type":73},{},{"nodeType":68,"value":618,"marks":619,"data":620},", choices and chasing opportunities when they arise. (\"",[],{},{"nodeType":68,"value":622,"marks":623,"data":625},"Core values matter!",[624],{"type":73},{},{"nodeType":68,"value":627,"marks":628,"data":629},"\"). I also gave a talk on ",[],{},{"nodeType":68,"value":631,"marks":632,"data":634},"Design Systems",[633],{"type":73},{},{"nodeType":68,"value":636,"marks":637,"data":638}," to students, on the various shapes and sizes you will encounter in the wild. Hopefully preparing them for a future in UI/UX and Frontend Development.",[],{},{"nodeType":106,"data":640,"content":641},{},[642,646,651,655,660],{"nodeType":68,"value":643,"marks":644,"data":645},"The best, however, was a guest lecture on AI: how it works (or not) ",[],{},{"nodeType":68,"value":647,"marks":648,"data":650},"for kids ages 10",[649],{"type":73},{},{"nodeType":68,"value":652,"marks":653,"data":654},"–",[],{},{"nodeType":68,"value":656,"marks":657,"data":659},"12",[658],{"type":73},{},{"nodeType":68,"value":661,"marks":662,"data":663},". We discovered how AI works under the hood and had lively discussions on all topics related to AI in general. It was super fun, with loads of engagement from both students as well as teachers and we went way over time! 🧠 My son's class was part of the audience and I even received lots of feedback from his peers in the following weeks! I've already been invited to return next year. Was an absolute highlight!",[],{},{"nodeType":148,"data":665,"content":666},{},[667],{"nodeType":68,"value":668,"marks":669,"data":670},"Program Committee",[],{},{"nodeType":106,"data":672,"content":673},{},[674,678,686,690,698],{"nodeType":68,"value":675,"marks":676,"data":677},"I've continued my program committee activities for ",[],{},{"nodeType":539,"data":679,"content":681},{"uri":680},"https://jsnation.com/#committee",[682],{"nodeType":68,"value":683,"marks":684,"data":685},"JS Nation",[],{},{"nodeType":68,"value":687,"marks":688,"data":689}," & ",[],{},{"nodeType":539,"data":691,"content":693},{"uri":692},"https://jsnation.us/#committee",[694],{"nodeType":68,"value":695,"marks":696,"data":697},"JS Nation US",[],{},{"nodeType":68,"value":699,"marks":700,"data":701},". It's still a seat that I'm very grateful for and proud of. The venue this year was a new one, and it was a total blast again! We had great weather outdoors, and the venue is a great space to connect with people in the JavaScript ecosystem and make and meet new friends! Always great to be there!",[],{},{"nodeType":148,"data":703,"content":704},{},[705],{"nodeType":68,"value":706,"marks":707,"data":708},"FrontMania",[],{},{"nodeType":106,"data":710,"content":711},{},[712,716,723],{"nodeType":68,"value":713,"marks":714,"data":715},"Having been on stage for three years prior, this year I was an attendee at ",[],{},{"nodeType":539,"data":717,"content":719},{"uri":718},"https://frontmania.com/",[720],{"nodeType":68,"value":706,"marks":721,"data":722},[],{},{"nodeType":68,"value":724,"marks":725,"data":726},". Saw some nice talks this year. Particularly Nir Kaufman and Brecht De Ruyte stood out! I met in real life with one of my mentees. It was great to meet her in person, after having coached her during the COVID-19 period. Met new friends, high-fived old friends and rode a mechanical bull! 🙈",[],{},{"nodeType":517,"data":728,"content":729},{},[730],{"nodeType":68,"value":731,"marks":732,"data":733},"Career and work 🧑‍💻",[],{},{"nodeType":106,"data":735,"content":736},{},[737,741,749],{"nodeType":68,"value":738,"marks":739,"data":740},"I have some big news to share here. After the summer vacation period I accepted a position at ",[],{},{"nodeType":539,"data":742,"content":744},{"uri":743},"https://tapp.online",[745],{"nodeType":68,"value":746,"marks":747,"data":748},"Tapp",[],{},{"nodeType":68,"value":750,"marks":751,"data":752}," to help them grow and mature the frontend & tech parts of this scale-up. Tapp aims to make waves in the supply chain by offering fully recyclable dataloggers. ",[],{},{"nodeType":106,"data":754,"content":755},{},[756],{"nodeType":68,"value":757,"marks":758,"data":759},"Existing dataloggers are made up of plastics, print boards and lithium batteries. Tapp does things differently with a bare minimum of electronics, encased in cardboard. Cardboard is one of the products that's easy to recycle worldwide. At our scale, we're not going to change the market on our own, but we can make an impact and be exemplary in how things can be done.",[],{},{"nodeType":517,"data":761,"content":762},{},[763],{"nodeType":68,"value":764,"marks":765,"data":766},"More bucket list 🪣",[],{},{"nodeType":106,"data":768,"content":769},{},[770],{"nodeType":68,"value":771,"marks":772,"data":773},"Since there's more to life than work alone (and the things outside of work shape us even more), this section is just as important as the learning part!",[],{},{"nodeType":517,"data":775,"content":776},{},[777],{"nodeType":68,"value":778,"marks":779,"data":780},"See the world 🗺️",[],{},{"nodeType":148,"data":782,"content":783},{},[784],{"nodeType":68,"value":785,"marks":786,"data":787},"New Years' Eve in Alsace 🏰",[],{},{"nodeType":106,"data":789,"content":790},{},[791,795,803],{"nodeType":68,"value":792,"marks":793,"data":794},"We started out the year continuing our stay in Alsace region in France. On January 1st, we headed for ",[],{},{"nodeType":539,"data":796,"content":798},{"uri":797},"https://www.europapark.de/",[799],{"nodeType":68,"value":800,"marks":801,"data":802},"Europa Park",[],{},{"nodeType":68,"value":804,"marks":805,"data":806}," to kick off the new year with thrills and exciting rides. It was our first time in Europa Park and we had such good fun there. I think we'll return there some time to try the rides we weren't able to do (although we ticked of a lot of rides on that day already)!",[],{},{"nodeType":148,"data":808,"content":809},{},[810],{"nodeType":68,"value":811,"marks":812,"data":813},"Snowboarding in Sverige 🏂",[],{},{"nodeType":106,"data":815,"content":816},{},[817,821,829],{"nodeType":68,"value":818,"marks":819,"data":820},"We drove all the way up to Sweden once more (this time we borrows a gasoline-fueled car). We rented a cabin at ",[],{},{"nodeType":539,"data":822,"content":824},{"uri":823},"https://www.branas.se/en/",[825],{"nodeType":68,"value":826,"marks":827,"data":828},"Branäs",[],{},{"nodeType":68,"value":830,"marks":831,"data":832}," ski resort and stayed for 5 days of skiing and snowboarding. My son took snowboarding lessons and picked it up so fast! Both my kids are getting more experienced on the slopes and we were able to do somewhat longer treks down the mountains.",[],{},{"nodeType":106,"data":834,"content":835},{},[836],{"nodeType":68,"value":837,"marks":838,"data":839},"On the last day we booked a snowquad tour, to celebrate the birthdays of my daughter and me. It was sunny, snowy and a lot of fun to be able to traverse any terrain on snow-tracked quads!",[],{},{"nodeType":148,"data":841,"content":842},{},[843],{"nodeType":68,"value":844,"marks":845,"data":846},"Spring in Sweden (Sverige revisited) 🌼",[],{},{"nodeType":106,"data":848,"content":849},{},[850],{"nodeType":68,"value":851,"marks":852,"data":853},"We have been exploring the option of seeking out a quieter life and have been exploring Sweden as an option for a more extended visit. We love the abundance of nature: forests and lakes, mountains, wide views. We spent a week in a lakeside cabin, enjoying the sauna, forests and rowing out on the lake. The following week we spent in an old farmhouse, going on moose safari and hiking in nature. It was great to recharge there with the four of us.",[],{},{"nodeType":148,"data":855,"content":856},{},[857],{"nodeType":68,"value":858,"marks":859,"data":860},"Hiking in Luxembourg 🇱🇺",[],{},{"nodeType":106,"data":862,"content":863},{},[864],{"nodeType":68,"value":865,"marks":866,"data":867},"In May we had a short stay in Luxembourg, in the Muellerthal region. With some of the most stunning hikes of Northwestern Europe, we had a couple of active days! The hikes were very suited for our kids as well. We explored caves, forests and lookouts on the various trails. We visited the capital of Luxembourg, using the free public transport, on a hot, humid day which ended in a massive thunderstorm. We were home in time!",[],{},{"nodeType":106,"data":869,"content":870},{},[871],{"nodeType":68,"value":872,"marks":873,"data":874},"The house we stayed in was great: spacious backyard with chickens to tend to and a spectacular view of the rolling countryside hills! Ended our stay with a nice little cookout in that backyard with a view!",[],{},{"nodeType":148,"data":876,"content":877},{},[878],{"nodeType":68,"value":879,"marks":880,"data":881},"Amsterdam Conference ⛴️",[],{},{"nodeType":106,"data":883,"content":884},{},[885,889,896,900,908,912,920],{"nodeType":68,"value":886,"marks":887,"data":888},"As part of my activities on the program committee of ",[],{},{"nodeType":539,"data":890,"content":892},{"uri":891},"https://jsnation.com/",[893],{"nodeType":68,"value":683,"marks":894,"data":895},[],{},{"nodeType":68,"value":897,"marks":898,"data":899},", I stayed a few nights in Amsterdam. Visited the conference, obviously! Had a super nice dinner on the ",[],{},{"nodeType":539,"data":901,"content":903},{"uri":902},"https://www.kapiteinanna.nl/nl/over-kapitein-anna/het-schip/",[904],{"nodeType":68,"value":905,"marks":906,"data":907},"Kapitein Anna",[],{},{"nodeType":68,"value":909,"marks":910,"data":911}," boat and took some time to visit some museums as well, just aimlessly wandering through the city on my own. Particularly loved ",[],{},{"nodeType":539,"data":913,"content":915},{"uri":914},"https://www.mocomuseum.com/amsterdam/",[916],{"nodeType":68,"value":917,"marks":918,"data":919},"Moco Amsterdam",[],{},{"nodeType":68,"value":548,"marks":921,"data":922},[],{},{"nodeType":148,"data":924,"content":925},{},[926],{"nodeType":68,"value":927,"marks":928,"data":929},"Bon Bini Bonaire 🦩",[],{},{"nodeType":106,"data":931,"content":932},{},[933],{"nodeType":68,"value":934,"marks":935,"data":936},"This was, of course, the big one. Our summer holiday was well spent on the tiny Caribbean island of Bonaire. It's a Dutch special municipality and has had a history intertwined with Dutch colonial times. People speak Dutch there, which was a treat for our kids. While the island is small, we weren't ready to head home after a generous three weeks of exploring both the island and the coral reefs surrounding it.",[],{},{"nodeType":106,"data":938,"content":939},{},[940],{"nodeType":68,"value":941,"marks":942,"data":943},"We swam with (surfing) turtles, snorkelled all around the gorgeous reefs on Bonaire and even smaller \"Klein Bonaire\". My son got to do two introduction scuba dives (both of which my wife and I could accompany him). He was completely overwhelmed by the experience! We met a great friend there, who taught our kids to do free diving and took them snorkelling while my wife and I did the occasional dive together. Apart from diving with my wife, I buddied up with a couple of other buddies as well and did more than 10 dives during our stay. Couple of underwater highlights were the various squid, always in groups of four to fourteen, floating in a line. The swimming moray eels, big tarpons, green turtles and spotting the juvenile fish in the coral.",[],{},{"nodeType":106,"data":945,"content":946},{},[947],{"nodeType":68,"value":948,"marks":949,"data":950},"Another big highlight was stumbling upon (not literally) a turtle nest, spending some time with the researchers and ultimately being able to watch the last egg hatch and wish a tiny turtle good luck in its journey.",[],{},{"nodeType":106,"data":952,"content":953},{},[954],{"nodeType":68,"value":955,"marks":956,"data":957},"We went kayaking in mangrove forests, explored the national park Washington Slagbaai and the Indian inscriptions. Watched the big cruise ships arrive at port and leave again and our kids took surfing lessons.",[],{},{"nodeType":106,"data":959,"content":960},{},[961],{"nodeType":68,"value":962,"marks":963,"data":964},"Our home was a Home Exchange house, so we had a complete house to ourselves, including a spacious pool and a view of the wilderness (Kunuk) which is typical for the island. In the morning we spotted hummingbirds and in the evening, flocks of parrots would fly overhead, resting in some of the high cacti.",[],{},{"nodeType":106,"data":966,"content":967},{},[968],{"nodeType":68,"value":969,"marks":970,"data":971},"It was a great adventure and we weren't close to ready to leave the island. In fact, get ready for a big update!",[],{},{"nodeType":148,"data":973,"content":974},{},[975],{"nodeType":68,"value":976,"marks":977,"data":978},"Home Exchange 🧳",[],{},{"nodeType":106,"data":980,"content":981},{},[982,986,994],{"nodeType":68,"value":983,"marks":984,"data":985},"When traveling, we try to make use of ",[],{},{"nodeType":539,"data":987,"content":989},{"uri":988},"https://www.homeexchange.com/",[990],{"nodeType":68,"value":991,"marks":992,"data":993},"HomeExchange",[],{},{"nodeType":68,"value":995,"marks":996,"data":997},". It's a platform where individuals or families exchange their homes with each other for a period of time, typically for a vacation or holiday. HomeExchange allows people to experience different destinations and cultures while staying in the comfort of a home, rather than a hotel or other traditional accommodation.",[],{},{"nodeType":106,"data":999,"content":1000},{},[1001,1005],{"nodeType":68,"value":1002,"marks":1003,"data":1004},"💡 If you're interested in this, or want to sign up, feel free to use our referral code which nets you (and us) some Guest Points to start with: ",[],{},{"nodeType":68,"value":1006,"marks":1007,"data":1011},"lydia-b4aeb",[1008,1009],{"type":73},{"type":1010},"code",{},{"nodeType":517,"data":1013,"content":1014},{},[1015],{"nodeType":68,"value":1016,"marks":1017,"data":1018},"Health 🏋️",[],{},{"nodeType":106,"data":1020,"content":1021},{},[1022],{"nodeType":68,"value":1023,"marks":1024,"data":1025},"I hit the gym more frequently this year, especially ramped up exercise during the year. I think this came at the cost of cycling, since I didn't even come close to my yearly goal! 😳 I did pick up running again and it's going fine. A few years ago I had to quit due to a painful knee injury, but all seems okay again. Have to admit, I love running because you can do it everywhere! 🏃‍♂️",[],{},{"nodeType":106,"data":1027,"content":1028},{},[1029],{"nodeType":68,"value":1030,"marks":1031,"data":1032},"With the weights in the gym, I started to lift heavier and heavier by changing my program. My legs were already strong, but I added a lot of upper body strength this year. Hope to keep that up, since my gym membership was tied to my position at Jumbo and has ended in November.",[],{},{"nodeType":106,"data":1034,"content":1035},{},[1036],{"nodeType":68,"value":1037,"marks":1038,"data":1039},"I mostly forgot about my stand-up desk and used it infrequently. Should step that up now that I'm working from home almost 100% of the time. (I'm writing this now sitting on one of those awkward ergonomic wobbly stools. Takes some getting used to! 😅)",[],{},{"nodeType":1041,"data":1042,"content":1043},"heading-4",{},[1044],{"nodeType":68,"value":1045,"marks":1046,"data":1047},"Other random things I never did or experienced before:",[],{},{"nodeType":106,"data":1049,"content":1050},{},[1051],{"nodeType":68,"value":1052,"marks":1053,"data":1054},"We went indoor skydiving in one of those loud upright wind tunnels. It was fun! I wouldn't rule out the possibility of doing a real skydive at some point!",[],{},{"nodeType":106,"data":1056,"content":1057},{},[1058,1062,1070],{"nodeType":68,"value":1059,"marks":1060,"data":1061},"In ",[],{},{"nodeType":539,"data":1063,"content":1065},{"uri":1064},"https://efteling.com",[1066],{"nodeType":68,"value":1067,"marks":1068,"data":1069},"Efteling",[],{},{"nodeType":68,"value":1071,"marks":1072,"data":1073},", a theme park near us (which we love to frequent) I saw a call for models for a photoshoot. We've done this once before, for a New Years'-themed shoot and we signed up for this one as well. This shoot was to promote the newly built hotel and surrounding stores and themed area. We were invited to pose as hotel visitors. It was fun to do and netted us free tickets to visit the park once more. Great value! 🍄✨",[],{},{"nodeType":517,"data":1075,"content":1076},{},[1077],{"nodeType":68,"value":1078,"marks":1079,"data":1080},"The Big One",[],{},{"nodeType":106,"data":1082,"content":1083},{},[1084],{"nodeType":68,"value":1085,"marks":1086,"data":1087},"One of the things that we started to value, as a family, is getting more and getting the most out of family time. Our kids are 11 and 8 years old right now. The older they get, the less time they want to (and should) spend with their parents. With our Home Exchange adventures of the past years, we've come to value time together and shared adventure.",[],{},{"nodeType":106,"data":1089,"content":1090},{},[1091],{"nodeType":68,"value":1092,"marks":1093,"data":1094},"We found the perfect opportunity this year, where all things (work & private) aligned to make this happen. We're moving to Bonaire to live on the island for half a year. Our kids will go to school there (being taught in Dutch is a huge plus): they can slide into their respective school years. Once we return, our son will leave for the next step in education (this was his last year at elementary school) and our daughter will return to her current class.",[],{},{"nodeType":106,"data":1096,"content":1097},{},[1098],{"nodeType":68,"value":1099,"marks":1100,"data":1101},"With my new position at Tapp, I can work fully remote. I've opted to work part time for the time being, similar to my wife, so that we only have to work when our kids are in school. Once they get off, we're all set to take every afternoon, weekend and vacation to enjoy and explore the island at our own leisure.",[],{},{"nodeType":106,"data":1103,"content":1104},{},[1105],{"nodeType":68,"value":1106,"marks":1107,"data":1108},"We think it's a generous amount of quality time we can spend together before our eldest goes to middle school. Our kids will experience finding their bearings in a new country, making new friends and spend time in a more active lifestyle, aimed at watersports.",[],{},{"nodeType":106,"data":1110,"content":1111},{},[1112],{"nodeType":68,"value":1113,"marks":1114,"data":1115},"For us, parents, it's also a valuable learning experience: working abroad, finding our way around in a different country and making friends similar to what our kids will experience.",[],{},{"nodeType":106,"data":1117,"content":1118},{},[1119],{"nodeType":68,"value":1120,"marks":1121,"data":1122},"At this point, we're done with all of the necessary arrangements in housing, schools and mobility and we're almost done packing. We're bringing a lot this time (normally we tend to travel very light: just carry-on luggage), so it's high stakes Tetris at the moment. Just a few more nights and we're off. Very much looking forward to it! 🌴",[],{},{"nodeType":106,"data":1124,"content":1125},{},[1126],{"nodeType":68,"value":1127,"marks":1128,"data":1129},"",[],{},{"data":1131,"content":1132,"nodeType":371},{},[1133,1140,1205],{"data":1134,"content":1135,"nodeType":517},{},[1136],{"data":1137,"marks":1138,"value":1139,"nodeType":68},{},[],"Past year:",{"data":1141,"content":1142,"nodeType":1204},{},[1143,1164,1184],{"data":1144,"content":1145,"nodeType":1163},{},[1146],{"data":1147,"content":1148,"nodeType":106},{},[1149,1152,1160],{"data":1150,"marks":1151,"value":1127,"nodeType":68},{},[],{"data":1153,"content":1155,"nodeType":539},{"uri":1154},"/articles/2024-year-in-review",[1156],{"data":1157,"marks":1158,"value":1159,"nodeType":68},{},[],"2024 Year in review",{"data":1161,"marks":1162,"value":1127,"nodeType":68},{},[],"list-item",{"data":1165,"content":1166,"nodeType":1163},{},[1167],{"data":1168,"content":1169,"nodeType":106},{},[1170,1173,1181],{"data":1171,"marks":1172,"value":1127,"nodeType":68},{},[],{"data":1174,"content":1176,"nodeType":539},{"uri":1175},"/articles/2023-year-in-review",[1177],{"data":1178,"marks":1179,"value":1180,"nodeType":68},{},[],"2023 Year in review",{"data":1182,"marks":1183,"value":1127,"nodeType":68},{},[],{"data":1185,"content":1186,"nodeType":1163},{},[1187],{"data":1188,"content":1189,"nodeType":106},{},[1190,1193,1201],{"data":1191,"marks":1192,"value":1127,"nodeType":68},{},[],{"data":1194,"content":1196,"nodeType":539},{"uri":1195},"https://www.joranquinten.nl/articles/2022-year-in-review/",[1197],{"data":1198,"marks":1199,"value":1200,"nodeType":68},{},[],"2022 Year in review",{"data":1202,"marks":1203,"value":1127,"nodeType":68},{},[],"unordered-list",{"data":1206,"content":1207,"nodeType":106},{},[1208],{"data":1209,"marks":1210,"value":1127,"nodeType":68},{},[],[1212,1228],{"metadata":1213,"sys":1216,"fields":1225},{"tags":1214,"concepts":1215},[],[],{"space":1217,"id":1219,"type":16,"createdAt":1220,"updatedAt":1220,"environment":1221,"publishedVersion":384,"revision":23,"contentType":1223,"locale":28},{"sys":1218},{"type":12,"linkType":13,"id":14},"1iRUazD182kJhNnCxrQqox","2022-07-13T12:01:37.626Z",{"sys":1222},{"id":20,"type":12,"linkType":21},{"sys":1224},{"type":12,"linkType":26,"id":387},{"title":1226,"slug":1227},"Career","career",{"metadata":1229,"sys":1232,"fields":1241},{"tags":1230,"concepts":1231},[],[],{"space":1233,"id":1235,"type":16,"createdAt":1236,"updatedAt":1236,"environment":1237,"publishedVersion":418,"revision":23,"contentType":1239,"locale":28},{"sys":1234},{"type":12,"linkType":13,"id":14},"1b0AnpYJZ0gRBPG9wnjJPs","2023-01-03T15:02:23.758Z",{"sys":1238},{"id":20,"type":12,"linkType":21},{"sys":1240},{"type":12,"linkType":26,"id":387},{"title":1242,"slug":1243},"Reflection","reflection",{"metadata":1245,"sys":1248,"fields":1259},{"tags":1246,"concepts":1247},[],[],{"space":1249,"id":1251,"type":16,"createdAt":1252,"updatedAt":1253,"environment":1254,"publishedVersion":1256,"revision":418,"contentType":1257,"locale":28},{"sys":1250},{"type":12,"linkType":13,"id":14},"6fFj1wddlPnxz7ujGubIBB","2025-09-25T11:24:02.725Z","2025-09-25T11:27:03.882Z",{"sys":1255},{"id":20,"type":12,"linkType":21},101,{"sys":1258},{"type":12,"linkType":26,"id":27},{"title":1260,"published":1261,"slug":1262,"heroImage":1263,"body":1284,"tags":1933},"Upgrading Nuxt v3 to v4 under 30 minutes","2025-09-25","upgrading-nuxt-v3-to-v4-under-30-minutes",{"metadata":1264,"sys":1267,"fields":1275},{"tags":1265,"concepts":1266},[],[],{"space":1268,"id":1270,"type":41,"createdAt":1271,"updatedAt":1271,"environment":1272,"publishedVersion":1274,"revision":23,"locale":28},{"sys":1269},{"type":12,"linkType":13,"id":14},"38uIhYN61UJW2SUMyNo5hc","2023-02-02T15:04:20.856Z",{"sys":1273},{"id":20,"type":12,"linkType":21},12,{"title":1276,"description":1277,"file":1278},"Astronauts","Photo of three small cute toy astronauts in various poses. Image courtesy of Ju Guan @ Unsplash",{"url":1279,"details":1280,"fileName":1283,"contentType":57},"//images.ctfassets.net/mqwrag4of3hk/38uIhYN61UJW2SUMyNo5hc/63818ac536b42a85cac5a984fe7e1680/ju-guan-D-jLxBtEwaA-unsplash.jpg",{"size":1281,"image":1282},23952,{"width":496,"height":497},"ju-guan-D-jLxBtEwaA-unsplash.jpg",{"nodeType":371,"data":1285,"content":1286},{},[1287,1299,1330,1337,1344,1351,1358,1365,1372,1450,1457,1464,1471,1479,1498,1506,1513,1521,1529,1536,1544,1551,1559,1566,1574,1581,1589,1596,1608,1615,1622,1629,1692,1699,1792,1799,1806,1869,1876,1883,1926],{"nodeType":106,"data":1288,"content":1289},{},[1290,1295],{"nodeType":68,"value":1291,"marks":1292,"data":1294},"TL;DR: ",[1293],{"type":73},{},{"nodeType":68,"value":1296,"marks":1297,"data":1298},"I upgraded a 32k LOC Nuxt app from v3 to v4 in 29 minutes of actual work. Here's how it went and what I learned.",[],{},{"nodeType":106,"data":1300,"content":1301},{},[1302,1306,1314,1318,1326],{"nodeType":68,"value":1303,"marks":1304,"data":1305},"I'm maintaining a reasonably sized ",[],{},{"nodeType":539,"data":1307,"content":1309},{"uri":1308},"https://nuxt.com/",[1310],{"nodeType":68,"value":1311,"marks":1312,"data":1313},"Nuxt",[],{},{"nodeType":68,"value":1315,"marks":1316,"data":1317}," application - not massive, but substantial enough to make upgrade decisions matter. We're talking about a project (excluded tests here) with 32k lines of code spread across 173 files, with a healthy mix of 72 ",[],{},{"nodeType":539,"data":1319,"content":1321},{"uri":1320},"https://vuejs.org/",[1322],{"nodeType":68,"value":1323,"marks":1324,"data":1325},"Vue",[],{},{"nodeType":68,"value":1327,"marks":1328,"data":1329}," components and 44 TypeScript files. The dependency footprint includes 34 production dependencies plus 7 development ones. So, not that big, which makes it a perfect candidate for an upgrade scenario!",[],{},{"nodeType":106,"data":1331,"content":1332},{},[1333],{"nodeType":68,"value":1334,"marks":1335,"data":1336},"Since I was already on a very recent Nuxt 3 version, I figured this would be a good time to take the plunge into Nuxt 4. I was curious to see how smooth the migration path would be. ",[],{},{"nodeType":106,"data":1338,"content":1339},{},[1340],{"nodeType":68,"value":1341,"marks":1342,"data":1343},"Spoiler alert: smoother than expected, but with a few interesting bumps along the way!",[],{},{"nodeType":517,"data":1345,"content":1346},{},[1347],{"nodeType":68,"value":1348,"marks":1349,"data":1350},"What's a major framework upgrade?",[],{},{"nodeType":106,"data":1352,"content":1353},{},[1354],{"nodeType":68,"value":1355,"marks":1356,"data":1357},"Let's talk about what we're actually dealing with when we say \"major version upgrade\":",[],{},{"nodeType":106,"data":1359,"content":1360},{},[1361],{"nodeType":68,"value":1362,"marks":1363,"data":1364},"A major framework upgrade typically involves breaking changes that require intentional code modifications. These aren't just bug fixes or new features - they're architectural shifts that can affect how your application builds, runs, and behaves.",[],{},{"nodeType":106,"data":1366,"content":1367},{},[1368],{"nodeType":68,"value":1369,"marks":1370,"data":1371},"The upgrade usually touches several areas:",[],{},{"nodeType":1204,"data":1373,"content":1374},{},[1375,1390,1405,1420,1435],{"nodeType":1163,"data":1376,"content":1377},{},[1378],{"nodeType":106,"data":1379,"content":1380},{},[1381,1386],{"nodeType":68,"value":1382,"marks":1383,"data":1385},"API Changes",[1384],{"type":73},{},{"nodeType":68,"value":1387,"marks":1388,"data":1389},": Method signatures, configuration options, or component props that work differently",[],{},{"nodeType":1163,"data":1391,"content":1392},{},[1393],{"nodeType":106,"data":1394,"content":1395},{},[1396,1401],{"nodeType":68,"value":1397,"marks":1398,"data":1400},"Build System Updates",[1399],{"type":73},{},{"nodeType":68,"value":1402,"marks":1403,"data":1404},": How your code gets compiled and bundled",[],{},{"nodeType":1163,"data":1406,"content":1407},{},[1408],{"nodeType":106,"data":1409,"content":1410},{},[1411,1416],{"nodeType":68,"value":1412,"marks":1413,"data":1415},"Dependency Ecosystem",[1414],{"type":73},{},{"nodeType":68,"value":1417,"marks":1418,"data":1419},": Other packages in your stack that need to catch up",[],{},{"nodeType":1163,"data":1421,"content":1422},{},[1423],{"nodeType":106,"data":1424,"content":1425},{},[1426,1431],{"nodeType":68,"value":1427,"marks":1428,"data":1430},"File Structure",[1429],{"type":73},{},{"nodeType":68,"value":1432,"marks":1433,"data":1434},": Sometimes the way you organize your code needs to change",[],{},{"nodeType":1163,"data":1436,"content":1437},{},[1438],{"nodeType":106,"data":1439,"content":1440},{},[1441,1446],{"nodeType":68,"value":1442,"marks":1443,"data":1445},"Type Definitions",[1444],{"type":73},{},{"nodeType":68,"value":1447,"marks":1448,"data":1449},": If you're using TypeScript, the type contracts might shift",[],{},{"nodeType":106,"data":1451,"content":1452},{},[1453],{"nodeType":68,"value":1454,"marks":1455,"data":1456},"In Nuxt's case, version 4 represents a significant step forward in their architectural vision, building on the solid foundation of Nuxt 3 but with some important refinements and improvements.",[],{},{"nodeType":106,"data":1458,"content":1459},{},[1460],{"nodeType":68,"value":1461,"marks":1462,"data":1463},"It's worth noting that Nuxt no longer follows Vue's major version numbers like it used to. In the early days, Nuxt 2 corresponded with Vue 2, and there was an expectation that framework versions would stay aligned. However, the Nuxt team realized this created unnecessary coupling between two different release cycles. Vue focuses on the reactive framework and component system, while Nuxt deals with the full-stack application layer, build tooling, and developer experience. These concerns evolve at different paces and have different breaking change considerations. By decoupling version numbers, Nuxt can iterate on its own architectural improvements without being constrained by Vue's release timeline, and vice versa. This independence actually benefits both ecosystems - Vue can focus on its core strengths while Nuxt can evolve its application framework features more naturally.",[],{},{"nodeType":517,"data":1465,"content":1466},{},[1467],{"nodeType":68,"value":1468,"marks":1469,"data":1470},"The upgrade journey: an honest timeline ⏱️",[],{},{"nodeType":106,"data":1472,"content":1473},{},[1474],{"nodeType":68,"value":1475,"marks":1476,"data":1478},"12:17 - The optimistic start",[1477],{"type":73},{},{"nodeType":106,"data":1480,"content":1481},{},[1482,1486,1494],{"nodeType":68,"value":1483,"marks":1484,"data":1485},"Like any good developer, I started with the ",[],{},{"nodeType":539,"data":1487,"content":1489},{"uri":1488},"https://nuxt.com/docs/4.x/getting-started/upgrade",[1490],{"nodeType":68,"value":1491,"marks":1492,"data":1493},"official approach",[],{},{"nodeType":68,"value":1495,"marks":1496,"data":1497},":",[],{},{"nodeType":106,"data":1499,"content":1500},{},[1501],{"nodeType":68,"value":1502,"marks":1503,"data":1505},"npx nuxt upgrade",[1504],{"type":1010},{},{"nodeType":106,"data":1507,"content":1508},{},[1509],{"nodeType":68,"value":1510,"marks":1511,"data":1512},"Well, that failed. Not entirely surprising: official upgrade tools are great when they work, but they can't account for every project's unique setup. No worries, let's move to plan B.",[],{},{"nodeType":106,"data":1514,"content":1515},{},[1516],{"nodeType":68,"value":1517,"marks":1518,"data":1520},"Manual approach (plan B):",[1519],{"type":73},{},{"nodeType":106,"data":1522,"content":1523},{},[1524],{"nodeType":68,"value":1525,"marks":1526,"data":1528},"npm install nuxt@^4.0.0npx\ncodemod@latest nuxt/4/migration-recipe",[1527],{"type":1010},{},{"nodeType":106,"data":1530,"content":1531},{},[1532],{"nodeType":68,"value":1533,"marks":1534,"data":1535},"The codemod did its thing, making some structural changes, but I held off on running npm install just yet. Sometimes it's better to see what breaks before fixing the dependencies.",[],{},{"nodeType":106,"data":1537,"content":1538},{},[1539],{"nodeType":68,"value":1540,"marks":1541,"data":1543},"12:23 - Dependency updates",[1542],{"type":73},{},{"nodeType":106,"data":1545,"content":1546},{},[1547],{"nodeType":68,"value":1548,"marks":1549,"data":1550},"The dependency updates began in earnest. Started with a general npm install, which highlighted the peer dependency conflicts I expected. Then I got targeted with the packages that needed attention:",[],{},{"nodeType":106,"data":1552,"content":1553},{},[1554],{"nodeType":68,"value":1555,"marks":1556,"data":1558},"npm install @nuxt/scripts@latest\nnpm install @vueuse/nuxt@latest",[1557],{"type":1010},{},{"nodeType":106,"data":1560,"content":1561},{},[1562],{"nodeType":68,"value":1563,"marks":1564,"data":1565},"PrimeVue also needed a bump to stay compatible.",[],{},{"nodeType":106,"data":1567,"content":1568},{},[1569],{"nodeType":68,"value":1570,"marks":1571,"data":1573},"12:36 - File reference fixes",[1572],{"type":73},{},{"nodeType":106,"data":1575,"content":1576},{},[1577],{"nodeType":68,"value":1578,"marks":1579,"data":1580},"This is where the real work began. Nuxt 4 has some differences in folder structure and conventions. I spent time updating import paths and file references. Nothing dramatic, just the kind of changes that codemods sometimes miss.",[],{},{"nodeType":106,"data":1582,"content":1583},{},[1584],{"nodeType":68,"value":1585,"marks":1586,"data":1588},"12:40 - Types and resolvers",[1587],{"type":73},{},{"nodeType":106,"data":1590,"content":1591},{},[1592],{"nodeType":68,"value":1593,"marks":1594,"data":1595},"The TypeScript definitions needed some love, and a few resolver configurations had to be updated. Again, these were focused changes rather than broad rewrites.",[],{},{"nodeType":106,"data":1597,"content":1598},{},[1599,1604],{"nodeType":68,"value":1600,"marks":1601,"data":1603},"12:46 - Stop the clock! 🎉",[1602],{"type":73},{},{"nodeType":68,"value":1605,"marks":1606,"data":1607}," ",[],{},{"nodeType":106,"data":1609,"content":1610},{},[1611],{"nodeType":68,"value":1612,"marks":1613,"data":1614},"App was running smoothly. Total active work time: 29 minutes.",[],{},{"nodeType":517,"data":1616,"content":1617},{},[1618],{"nodeType":68,"value":1619,"marks":1620,"data":1621},"What made this upgrade smooth?",[],{},{"nodeType":106,"data":1623,"content":1624},{},[1625],{"nodeType":68,"value":1626,"marks":1627,"data":1628},"Several factors contributed to the relatively painless experience:",[],{},{"nodeType":1204,"data":1630,"content":1631},{},[1632,1647,1662,1677],{"nodeType":1163,"data":1633,"content":1634},{},[1635],{"nodeType":106,"data":1636,"content":1637},{},[1638,1643],{"nodeType":68,"value":1639,"marks":1640,"data":1642},"Recent starting point",[1641],{"type":73},{},{"nodeType":68,"value":1644,"marks":1645,"data":1646},": I was already on a very recent Nuxt 3 version, which meant I wasn't carrying forward old technical debt or deprecated patterns.",[],{},{"nodeType":1163,"data":1648,"content":1649},{},[1650],{"nodeType":106,"data":1651,"content":1652},{},[1653,1658],{"nodeType":68,"value":1654,"marks":1655,"data":1657},"AI-assisted troubleshooting",[1656],{"type":73},{},{"nodeType":68,"value":1659,"marks":1660,"data":1661},": I used Claude to help resolve some errors and interpret documentation. Having an AI assistant review error messages and suggest solutions definitely accelerated the debugging process.",[],{},{"nodeType":1163,"data":1663,"content":1664},{},[1665],{"nodeType":106,"data":1666,"content":1667},{},[1668,1673],{"nodeType":68,"value":1669,"marks":1670,"data":1672},"Focused scope",[1671],{"type":73},{},{"nodeType":68,"value":1674,"marks":1675,"data":1676},": The changes were mostly mechanical - updating imports, tweaking configurations, and bumping dependencies. No major architectural rewrites required.",[],{},{"nodeType":1163,"data":1678,"content":1679},{},[1680],{"nodeType":106,"data":1681,"content":1682},{},[1683,1688],{"nodeType":68,"value":1684,"marks":1685,"data":1687},"Good foundation",[1686],{"type":73},{},{"nodeType":68,"value":1689,"marks":1690,"data":1691},": The existing codebase was well-structured with clear separation of concerns, which made it easier to identify what needed changing.",[],{},{"nodeType":517,"data":1693,"content":1694},{},[1695],{"nodeType":68,"value":1696,"marks":1697,"data":1698},"Lessons learned and practical tips ✍️",[],{},{"nodeType":1204,"data":1700,"content":1701},{},[1702,1717,1732,1747,1762,1777],{"nodeType":1163,"data":1703,"content":1704},{},[1705],{"nodeType":106,"data":1706,"content":1707},{},[1708,1713],{"nodeType":68,"value":1709,"marks":1710,"data":1712},"Start with the official tools, but don't depend on them",[1711],{"type":73},{},{"nodeType":68,"value":1714,"marks":1715,"data":1716},": While the nuxt upgrade command failed for me, but that's not necessarily a bad thing. Sometimes manual upgrades give you better control and understanding of what's changing.",[],{},{"nodeType":1163,"data":1718,"content":1719},{},[1720],{"nodeType":106,"data":1721,"content":1722},{},[1723,1728],{"nodeType":68,"value":1724,"marks":1725,"data":1727},"AI assistance is a game-changer",[1726],{"type":73},{},{"nodeType":68,"value":1729,"marks":1730,"data":1731},": Having Claude help interpret error messages and suggest solutions significantly reduced the time I spent stuck on individual issues. It's like having a very knowledgeable pair programming partner who's read all the documentation.",[],{},{"nodeType":1163,"data":1733,"content":1734},{},[1735],{"nodeType":106,"data":1736,"content":1737},{},[1738,1743],{"nodeType":68,"value":1739,"marks":1740,"data":1742},"Dependency timing matters",[1741],{"type":73},{},{"nodeType":68,"value":1744,"marks":1745,"data":1746},": Being on a recent version of the previous major made all the difference. If I'd been on an older Nuxt 3 version, I might have had to deal with accumulated breaking changes rather than just the v3 to v4 delta.",[],{},{"nodeType":1163,"data":1748,"content":1749},{},[1750],{"nodeType":106,"data":1751,"content":1752},{},[1753,1758],{"nodeType":68,"value":1754,"marks":1755,"data":1757},"Think before you code",[1756],{"type":73},{},{"nodeType":68,"value":1759,"marks":1760,"data":1761},": Taking time to understand what needs changing rather than just reacting to each error as it comes up leads to more focused solutions.",[],{},{"nodeType":1163,"data":1763,"content":1764},{},[1765],{"nodeType":106,"data":1766,"content":1767},{},[1768,1773],{"nodeType":68,"value":1769,"marks":1770,"data":1772},"Focus on the critical path",[1771],{"type":73},{},{"nodeType":68,"value":1774,"marks":1775,"data":1776},": I didn't try to optimize everything at once. Get it working first, then improve. The upgrade revealed some areas for future optimization, but those weren't blocking issues.",[],{},{"nodeType":1163,"data":1778,"content":1779},{},[1780],{"nodeType":106,"data":1781,"content":1782},{},[1783,1788],{"nodeType":68,"value":1784,"marks":1785,"data":1787},"Choose the right moment:",[1786],{"type":73},{},{"nodeType":68,"value":1789,"marks":1790,"data":1791}," I waited a while before running the upgrade, since I had a couple of dependencies (PrimeVue mostly) that needed some time for compatibility. This ensures that some of the initial friction and kinks are ironed out before I apply them.\n",[],{},{"nodeType":517,"data":1793,"content":1794},{},[1795],{"nodeType":68,"value":1796,"marks":1797,"data":1798},"Why this matters 🎯",[],{},{"nodeType":106,"data":1800,"content":1801},{},[1802],{"nodeType":68,"value":1803,"marks":1804,"data":1805},"Framework upgrades often feel like massive undertakings, but this experience reinforces that they don't have to be. The key is preparation and approach:",[],{},{"nodeType":1204,"data":1807,"content":1808},{},[1809,1824,1839,1854],{"nodeType":1163,"data":1810,"content":1811},{},[1812],{"nodeType":106,"data":1813,"content":1814},{},[1815,1820],{"nodeType":68,"value":1816,"marks":1817,"data":1819},"Know your starting point",[1818],{"type":73},{},{"nodeType":68,"value":1821,"marks":1822,"data":1823},": Understanding your codebase size, dependency footprint, and current version helps set realistic expectations.",[],{},{"nodeType":1163,"data":1825,"content":1826},{},[1827],{"nodeType":106,"data":1828,"content":1829},{},[1830,1835],{"nodeType":68,"value":1831,"marks":1832,"data":1834},"Use the right tools",[1833],{"type":73},{},{"nodeType":68,"value":1836,"marks":1837,"data":1838},": Codemods, AI assistance, and good version control make the process much more manageable.",[],{},{"nodeType":1163,"data":1840,"content":1841},{},[1842],{"nodeType":106,"data":1843,"content":1844},{},[1845,1850],{"nodeType":68,"value":1846,"marks":1847,"data":1849},"Accept that not everything moves at the same pace",[1848],{"type":73},{},{"nodeType":68,"value":1851,"marks":1852,"data":1853},": Some packages in the ecosystem might lag behind major releases, and that's okay. You can work around it or wait for compatibility updates.",[],{},{"nodeType":1163,"data":1855,"content":1856},{},[1857],{"nodeType":106,"data":1858,"content":1859},{},[1860,1865],{"nodeType":68,"value":1861,"marks":1862,"data":1864},"Measure what matters",[1863],{"type":73},{},{"nodeType":68,"value":1866,"marks":1867,"data":1868},": The 29-minute active work time is a useful metric, but so is the fact that the app remained stable and performant after the upgrade.",[],{},{"nodeType":517,"data":1870,"content":1871},{},[1872],{"nodeType":68,"value":1873,"marks":1874,"data":1875},"The bigger picture 🌌",[],{},{"nodeType":106,"data":1877,"content":1878},{},[1879],{"nodeType":68,"value":1880,"marks":1881,"data":1882},"Most of the upgrade is owed to the work of the Nuxt team. Big applause to all contributors! ",[],{},{"nodeType":1204,"data":1884,"content":1885},{},[1886,1896,1906,1916],{"nodeType":1163,"data":1887,"content":1888},{},[1889],{"nodeType":106,"data":1890,"content":1891},{},[1892],{"nodeType":68,"value":1893,"marks":1894,"data":1895},"The Nuxt team has invested heavily in migration tooling",[],{},{"nodeType":1163,"data":1897,"content":1898},{},[1899],{"nodeType":106,"data":1900,"content":1901},{},[1902],{"nodeType":68,"value":1903,"marks":1904,"data":1905},"The ecosystem has caught up with v4 compatibility",[],{},{"nodeType":1163,"data":1907,"content":1908},{},[1909],{"nodeType":106,"data":1910,"content":1911},{},[1912],{"nodeType":68,"value":1913,"marks":1914,"data":1915},"The codebase was already following modern patterns",[],{},{"nodeType":1163,"data":1917,"content":1918},{},[1919],{"nodeType":106,"data":1920,"content":1921},{},[1922],{"nodeType":68,"value":1923,"marks":1924,"data":1925},"I had the right tools and assistance available",[],{},{"nodeType":106,"data":1927,"content":1928},{},[1929],{"nodeType":68,"value":1930,"marks":1931,"data":1932},"Not every upgrade will be this smooth, but when the conditions align, it's surprisingly achievable to make major version jumps without major drama. I remember the upgrade from v2 to v3. This was way better, which was the intention of having shorter release cycles in the first place! Having a community which prioritizes Developer Experience is such a joy to work with! 💚",[],{},[1934,1949,407,1965,424,440],{"metadata":1935,"sys":1938,"fields":1947},{"tags":1936,"concepts":1937},[],[],{"space":1939,"id":1941,"type":16,"createdAt":1942,"updatedAt":1942,"environment":1943,"publishedVersion":418,"revision":23,"contentType":1945,"locale":28},{"sys":1940},{"type":12,"linkType":13,"id":14},"1LhhGqjzyvyvopxBdoyhPh","2025-06-10T11:20:11.842Z",{"sys":1944},{"id":20,"type":12,"linkType":21},{"sys":1946},{"type":12,"linkType":26,"id":387},{"title":1323,"slug":1948},"vue",{"metadata":1950,"sys":1953,"fields":1962},{"tags":1951,"concepts":1952},[],[],{"space":1954,"id":1956,"type":16,"createdAt":1957,"updatedAt":1957,"environment":1958,"publishedVersion":418,"revision":23,"contentType":1960,"locale":28},{"sys":1955},{"type":12,"linkType":13,"id":14},"5HyiSWd1pWaS8lD8FQLTJo","2023-03-07T14:53:10.764Z",{"sys":1959},{"id":20,"type":12,"linkType":21},{"sys":1961},{"type":12,"linkType":26,"id":387},{"title":1963,"slug":1964},"Frameworks","frameworks",{"metadata":1966,"sys":1969,"fields":1978},{"tags":1967,"concepts":1968},[],[],{"space":1970,"id":1972,"type":16,"createdAt":1973,"updatedAt":1973,"environment":1974,"publishedVersion":418,"revision":23,"contentType":1976,"locale":28},{"sys":1971},{"type":12,"linkType":13,"id":14},"5SlAD5NA7eAswGfHG0bS2R","2022-11-07T21:13:48.199Z",{"sys":1975},{"id":20,"type":12,"linkType":21},{"sys":1977},{"type":12,"linkType":26,"id":387},{"title":1311,"slug":1979},"nuxt",{"metadata":1981,"sys":1984,"fields":1994},{"tags":1982,"concepts":1983},[],[],{"space":1985,"id":1987,"type":16,"createdAt":1988,"updatedAt":1988,"environment":1989,"publishedVersion":1991,"revision":23,"contentType":1992,"locale":28},{"sys":1986},{"type":12,"linkType":13,"id":14},"2orb3JgUhlFSlK6GcmLauG","2025-06-16T08:31:02.905Z",{"sys":1990},{"id":20,"type":12,"linkType":21},423,{"sys":1993},{"type":12,"linkType":26,"id":27},{"title":1995,"published":1996,"slug":1997,"heroImage":1998,"body":2021,"sidebar":2507,"tags":2564},"From Vue to Google Play Store – Building & Publishing a Native Android App with Quasar","2025-06-03","publishing-a-vue-app-native-android-google-play-store-quasar",{"metadata":1999,"sys":2002,"fields":2010},{"tags":2000,"concepts":2001},[],[],{"space":2003,"id":2005,"type":41,"createdAt":2006,"updatedAt":2006,"environment":2007,"publishedVersion":2009,"revision":23,"locale":28},{"sys":2004},{"type":12,"linkType":13,"id":14},"ISNSkRatRaSGaIdMWpC1J","2025-06-05T07:10:58.450Z",{"sys":2008},{"id":20,"type":12,"linkType":21},14,{"title":2011,"description":2012,"file":2013},"Different screens of the Doorrekenen app","A combination of different mocks of an Android phone which displays screens of the app, which clearly shows that it an app that deals with calculations.",{"url":2014,"details":2015,"fileName":2019,"contentType":2020},"//images.ctfassets.net/mqwrag4of3hk/ISNSkRatRaSGaIdMWpC1J/d40196ae3a221130ceddd360a1dba9e1/functieafbeelding.jpg",{"size":2016,"image":2017},111929,{"width":496,"height":2018},352,"functieafbeelding.jpg","image/png",{"nodeType":371,"data":2022,"content":2023},{},[2024,2031,2050,2057,2088,2095,2102,2109,2116,2123,2130,2137,2144,2151,2158,2176,2184,2191,2205,2212,2220,2239,2246,2253,2260,2267,2274,2293,2300,2331,2338,2345,2352,2359,2366,2373,2380,2411,2430,2437,2444,2451,2458,2465,2472,2479,2486,2493,2500],{"nodeType":517,"data":2025,"content":2026},{},[2027],{"nodeType":68,"value":2028,"marks":2029,"data":2030},"Why I Built a Multiplication App with Vue & Quasar",[],{},{"nodeType":106,"data":2032,"content":2033},{},[2034,2038,2046],{"nodeType":68,"value":2035,"marks":2036,"data":2037},"I recently completed a rite of passage: I've published my ",[],{},{"nodeType":539,"data":2039,"content":2041},{"uri":2040},"https://play.google.com/store/apps/details?id=nl.doorrekenen.app",[2042],{"nodeType":68,"value":2043,"marks":2044,"data":2045},"first app in the Google Play app store",[],{},{"nodeType":68,"value":2047,"marks":2048,"data":2049},". The reason for going through this was two fold: I was aware of the capacities of multiplatform builds using my favorite framework of choice and wanted to explore how this would pan out in practice. At the same time, the perfect opportunity presented itself: my kids were practicing tables of multiplication and to me, that seemed a perfect challenge to build an app for!",[],{},{"nodeType":106,"data":2051,"content":2052},{},[2053],{"nodeType":68,"value":2054,"marks":2055,"data":2056},"So the app I built is a learning game. You get to choose what tables you want to practice and supports different practice modes. In order to achieve this, I built several screens which allow you to configure your practice runs, do the actual practive and show you the results. Since it's built for kids, I added a bit of whimsical options and made sure that personal privacy was paramount: no data collection, no profiling, nothing.",[],{},{"nodeType":106,"data":2058,"content":2059},{},[2060,2064,2072,2076,2084],{"nodeType":68,"value":2061,"marks":2062,"data":2063},"As I said, I was aware of the cross platform capabilities, having built desktop apps before (also while wokring on ",[],{},{"nodeType":539,"data":2065,"content":2067},{"uri":2066},"https://untitled+.vscode-resource.vscode-cdn.net/books",[2068],{"nodeType":68,"value":2069,"marks":2070,"data":2071},"my book",[],{},{"nodeType":68,"value":2073,"marks":2074,"data":2075},"). I never however, went through with building an app and the Play Store publishing process. I chose to use ",[],{},{"nodeType":539,"data":2077,"content":2079},{"uri":2078},"https://quasar.dev/",[2080],{"nodeType":68,"value":2081,"marks":2082,"data":2083},"Quasar",[],{},{"nodeType":68,"value":2085,"marks":2086,"data":2087}," for building this, since it has first class support for cross platform builds built in.",[],{},{"nodeType":517,"data":2089,"content":2090},{},[2091],{"nodeType":68,"value":2092,"marks":2093,"data":2094},"Choosing Quasar: Vue-Powered and Mobile-Ready",[],{},{"nodeType":106,"data":2096,"content":2097},{},[2098],{"nodeType":68,"value":2099,"marks":2100,"data":2101},"My goal was not to learn the app building and publishing process, not get into new tech. So I chose to use a tech stack that I'm very familiar with: Vue and Quasar. It also helped that I built some apps with Quasar in the past, so I could easily get my bearings there.",[],{},{"nodeType":106,"data":2103,"content":2104},{},[2105],{"nodeType":68,"value":2106,"marks":2107,"data":2108},"Quasar is a framework built on vue to help with cross platform development. It's truly a build once, deploy everywhere approach. While the Nuxt developer experience (DX) is top notch, Quasar's is actually not far behind in terms of DX. It's a joy to work with. You do have to get used to small changes in the project setup though. Luckily, the documentation explains it all!",[],{},{"nodeType":106,"data":2110,"content":2111},{},[2112],{"nodeType":68,"value":2113,"marks":2114,"data":2115},"It also offers a handy library of cross platform components, so that you can quickly scaffold out a varied range of interactive screens.",[],{},{"nodeType":106,"data":2117,"content":2118},{},[2119],{"nodeType":68,"value":2120,"marks":2121,"data":2122},"Lastly, the CLI offers built in tooling for all the operations you need in order to build assets and build the package.",[],{},{"nodeType":517,"data":2124,"content":2125},{},[2126],{"nodeType":68,"value":2127,"marks":2128,"data":2129},"Building the App: From Idea to Working UI",[],{},{"nodeType":106,"data":2131,"content":2132},{},[2133],{"nodeType":68,"value":2134,"marks":2135,"data":2136},"For the project itself, I did nothing special to be honest. This was fine, and perfectly in line with what I set out to achieve. I did learn about some caveats between booting an app and running a (Nuxt based) web application, but that's expected when switching metaframeworks and everything was well documented.",[],{},{"nodeType":106,"data":2138,"content":2139},{},[2140],{"nodeType":68,"value":2141,"marks":2142,"data":2143},"If we're being completely honest: I have to admit that I first built the app as a plain SPA using just Vue. This proved valuable in early user testing. I later ported it to Quasar without much effort: moving around components isn't that big of a deal after all.",[],{},{"nodeType":106,"data":2145,"content":2146},{},[2147],{"nodeType":68,"value":2148,"marks":2149,"data":2150},"I did have a lot of fun with user testing, since my test panel were my own two kids (10 and 8 years old). They did not hold back on the comments! Together we came up with different play modes as well, which was a fun exercise. And for them, it became a bit more tangible what I do \"on the laptop\" all day, for a living!",[],{},{"nodeType":517,"data":2152,"content":2153},{},[2154],{"nodeType":68,"value":2155,"marks":2156,"data":2157},"Turning it into a Native Android App",[],{},{"nodeType":106,"data":2159,"content":2160},{},[2161,2164,2172],{"nodeType":68,"value":1127,"marks":2162,"data":2163},[],{},{"nodeType":539,"data":2165,"content":2167},{"uri":2166},"https://capacitorjs.com/",[2168],{"nodeType":68,"value":2169,"marks":2170,"data":2171},"Capacitor",[],{},{"nodeType":68,"value":2173,"marks":2174,"data":2175}," has been a standard in terms of enabling cross platform development. Quasar exposes the option of adding that build mode to your project. After that, building for Android becomes easy, with the Quasar CLI, as you can see below (excerpt from my package.json):",[],{},{"nodeType":106,"data":2177,"content":2178},{},[2179],{"nodeType":68,"value":2180,"marks":2181,"data":2183},"quasar build -m capacitor -T android -d",[2182],{"type":1010},{},{"nodeType":106,"data":2185,"content":2186},{},[2187],{"nodeType":68,"value":2188,"marks":2189,"data":2190},"The resulting APK can be installed on your Android device by manually opening it from your favorite file manager. Milestone achieved! I used the APK for quick tests on my own device, which was basically the only reason for building them.",[],{},{"nodeType":106,"data":2192,"content":2193},{},[2194,2199],{"nodeType":68,"value":2195,"marks":2196,"data":2198},"Sidenote:",[2197],{"type":73},{},{"nodeType":68,"value":2200,"marks":2201,"data":2204}," I had Android Studio already installed, so I'm not entirely sure whether that's a prerequisite for the builds. It's recommended to install it anyway to be able to run your native app on an emulator.",[2202],{"type":2203},"italic",{},{"nodeType":106,"data":2206,"content":2207},{},[2208],{"nodeType":68,"value":2209,"marks":2210,"data":2211},"For building I relied on the CLI as much as possible. In order to be able to publish your app to the Play Store, an APK will not suffice! You need to provide a bundle of the app. This is my script for building the initial bundle:",[],{},{"nodeType":106,"data":2213,"content":2214},{},[2215],{"nodeType":68,"value":2216,"marks":2217,"data":2219},"cd src-capacitor/android && ./gradlew bundleRelease",[2218],{"type":1010},{},{"nodeType":106,"data":2221,"content":2222},{},[2223,2227,2235],{"nodeType":68,"value":2224,"marks":2225,"data":2226},"That script stores the .aab file deep in the src-capacitor directory, but that's fine! Next is the signing process. To sign an .aab file, I used jarsigner. This is the part where I needed to do some Doc reading, Stack Overflowing, Googling and Vibe Coding. I started out with the docs on ",[],{},{"nodeType":539,"data":2228,"content":2230},{"uri":2229},"https://quasar.dev/quasar-cli-vite/developing-capacitor-apps/publishing-to-store#android-publishing",[2231],{"nodeType":68,"value":2232,"marks":2233,"data":2234},"Publishing to Store by Quasar",[],{},{"nodeType":68,"value":2236,"marks":2237,"data":2238},", but the APK part seems outdated at this point.",[],{},{"nodeType":106,"data":2240,"content":2241},{},[2242],{"nodeType":68,"value":2243,"marks":2244,"data":2245},"I ended up using jarsigner together with the generated key to sign the bundle. Next, I was ready for the Play Store.",[],{},{"nodeType":106,"data":2247,"content":2248},{},[2249],{"nodeType":68,"value":2250,"marks":2251,"data":2252},"Or so I thought!",[],{},{"nodeType":517,"data":2254,"content":2255},{},[2256],{"nodeType":68,"value":2257,"marks":2258,"data":2259},"Publishing to Google Play: The Full Process",[],{},{"nodeType":106,"data":2261,"content":2262},{},[2263],{"nodeType":68,"value":2264,"marks":2265,"data":2266},"Man, this was the difficult step! Obviously I was blissfully unaware of all the hoops you have to jump through to get an app published in the store! In hindsight: building something for children meant stricter checks as well, so I added a bit of a challenge there, inadvertently.",[],{},{"nodeType":106,"data":2268,"content":2269},{},[2270],{"nodeType":68,"value":2271,"marks":2272,"data":2273},"Creating a Google Play developer account was simple enough. I opted to just release for Android, simply because publishing to the Google Play store was about € 30, while for an Apple developer account you'd have to fork over € 100. That was a bit too much for my learning goal. I'm sure that the Apple process and Google processes are in many ways overlapping, so I'm fine with this blind spot.",[],{},{"nodeType":106,"data":2275,"content":2276},{},[2277,2281,2289],{"nodeType":68,"value":2278,"marks":2279,"data":2280},"Next step was preparing and creating assets for the Play Store. There are ",[],{},{"nodeType":539,"data":2282,"content":2284},{"uri":2283},"https://support.google.com/googleplay/android-developer/answer/9866151?hl=en",[2285],{"nodeType":68,"value":2286,"marks":2287,"data":2288},"clear guidelines here",[],{},{"nodeType":68,"value":2290,"marks":2291,"data":2292},", so you know exactly what's expected of you. My only trouble was being able to generate the screenshots at the right resolution, since I was using the browser as my screenshot generator. Fiddling with the settings in the DevTools emulator in combination with an image upscaler got things the way I wanted with relative ease. Again, I wasn't really that interested in creating assets and for a more professional approach I'd probably spent a bit more time in imaging software the create commercially seductive images for the app. ",[],{},{"nodeType":106,"data":2294,"content":2295},{},[2296],{"nodeType":68,"value":2297,"marks":2298,"data":2299},"I did spent some extra effort in the descriptive texts, since I did want to measure or verify how and when an app would show up in the listing. I wasn't aware of the term App Store Optimization (ASO), before I started this. There's a whole (inaccurate) science behind this! I limited myself with my own experience in Search Engine Optimization (SEO) and went for accurate and descriptive texts with some search terms sprinkled in. Not sure how this performs to this date! 😅",[],{},{"nodeType":106,"data":2301,"content":2302},{},[2303,2307,2315,2319,2327],{"nodeType":68,"value":2304,"marks":2305,"data":2306},"At this point, I also launched ",[],{},{"nodeType":539,"data":2308,"content":2310},{"uri":2309},"https://doorrekenen.nl/",[2311],{"nodeType":68,"value":2312,"marks":2313,"data":2314},"a website",[],{},{"nodeType":68,"value":2316,"marks":2317,"data":2318}," to accompany the app. I vaguely remembered that this was a prerequisite in earlier app publishing days, so I built it during the app development process as well. It's a small scale website, built on Vue, Nuxt with the ",[],{},{"nodeType":539,"data":2320,"content":2322},{"uri":2321},"https://content.nuxt.com/",[2323],{"nodeType":68,"value":2324,"marks":2325,"data":2326},"Nuxt Content",[],{},{"nodeType":68,"value":2328,"marks":2329,"data":2330}," module (I'll have to do a write up for that one as well: it's a bliss to work with!). Via the website I started to collect email addresses for app testing purposes. At an early stage I already got the memo that you need to have at least a handful of testers ready. Apart from that requirement, I was also a bit curious on other peoples' experiences and opinions. By sharing the link to the signup form with coworkers, friend and family, I was able to collect a bunch of testers. Hooray!",[],{},{"nodeType":148,"data":2332,"content":2333},{},[2334],{"nodeType":68,"value":2335,"marks":2336,"data":2337},"Google Console Walkthrough (spoilers!)",[],{},{"nodeType":106,"data":2339,"content":2340},{},[2341],{"nodeType":68,"value":2342,"marks":2343,"data":2344},"Now it was time to dive into the Play Console. This is where the bureaucracy happens!",[],{},{"nodeType":106,"data":2346,"content":2347},{},[2348],{"nodeType":68,"value":2349,"marks":2350,"data":2351},"First, I created the app listing by filling out the usual info: title, descriptions, category, contact email, and of course a privacy policy. There are plenty of tools that can help you in generating this content as well. I came prepared for this step!",[],{},{"nodeType":106,"data":2353,"content":2354},{},[2355],{"nodeType":68,"value":2356,"marks":2357,"data":2358},"Next was creating a release. I followed the required steps here. I was expecting that there is a vetting process, so I was well aware that publishing isn't done in a day. By requirements, you start with a Closed Testing track. I added my band of testers. That part went pretty smoothly, save for a minor hiccup.",[],{},{"nodeType":106,"data":2360,"content":2361},{},[2362],{"nodeType":68,"value":2363,"marks":2364,"data":2365},"I wanted to test a paid app. Here's the rub: I already listed the app as a paid app in the Developer Console. After doing that, you cannot make it a free app and change it back to a paid app. Once it's free, it's free forever! This meant that I had to work with discount codes, updated pricing models and whatnot, which I could've sidestepped (I think) if I'd started out with a free app and just before publishing made it a paid app. 🤦‍♂️",[],{},{"nodeType":106,"data":2367,"content":2368},{},[2369],{"nodeType":68,"value":2370,"marks":2371,"data":2372},"While my testers were initially excited to be part of this exclusive group, it turns out that following through with actual testing, meaning installing the app and opening it at least a couple of times, was a bit too much effort. I don't blame anyone, I did the same with the \"tit for tat\" services. There's a 14 day period in which 12 people need to have opted in, installed and opened your app and kept it installed for the duration. So anxiously, I was counting down the days and looking at the number of testers. After nudging and encouraging additional individuals to meet my mark, I though I was done for the next step.",[],{},{"nodeType":106,"data":2374,"content":2375},{},[2376],{"nodeType":68,"value":2377,"marks":2378,"data":2379},"I was not.",[],{},{"nodeType":106,"data":2381,"content":2382},{},[2383,2387,2395,2399,2407],{"nodeType":68,"value":2384,"marks":2385,"data":2386},"After submitting for approval, the report came in that testing was inadequate. 🫣 So now, I already strained my goodwill resources, so I turned to Google to investigate how other developers handled this. Turns out, there's an industry built around the testing requirement 😅. If you want to roll for free, you can try out posting on ",[],{},{"nodeType":539,"data":2388,"content":2390},{"uri":2389},"https://www.reddit.com/r/AndroidClosedTesting/",[2391],{"nodeType":68,"value":2392,"marks":2393,"data":2394},"Reddit",[],{},{"nodeType":68,"value":2396,"marks":2397,"data":2398}," or using a \"you test mine, I test yours\" service, like ",[],{},{"nodeType":539,"data":2400,"content":2402},{"uri":2401},"https://www.testerscommunity.com/",[2403],{"nodeType":68,"value":2404,"marks":2405,"data":2406},"Testers Community",[],{},{"nodeType":68,"value":2408,"marks":2409,"data":2410},". The general premise of this approach is simple: it connects app developers in need of testing. For every tester that tests your app, it's expected to return the favor. With Testers Community it's a credits system, with Reddit it's based on gentleman's agreement. With my low cost approach, this seems ideal. I tried out both systems, but they didn't really seem to work for me, to be honest. This was where I realized the threshold of going through app installations, opting in, trying out the app, providing feedback etc. It was just too much of a hassle. Also, with both services, I wasn't getting enough testers on the timeline that I was looking for. Since I already \"wasted\" the first 14 days, I wanted to make some good speed at this point. ",[],{},{"nodeType":106,"data":2412,"content":2413},{},[2414,2418,2426],{"nodeType":68,"value":2415,"marks":2416,"data":2417},"I caved in and used a paid service that guarantees a successful testing step. I used ",[],{},{"nodeType":539,"data":2419,"content":2421},{"uri":2420},"https://www.apptesterhub.com/",[2422],{"nodeType":68,"value":2423,"marks":2424,"data":2425},"AppTesterHub",[],{},{"nodeType":68,"value":2427,"marks":2428,"data":2429}," for this. For a couple of Euros, the whole process of chasing people and investing my own time on random apps was made obsolete. After a day or so after submitting the testing track, I saw that the number of testers started to increase to well over the required amount. ",[],{},{"nodeType":106,"data":2431,"content":2432},{},[2433],{"nodeType":68,"value":2434,"marks":2435,"data":2436},"Is it cheating? Maybe. To be fair, I didn't receive feedback on bugs during that testing period, while I am sure that there is certainly a bug or two noticeable. I can also imagine that it's quite hard, when you're a non Dutch speaker, to properly test an app that's Dutch. Anyway, it did the trick.",[],{},{"nodeType":106,"data":2438,"content":2439},{},[2440],{"nodeType":68,"value":2441,"marks":2442,"data":2443},"After the testing periode, you have to fill out a questionnaire on how you approached testing. I have been completely transparent in my answers (seeing what would happen), and the testing was approved.",[],{},{"nodeType":106,"data":2445,"content":2446},{},[2447],{"nodeType":68,"value":2448,"marks":2449,"data":2450},"After that, I filled out the required app content form, with stuff like target audience, data usage & collection (none), and ads (also none). I also listed it as an educational app, since that's what it is. I'm guessing that these trigger a slightly stricter review path, since apps aimed at children get extra scrutiny. I'm all in favor for this, and all was good, since I have been very deliberate about privacy.",[],{},{"nodeType":106,"data":2452,"content":2453},{},[2454],{"nodeType":68,"value":2455,"marks":2456,"data":2457},"Once everything was filled out, checked, and confirmed, I submitted the release for review. That took a couple of days, but eventually, it got approved and published! 🎉",[],{},{"nodeType":517,"data":2459,"content":2460},{},[2461],{"nodeType":68,"value":2462,"marks":2463,"data":2464},"What I Learned (and What I’d Do Differently)",[],{},{"nodeType":106,"data":2466,"content":2467},{},[2468],{"nodeType":68,"value":2469,"marks":2470,"data":2471},"As you can imagine, that publishing steps were definitely the most stressful and complicated! That's why I wanted to experience this, to see how much sense I could make of it. And to be clear: I'm still not entirely comfortable with the Developer Console. Coming from web development, this is another process entirely! It was a fun challenge though! I'm still very excited and impressed with what you can do with (open source) web tools and the web standards! Building stuff is still something that gives me energy: identifying a problem, coming up with a solution, building and testing it. It's empowering to be able to do all of this.",[],{},{"nodeType":106,"data":2473,"content":2474},{},[2475],{"nodeType":68,"value":2476,"marks":2477,"data":2478},"The thing that I disliked the most was the waiting period. I think, objectively, that it's good to have a slow process by design, since it theoretically prevents the app store to be overflowed with low effort and low quality apps. Given the ease of bypassing this, if you're willing to spend a couple of bucks however, seems to indicate that it's not the best method. But still. I guess I'm more of an action kinda developer. I also hate it when a CI/CD pipeline is slow, or halts for some reason. And I'm used to be able to deploy in an instant on the web.",[],{},{"nodeType":106,"data":2480,"content":2481},{},[2482],{"nodeType":68,"value":2483,"marks":2484,"data":2485},"So next time, I'd make sure to have my paid testers lined up for the initial testing track.",[],{},{"nodeType":106,"data":2487,"content":2488},{},[2489],{"nodeType":68,"value":2490,"marks":2491,"data":2492},"As I already mentioned: I'm still not 100% comfortable with de Developer Console. I do have plans to go through the process of updating the app. There are some bugfixes lined up and extra features I could cover. Once those are ready and well tested, I'll have the pleasure of trying to figure out additional updates. As far as I understand, this process is more streamlined than the initial publication (which makes sense).",[],{},{"nodeType":106,"data":2494,"content":2495},{},[2496],{"nodeType":68,"value":2497,"marks":2498,"data":2499},"Overall, I'm pleased with the result. For under € 50, I learnt a lot about the hybrid app development process. Figuring out everything by yourself isn't always the most efficient route, though. But with some perseverance you'll get there eventually. ",[],{},{"nodeType":106,"data":2501,"content":2502},{},[2503],{"nodeType":68,"value":2504,"marks":2505,"data":2506},"Am I an app developer? Somewhat. I can build an deploy a basic app. I also realize there's a lot more to learn and uncover. If you're curious yourself, give it a go!",[],{},{"data":2508,"content":2509,"nodeType":371},{},[2510,2517,2558],{"data":2511,"content":2512,"nodeType":517},{},[2513],{"data":2514,"marks":2515,"value":2516,"nodeType":68},{},[],"Links",{"data":2518,"content":2519,"nodeType":1204},{},[2520,2539],{"data":2521,"content":2522,"nodeType":1163},{},[2523],{"data":2524,"content":2525,"nodeType":106},{},[2526,2529,2536],{"data":2527,"marks":2528,"value":1127,"nodeType":68},{},[],{"data":2530,"content":2531,"nodeType":539},{"uri":2309},[2532],{"data":2533,"marks":2534,"value":2535,"nodeType":68},{},[],"Doorrekenen.nl",{"data":2537,"marks":2538,"value":1127,"nodeType":68},{},[],{"data":2540,"content":2541,"nodeType":1163},{},[2542],{"data":2543,"content":2544,"nodeType":106},{},[2545,2548,2555],{"data":2546,"marks":2547,"value":1127,"nodeType":68},{},[],{"data":2549,"content":2550,"nodeType":539},{"uri":2040},[2551],{"data":2552,"marks":2553,"value":2554,"nodeType":68},{},[],"Doorrekenen Play Store app",{"data":2556,"marks":2557,"value":1127,"nodeType":68},{},[],{"data":2559,"content":2560,"nodeType":106},{},[2561],{"data":2562,"marks":2563,"value":1127,"nodeType":68},{},[],[1228,2565,1934,2581],{"metadata":2566,"sys":2569,"fields":2578},{"tags":2567,"concepts":2568},[],[],{"space":2570,"id":2572,"type":16,"createdAt":2573,"updatedAt":2573,"environment":2574,"publishedVersion":418,"revision":23,"contentType":2576,"locale":28},{"sys":2571},{"type":12,"linkType":13,"id":14},"4JO8jgvxvcPBL3lioPjUBO","2022-07-13T11:58:58.684Z",{"sys":2575},{"id":20,"type":12,"linkType":21},{"sys":2577},{"type":12,"linkType":26,"id":387},{"title":2579,"slug":2580},"Learning","learning",{"metadata":2582,"sys":2585,"fields":2594},{"tags":2583,"concepts":2584},[],[],{"space":2586,"id":2588,"type":16,"createdAt":2589,"updatedAt":2589,"environment":2590,"publishedVersion":418,"revision":23,"contentType":2592,"locale":28},{"sys":2587},{"type":12,"linkType":13,"id":14},"M4gsBA3vPpx68krYqEnco","2025-06-10T11:20:23.570Z",{"sys":2591},{"id":20,"type":12,"linkType":21},{"sys":2593},{"type":12,"linkType":26,"id":387},{"title":2081,"slug":2595},"quasar",{"metadata":2597,"sys":2600,"fields":2611},{"tags":2598,"concepts":2599},[],[],{"space":2601,"id":2603,"type":16,"createdAt":2604,"updatedAt":2605,"environment":2606,"publishedVersion":2608,"revision":384,"contentType":2609,"locale":28},{"sys":2602},{"type":12,"linkType":13,"id":14},"6FbX4KNgqMQWjsa1mF3HDZ","2025-03-17T10:14:21.866Z","2025-03-17T10:24:30.119Z",{"sys":2607},{"id":20,"type":12,"linkType":21},169,{"sys":2610},{"type":12,"linkType":26,"id":27},{"title":2612,"published":2613,"slug":2614,"heroImage":2615,"body":2639,"tags":3035},"JavaScript’s Temporal API: the future of date time handling!","2025-03-03","javascripts-temporal-api-the-future-of-date-time-handling",{"metadata":2616,"sys":2619,"fields":2627},{"tags":2617,"concepts":2618},[],[],{"space":2620,"id":2622,"type":41,"createdAt":2623,"updatedAt":2623,"environment":2624,"publishedVersion":2626,"revision":23,"locale":28},{"sys":2621},{"type":12,"linkType":13,"id":14},"5lfwyafx34vHjSLbZ7K6Ih","2025-03-17T09:45:01.979Z",{"sys":2625},{"id":20,"type":12,"linkType":21},6,{"title":2628,"description":2629,"file":2630},"Flux Capacitor","A still from the movie \"Back to the Future\", depicting the Flux Capacitor",{"url":2631,"details":2632,"fileName":2637,"contentType":2638},"//images.ctfassets.net/mqwrag4of3hk/5lfwyafx34vHjSLbZ7K6Ih/54327a9ca0f50de65b2cf6621b5dd430/flux-capacitor.webp",{"size":2633,"image":2634},45680,{"width":2635,"height":2636},1000,563,"flux-capacitor.webp","image/webp",{"nodeType":371,"data":2640,"content":2641},{},[2642,2702,2721,2728,2735,2754,2761,2768,2802,2809,2817,2873,2880,2896,2904,2919,2926,2933,2941,2957,2964,2971,2979,2986,2993,3009,3016],{"nodeType":106,"data":2643,"content":2644},{},[2645,2649,2654,2658,2666,2670,2678,2682,2690,2694,2699],{"nodeType":68,"value":2646,"marks":2647,"data":2648},"Ah, the ",[],{},{"nodeType":68,"value":2650,"marks":2651,"data":2653},"JavaScript Date",[2652],{"type":73},{},{"nodeType":68,"value":2655,"marks":2656,"data":2657}," object. It just doesn't cut it, does it? Working with dates can be ",[],{},{"nodeType":539,"data":2659,"content":2661},{"uri":2660},"https://www.youtube.com/watch?v=-5wpm-gesOY",[2662],{"nodeType":68,"value":2663,"marks":2664,"data":2665},"daunting or maddening",[],{},{"nodeType":68,"value":2667,"marks":2668,"data":2669},"! So rather than using the Date object, we've been resorting to libraries (like ",[],{},{"nodeType":539,"data":2671,"content":2673},{"uri":2672},"https://momentjs.com/",[2674],{"nodeType":68,"value":2675,"marks":2676,"data":2677},"moment.js",[],{},{"nodeType":68,"value":2679,"marks":2680,"data":2681}," or ",[],{},{"nodeType":539,"data":2683,"content":2685},{"uri":2684},"https://date-fns.org/",[2686],{"nodeType":68,"value":2687,"marks":2688,"data":2689},"date-fns",[],{},{"nodeType":68,"value":2691,"marks":2692,"data":2693},") that tackle the complexity for us. We're getting at a comfortable space right now, with the ",[],{},{"nodeType":68,"value":2695,"marks":2696,"data":2698},"Temporal API",[2697],{"type":73},{},{"nodeType":68,"value":548,"marks":2700,"data":2701},[],{},{"nodeType":106,"data":2703,"content":2704},{},[2705,2709,2717],{"nodeType":68,"value":2706,"marks":2707,"data":2708},"It's not widely supported right now (",[],{},{"nodeType":539,"data":2710,"content":2712},{"uri":2711},"https://caniuse.com/mdn-javascript_builtins_temporal",[2713],{"nodeType":68,"value":2714,"marks":2715,"data":2716},"experimental stage",[],{},{"nodeType":68,"value":2718,"marks":2719,"data":2720},"), but close to being finalized and adopted by major browsers!",[],{},{"nodeType":106,"data":2722,"content":2723},{},[2724],{"nodeType":68,"value":2725,"marks":2726,"data":2727},"Let’s warm up the flux capacitor and dive into the Temporal API. Spoiler: it’s not just about better date formatting (though, that’s a big part of it).",[],{},{"nodeType":148,"data":2729,"content":2730},{},[2731],{"nodeType":68,"value":2732,"marks":2733,"data":2734},"The Problem with Date",[],{},{"nodeType":106,"data":2736,"content":2737},{},[2738,2742,2750],{"nodeType":68,"value":2739,"marks":2740,"data":2741},"If you’ve worked with the Date object in JavaScript for more than five minutes, you’ve likely wanted to ",[],{},{"nodeType":539,"data":2743,"content":2745},{"uri":2744},"https://theoatmeal.com/book",[2746],{"nodeType":68,"value":2747,"marks":2748,"data":2749},"punch a dolphin in the mouth",[],{},{"nodeType":68,"value":2751,"marks":2752,"data":2753},". Between time zones, leap years, and the general confusion of unexpected results, it’s been a wild ride. The Date object is like that one kitchen drawer filled with mismatched utensils—functional but chaotic.",[],{},{"nodeType":106,"data":2755,"content":2756},{},[2757],{"nodeType":68,"value":2758,"marks":2759,"data":2760},"That's why libraries stepped in to tidy things up. It took some time, but now we're on the verge of getting a useful API to handle those pesky date and time situations.",[],{},{"nodeType":148,"data":2762,"content":2763},{},[2764],{"nodeType":68,"value":2765,"marks":2766,"data":2767},"Temporal: First Impressions",[],{},{"nodeType":106,"data":2769,"content":2770},{},[2771,2775,2780,2784,2789,2793,2798],{"nodeType":68,"value":2772,"marks":2773,"data":2774},"Unlike the Date object, ",[],{},{"nodeType":68,"value":2776,"marks":2777,"data":2779},"Temporal",[2778],{"type":73},{},{"nodeType":68,"value":2781,"marks":2782,"data":2783}," is ",[],{},{"nodeType":68,"value":2785,"marks":2786,"data":2788},"straightforward",[2787],{"type":2203},{},{"nodeType":68,"value":2790,"marks":2791,"data":2792}," and ",[],{},{"nodeType":68,"value":2794,"marks":2795,"data":2797},"specific",[2796],{"type":2203},{},{"nodeType":68,"value":2799,"marks":2800,"data":2801},". Instead of relying on relative and implicit assumptions, Temporal uses explicit types for each time-related concept. You’re not just slapping together a date and hoping for the best anymore.",[],{},{"nodeType":106,"data":2803,"content":2804},{},[2805],{"nodeType":68,"value":2806,"marks":2807,"data":2808},"Let’s look at a simple example:",[],{},{"nodeType":106,"data":2810,"content":2811},{},[2812],{"nodeType":68,"value":2813,"marks":2814,"data":2816},"const now = Temporal.Now.plainDateISO();\nconsole.log(now);  // 2024-12-31",[2815],{"type":1010},{},{"nodeType":106,"data":2818,"content":2819},{},[2820,2824,2833,2837,2842,2846,2851,2855,2860,2864,2869],{"nodeType":68,"value":2821,"marks":2822,"data":2823},"Easy, right? No time zone confusion, no guesswork—just clarity. It’s ",[],{},{"nodeType":539,"data":2825,"content":2827},{"uri":2826},"https://en.wikipedia.org/wiki/ISO_8601",[2828],{"nodeType":68,"value":2829,"marks":2830,"data":2832},"ISO 8601",[2831],{"type":73},{},{"nodeType":68,"value":2834,"marks":2835,"data":2836}," (regardless of cultural formatting preference). So far so good. But Temporal doesn’t stop there. It handles everything from ",[],{},{"nodeType":68,"value":2838,"marks":2839,"data":2841},"dates",[2840],{"type":73},{},{"nodeType":68,"value":2843,"marks":2844,"data":2845}," to ",[],{},{"nodeType":68,"value":2847,"marks":2848,"data":2850},"times",[2849],{"type":73},{},{"nodeType":68,"value":2852,"marks":2853,"data":2854},", ",[],{},{"nodeType":68,"value":2856,"marks":2857,"data":2859},"durations",[2858],{"type":73},{},{"nodeType":68,"value":2861,"marks":2862,"data":2863},", and even ",[],{},{"nodeType":68,"value":2865,"marks":2866,"data":2868},"calendars",[2867],{"type":73},{},{"nodeType":68,"value":2870,"marks":2871,"data":2872},".",[],{},{"nodeType":148,"data":2874,"content":2875},{},[2876],{"nodeType":68,"value":2877,"marks":2878,"data":2879},"Explicit is Better Than Implicit",[],{},{"nodeType":106,"data":2881,"content":2882},{},[2883,2887,2892],{"nodeType":68,"value":2884,"marks":2885,"data":2886},"The first thing you’ll notice about Temporal is that it doesn’t try to “help” you in the same way Date does—by making guesses about what you mean. Want to create a specific moment in time? You better be sure about ",[],{},{"nodeType":68,"value":2888,"marks":2889,"data":2891},"exactly",[2890],{"type":73},{},{"nodeType":68,"value":2893,"marks":2894,"data":2895}," what you mean.",[],{},{"nodeType":106,"data":2897,"content":2898},{},[2899],{"nodeType":68,"value":2900,"marks":2901,"data":2903},"const someDate = Temporal.PlainDate.from('2024-12-31');",[2902],{"type":1010},{},{"nodeType":106,"data":2905,"content":2906},{},[2907,2911,2915],{"nodeType":68,"value":2908,"marks":2909,"data":2910},"Want to try and flip the days and months? No sir! The API returns an error, explaining ",[],{},{"nodeType":68,"value":2888,"marks":2912,"data":2914},[2913],{"type":73},{},{"nodeType":68,"value":2916,"marks":2917,"data":2918}," what went wrong (\"Uncaught RangeError: can't parse date-time: month must be a number from 1 to 12\"). No more guessing! Why Date returns an \"Invalid Date\" error. It's the little things, right?",[],{},{"nodeType":148,"data":2920,"content":2921},{},[2922],{"nodeType":68,"value":2923,"marks":2924,"data":2925},"Having Fun with Time Zones (Just Kidding)",[],{},{"nodeType":106,"data":2927,"content":2928},{},[2929],{"nodeType":68,"value":2930,"marks":2931,"data":2932},"I am very fortunate to (knock on wood) never really had to deal with time zone-related bugs. And given some time, I never have to, with Temporal coming to the rescue again. 💪",[],{},{"nodeType":106,"data":2934,"content":2935},{},[2936],{"nodeType":68,"value":2937,"marks":2938,"data":2940},"const zoned = Temporal.ZonedDateTime.from('2024-12-31T15:30:00[Europe/Amsterdam]');\nconsole.log(zoned.toString());  // 2024-12-31T15:30:00+01:00[Europe/Amsterdam]",[2939],{"type":1010},{},{"nodeType":106,"data":2942,"content":2943},{},[2944,2948,2953],{"nodeType":68,"value":2945,"marks":2946,"data":2947},"Built in, clear handling of timezones! Temporal even keeps track of ",[],{},{"nodeType":68,"value":2949,"marks":2950,"data":2952},"daylight saving time",[2951],{"type":73},{},{"nodeType":68,"value":2954,"marks":2955,"data":2956}," for you, so you can stop worrying about whether your app breaks when the clocks change over the course of weeks across the globe. Imagine that.",[],{},{"nodeType":148,"data":2958,"content":2959},{},[2960],{"nodeType":68,"value":2961,"marks":2962,"data":2963},"Durations: More Than Just Counting the Days",[],{},{"nodeType":106,"data":2965,"content":2966},{},[2967],{"nodeType":68,"value":2968,"marks":2969,"data":2970},"Temporal also makes working with durations—something we all do at some point—a breeze:",[],{},{"nodeType":106,"data":2972,"content":2973},{},[2974],{"nodeType":68,"value":2975,"marks":2976,"data":2978},"const duration = Temporal.Duration.from({ days: 7, hours: 5 });\nconst newDate = Temporal.PlainDate.from('2024-12-31').add(duration);\nconsole.log(newDate.toString());  // 2025-01-07",[2977],{"type":1010},{},{"nodeType":106,"data":2980,"content":2981},{},[2982],{"nodeType":68,"value":2983,"marks":2984,"data":2985},"This has to be one of the features I love most: it's so flexible and readable at the same time!",[],{},{"nodeType":148,"data":2987,"content":2988},{},[2989],{"nodeType":68,"value":2990,"marks":2991,"data":2992},"The Catch (for now)",[],{},{"nodeType":106,"data":2994,"content":2995},{},[2996,3000,3005],{"nodeType":68,"value":2997,"marks":2998,"data":2999},"Now (not a pun), before you get too excited, as I said: the Temporal API is ",[],{},{"nodeType":68,"value":3001,"marks":3002,"data":3004},"not",[3003],{"type":73},{},{"nodeType":68,"value":3006,"marks":3007,"data":3008}," yet natively available in every browser as of writing this. So you may still need polyfills or tooling support. That's fine too, been there, done that!",[],{},{"nodeType":106,"data":3010,"content":3011},{},[3012],{"nodeType":68,"value":3013,"marks":3014,"data":3015},"Don’t let it stop you. Temporal is the future, and like all good things in JavaScript, it will eventually become the standard.",[],{},{"nodeType":106,"data":3017,"content":3018},{},[3019,3023,3031],{"nodeType":68,"value":3020,"marks":3021,"data":3022},"I've been playing with the Temporal API in ",[],{},{"nodeType":539,"data":3024,"content":3026},{"uri":3025},"https://www.mozilla.org/en-US/firefox/channel/desktop/",[3027],{"nodeType":68,"value":3028,"marks":3029,"data":3030},"Firefox Nightly",[],{},{"nodeType":68,"value":3032,"marks":3033,"data":3034},", but it's likely to be available on more browsers in Canaries, Nightlies or behind feature flags. I recommend trying it out, but since it's still experimental, might be subject to changes. I highly doubt it will be a complete overhaul, but it's definitely not ready for your production environments!",[],{},[3036,3052,3068],{"metadata":3037,"sys":3040,"fields":3049},{"tags":3038,"concepts":3039},[],[],{"space":3041,"id":3043,"type":16,"createdAt":3044,"updatedAt":3044,"environment":3045,"publishedVersion":418,"revision":23,"contentType":3047,"locale":28},{"sys":3042},{"type":12,"linkType":13,"id":14},"2T1gWFqfLcb4su81mAX2w","2022-11-07T20:29:32.889Z",{"sys":3046},{"id":20,"type":12,"linkType":21},{"sys":3048},{"type":12,"linkType":26,"id":387},{"title":3050,"slug":3051},"JavaScript","javascript",{"metadata":3053,"sys":3056,"fields":3065},{"tags":3054,"concepts":3055},[],[],{"space":3057,"id":3059,"type":16,"createdAt":3060,"updatedAt":3060,"environment":3061,"publishedVersion":384,"revision":23,"contentType":3063,"locale":28},{"sys":3058},{"type":12,"linkType":13,"id":14},"3ZBpdQzzZeDnPfm5yS2VQ0","2022-07-13T11:58:48.033Z",{"sys":3062},{"id":20,"type":12,"linkType":21},{"sys":3064},{"type":12,"linkType":26,"id":387},{"title":3066,"slug":3067},"Coding","coding",{"metadata":3069,"sys":3072,"fields":3081},{"tags":3070,"concepts":3071},[],[],{"space":3073,"id":3075,"type":16,"createdAt":3076,"updatedAt":3076,"environment":3077,"publishedVersion":418,"revision":23,"contentType":3079,"locale":28},{"sys":3074},{"type":12,"linkType":13,"id":14},"gwuNdh5u84C2SbTSFWnmT","2025-03-17T09:36:29.712Z",{"sys":3078},{"id":20,"type":12,"linkType":21},{"sys":3080},{"type":12,"linkType":26,"id":387},{"title":3082,"slug":3083},"Web Standards","web-standards",{"metadata":3085,"sys":3088,"fields":3098},{"tags":3086,"concepts":3087},[],[],{"space":3089,"id":3091,"type":16,"createdAt":3092,"updatedAt":3092,"environment":3093,"publishedVersion":3095,"revision":23,"contentType":3096,"locale":28},{"sys":3090},{"type":12,"linkType":13,"id":14},"6pG0paxkBSVdCVUaNxXEKy","2024-12-28T11:00:02.691Z",{"sys":3094},{"id":20,"type":12,"linkType":21},735,{"sys":3097},{"type":12,"linkType":26,"id":27},{"title":3099,"published":3100,"slug":3101,"heroImage":476,"body":3102,"sidebar":3815,"tags":3869},"2024: Year in Review","2024-12-28","2024-year-in-review",{"nodeType":371,"data":3103,"content":3104},{},[3105,3112,3119,3135,3151,3157,3164,3171,3178,3213,3257,3274,3293,3312,3318,3345,3364,3371,3414,3420,3427,3434,3475,3482,3489,3496,3502,3508,3514,3521,3540,3547,3554,3561,3568,3575,3581,3598,3605,3621,3628,3635,3642,3649,3656,3663,3670,3676,3691,3702,3708,3715,3722,3741,3760,3766,3773,3801,3808],{"nodeType":106,"data":3106,"content":3107},{},[3108],{"nodeType":68,"value":3109,"marks":3110,"data":3111},"Another year draws to a close and while we don't have hover boards or flying cars yet, we're on the brink of 2025 already! ",[],{},{"nodeType":517,"data":3113,"content":3114},{},[3115],{"nodeType":68,"value":3116,"marks":3117,"data":3118},"The Book (continued) 📚",[],{},{"nodeType":106,"data":3120,"content":3121},{},[3122,3126,3131],{"nodeType":68,"value":3123,"marks":3124,"data":3125},"My book was published in the beginning of the year and has been sold over ",[],{},{"nodeType":68,"value":3127,"marks":3128,"data":3130},"300 copies since launch",[3129],{"type":73},{},{"nodeType":68,"value":3132,"marks":3133,"data":3134},"! My goal was mostly to experience the book writing process and selling over a hundred copies already vastly exceeded expectations. I have received some offers for new books as well, but given the time and effort it took, I did not follow through on those opportunities. 😅",[],{},{"nodeType":106,"data":3136,"content":3137},{},[3138,3141,3148],{"nodeType":68,"value":535,"marks":3139,"data":3140},[],{},{"nodeType":539,"data":3142,"content":3143},{"uri":541},[3144],{"nodeType":68,"value":3145,"marks":3146,"data":3147},"still available as hard copy or digital version",[],{},{"nodeType":68,"value":548,"marks":3149,"data":3150},[],{},{"nodeType":517,"data":3152,"content":3153},{},[3154],{"nodeType":68,"value":555,"marks":3155,"data":3156},[],{},{"nodeType":106,"data":3158,"content":3159},{},[3160],{"nodeType":68,"value":3161,"marks":3162,"data":3163},"The AI train is still picking up steam, and with the genie out of the bottle, it's become an ubiquitous part of everybody's life. I've moved to a team which investigates leveraging AI to provide better customer service via chatbots.",[],{},{"nodeType":106,"data":3165,"content":3166},{},[3167],{"nodeType":68,"value":3168,"marks":3169,"data":3170},"From frontend capacity, I'm mostly involved with providing the interfaces for these agents. I'm also leading the research in how we can train our internal AI tools to provide better and faster results when ingesting large sets of internal manuals and procedures. This initiative has a lot of potential, so I'm very excited about the possibilities here!",[],{},{"nodeType":517,"data":3172,"content":3173},{},[3174],{"nodeType":68,"value":3175,"marks":3176,"data":3177},"The \"first\" talks 🎤",[],{},{"nodeType":106,"data":3179,"content":3180},{},[3181,3185,3190,3194,3199,3202,3210],{"nodeType":68,"value":3182,"marks":3183,"data":3184},"This year I had to deal with limited resources and support from my employer, which led to a different approach and setup in my talks and CFPs. I was able to give a couple of talks of things that are very close to my heart, such as the latest features of ",[],{},{"nodeType":68,"value":3186,"marks":3187,"data":3189},"current gen CSS",[3188],{"type":73},{},{"nodeType":68,"value":3191,"marks":3192,"data":3193}," and the ",[],{},{"nodeType":68,"value":3195,"marks":3196,"data":3198},"first ever",[3197],{"type":73},{},{"nodeType":68,"value":1605,"marks":3200,"data":3201},[],{},{"nodeType":539,"data":3203,"content":3205},{"uri":3204},"https://frontendnation.com/",[3206],{"nodeType":68,"value":3207,"marks":3208,"data":3209},"FrontNation",[],{},{"nodeType":68,"value":548,"marks":3211,"data":3212},[],{},{"nodeType":106,"data":3214,"content":3215},{},[3216,3220,3228,3232,3237,3241,3246,3249,3254],{"nodeType":68,"value":3217,"marks":3218,"data":3219},"I was invited at another premiere: on the first edition of ",[],{},{"nodeType":539,"data":3221,"content":3223},{"uri":3222},"https://c3fest.com/",[3224],{"nodeType":68,"value":3225,"marks":3226,"data":3227},"C3 DevFest",[],{},{"nodeType":68,"value":3229,"marks":3230,"data":3231}," I talked about ",[],{},{"nodeType":68,"value":3233,"marks":3234,"data":3236},"Design System Maturity Models",[3235],{"type":73},{},{"nodeType":68,"value":3238,"marks":3239,"data":3240}," and met some cool people, like ",[],{},{"nodeType":68,"value":3242,"marks":3243,"data":3245},"John Romero",[3244],{"type":73},{},{"nodeType":68,"value":2790,"marks":3247,"data":3248},[],{},{"nodeType":68,"value":3250,"marks":3251,"data":3253},"Una Kravets",[3252],{"type":73},{},{"nodeType":68,"value":548,"marks":3255,"data":3256},[],{},{"nodeType":106,"data":3258,"content":3259},{},[3260,3264,3270],{"nodeType":68,"value":3261,"marks":3262,"data":3263},"Another first was a hattrick: speaking at the same venue three years in a row! I completed this streak at ",[],{},{"nodeType":539,"data":3265,"content":3266},{"uri":718},[3267],{"nodeType":68,"value":706,"marks":3268,"data":3269},[],{},{"nodeType":68,"value":3271,"marks":3272,"data":3273},", with another talk on the current gen CSS capabilities. I received a lot of positive feedback on this topic! 💜",[],{},{"nodeType":106,"data":3275,"content":3276},{},[3277,3281,3289],{"nodeType":68,"value":3278,"marks":3279,"data":3280},"Another first was an invite to speak abroad, on the ",[],{},{"nodeType":539,"data":3282,"content":3284},{"uri":3283},"https://codemash.org/",[3285],{"nodeType":68,"value":3286,"marks":3287,"data":3288},"CodeMash 2025",[],{},{"nodeType":68,"value":3290,"marks":3291,"data":3292}," conference! 🇺🇸 Due to unforeseen circumstances however, I had to decline this invite.",[],{},{"nodeType":106,"data":3294,"content":3295},{},[3296,3300,3308],{"nodeType":68,"value":3297,"marks":3298,"data":3299},"On ",[],{},{"nodeType":539,"data":3301,"content":3303},{"uri":3302},"https://events.geekle.us/vuejs/",[3304],{"nodeType":68,"value":3305,"marks":3306,"data":3307},"Vue.js Global Summit",[],{},{"nodeType":68,"value":3309,"marks":3310,"data":3311}," I talked about what I've learned from doing a multitude of projects in the Vue ecosystem.",[],{},{"nodeType":148,"data":3313,"content":3314},{},[3315],{"nodeType":68,"value":668,"marks":3316,"data":3317},[],{},{"nodeType":106,"data":3319,"content":3320},{},[3321,3324,3330,3334,3341],{"nodeType":68,"value":675,"marks":3322,"data":3323},[],{},{"nodeType":539,"data":3325,"content":3326},{"uri":680},[3327],{"nodeType":68,"value":683,"marks":3328,"data":3329},[],{},{"nodeType":68,"value":3331,"marks":3332,"data":3333},". This was a first to contribute to the full cycle, which was still very interesting and fun to participate in. On top of that, this year GitNation organizes a new JS Nation event in New York and I'm part of that ",[],{},{"nodeType":539,"data":3335,"content":3336},{"uri":692},[3337],{"nodeType":68,"value":3338,"marks":3339,"data":3340},"program committee",[],{},{"nodeType":68,"value":3342,"marks":3343,"data":3344}," as well! 🗽",[],{},{"nodeType":106,"data":3346,"content":3347},{},[3348,3352,3360],{"nodeType":68,"value":3349,"marks":3350,"data":3351},"In New York, I had a role to play moderating the discussion panels for both JS Nation as well as ",[],{},{"nodeType":539,"data":3353,"content":3355},{"uri":3354},"https://reactsummit.us/",[3356],{"nodeType":68,"value":3357,"marks":3358,"data":3359},"React Summit",[],{},{"nodeType":68,"value":3361,"marks":3362,"data":3363}," conference. I must admit, speaking with core React maintainers, my appreciation for their challenge of both pushing boundaries as maintaining compatibility is a very unique and interesting challenge. As one of the people at the table said: \"the value of React is in the millions lines of code written past, present and future\". I am paraphrasing here, but it does provide a very good reason for maintaining certain parts and ways of doing things.",[],{},{"nodeType":148,"data":3365,"content":3366},{},[3367],{"nodeType":68,"value":3368,"marks":3369,"data":3370},"Socials",[],{},{"nodeType":106,"data":3372,"content":3373},{},[3374,3378,3386,3390,3398,3402,3410],{"nodeType":68,"value":3375,"marks":3376,"data":3377},"I was not particularly focused on increasing or even maintaining a social media presence. I do notice that ",[],{},{"nodeType":539,"data":3379,"content":3381},{"uri":3380},"https://x.com/joranquinten",[3382],{"nodeType":68,"value":3383,"marks":3384,"data":3385},"Twitter",[],{},{"nodeType":68,"value":3387,"marks":3388,"data":3389}," (or X) seems to be in rapid decline, ",[],{},{"nodeType":539,"data":3391,"content":3393},{"uri":3392},"https://www.linkedin.com/in/joranquinten/",[3394],{"nodeType":68,"value":3395,"marks":3396,"data":3397},"LinkedIn",[],{},{"nodeType":68,"value":3399,"marks":3400,"data":3401}," is still proving to be stable. The decline of Twitter is sad, since it used to be a very open way of connecting with developers around the world. Luckily, seemingly overnight, tech twitter jumped over the ",[],{},{"nodeType":539,"data":3403,"content":3405},{"uri":3404},"https://bsky.app/",[3406],{"nodeType":68,"value":3407,"marks":3408,"data":3409},"Bluesky",[],{},{"nodeType":68,"value":3411,"marks":3412,"data":3413}," 🦋. It's still a rather fresh jump, but it seems to have a better \"stick\" than the Mastodon alternative a few years back.",[],{},{"nodeType":517,"data":3415,"content":3416},{},[3417],{"nodeType":68,"value":731,"marks":3418,"data":3419},[],{},{"nodeType":106,"data":3421,"content":3422},{},[3423],{"nodeType":68,"value":3424,"marks":3425,"data":3426},"I moved again! In the first quarter of this year, an opportunity opened up to pursue more Engineering Manager responsibilities. I've since then been working as an Engineering Manager in a hybrid role, where I partly contribute to frontend development, but also transition into assuming a management role. This was a tough balance at first, but I'm now comfortable in managing teams.",[],{},{"nodeType":106,"data":3428,"content":3429},{},[3430],{"nodeType":68,"value":3431,"marks":3432,"data":3433},"The final update however, is that I will not be able to pursue this goal in the immediate future, due to organizational restructuring. This limits my growth potential within Jumbo at the moment, so I'll have to see how to shape my future career path.",[],{},{"nodeType":106,"data":3435,"content":3436},{},[3437,3441,3450,3454,3462,3466,3471],{"nodeType":68,"value":3438,"marks":3439,"data":3440},"Our company went through a hefty reorganization and severe budget cuts this year, which unfortunately led to the collaboration between ",[],{},{"nodeType":539,"data":3442,"content":3444},{"uri":3443},"https://fontys.edu/",[3445],{"nodeType":68,"value":3446,"marks":3447,"data":3449},"Fontys University of Applied Science",[3448],{"type":73},{},{"nodeType":68,"value":3451,"marks":3452,"data":3453},"'s ",[],{},{"nodeType":539,"data":3455,"content":3457},{"uri":3456},"https://www.fontysictinnovationlab.nl/",[3458],{"nodeType":68,"value":3459,"marks":3460,"data":3461},"InnovationLab",[],{},{"nodeType":68,"value":3463,"marks":3464,"data":3465}," and our ",[],{},{"nodeType":68,"value":3467,"marks":3468,"data":3470},"Jumbo Tech Campus",[3469],{"type":73},{},{"nodeType":68,"value":3472,"marks":3473,"data":3474}," was ended. I spent a lot of time and energy in bringing those two together, so that was a though decision to accept.",[],{},{"nodeType":517,"data":3476,"content":3477},{},[3478],{"nodeType":68,"value":3479,"marks":3480,"data":3481},"Mentoring",[],{},{"nodeType":148,"data":3483,"content":3484},{},[3485],{"nodeType":68,"value":3486,"marks":3487,"data":3488},"Career Day and Invites",[],{},{"nodeType":106,"data":3490,"content":3491},{},[3492],{"nodeType":68,"value":3493,"marks":3494,"data":3495},"With three colleagues I represented Jumbo Tech Campus as a potential organization for graduate assignments and we set up a special day to invite students over to give more information on the Jumbo Tech Campus and promote Jumbo as a tech employer. It was a very successful event, with over 40 students visiting our head office and expressing interest in Jumbo as a potential employer.",[],{},{"nodeType":517,"data":3497,"content":3498},{},[3499],{"nodeType":68,"value":764,"marks":3500,"data":3501},[],{},{"nodeType":106,"data":3503,"content":3504},{},[3505],{"nodeType":68,"value":771,"marks":3506,"data":3507},[],{},{"nodeType":517,"data":3509,"content":3510},{},[3511],{"nodeType":68,"value":778,"marks":3512,"data":3513},[],{},{"nodeType":148,"data":3515,"content":3516},{},[3517],{"nodeType":68,"value":3518,"marks":3519,"data":3520},"Long Weekend in Amsterdam 🌷",[],{},{"nodeType":106,"data":3522,"content":3523},{},[3524,3528,3536],{"nodeType":68,"value":3525,"marks":3526,"data":3527},"Via Home Exchange we landed in a nice little house in the North of Amsterdam. It was within walking distance of the ",[],{},{"nodeType":539,"data":3529,"content":3531},{"uri":3530},"https://wondrexperience.com/ams/",[3532],{"nodeType":68,"value":3533,"marks":3534,"data":3535},"Wondr Experience",[],{},{"nodeType":68,"value":3537,"marks":3538,"data":3539}," (which we obviously visited for glorious selfies). We also explored the city centre. The nice thing was to use the public ferries to cross the IJ every time. We visited some of the museums and took a boat tour. Had a lot of fun being a tourist family!",[],{},{"nodeType":148,"data":3541,"content":3542},{},[3543],{"nodeType":68,"value":3544,"marks":3545,"data":3546},"Snowboarding in Austria 🏂",[],{},{"nodeType":106,"data":3548,"content":3549},{},[3550],{"nodeType":68,"value":3551,"marks":3552,"data":3553},"It was a while since I went on a skiing / snowboarding trip with \"the guys\". We went to Zell am See this year and had loads of fun! It was warm however and conditions have definitely changed over the years! 🥵 ",[],{},{"nodeType":148,"data":3555,"content":3556},{},[3557],{"nodeType":68,"value":3558,"marks":3559,"data":3560},"Train Travels in Italy 🍝",[],{},{"nodeType":106,"data":3562,"content":3563},{},[3564],{"nodeType":68,"value":3565,"marks":3566,"data":3567},"Based on a Home Exchange request in Rome, our visit to the city transformed in a bigger tour, where we visited some famous sites by train! We started by visiting the famous canals of Venice and boarded the train to Florence. In two very rainy days we explored the Duomo, Old town and bridge and boarded the train to Pisa! There we had to take some posing photos with the leaning tower, but we had just as much fun exploring the country side by bicycle!",[],{},{"nodeType":106,"data":3569,"content":3570},{},[3571],{"nodeType":68,"value":3572,"marks":3573,"data":3574},"Our final stop was Rome (or, more precisely, Santa Marinella near Rome) and we spent our days chilling at the beach front and doing quick day trips to the ancient city. It was hectic, traveling to so many locations with the four of us, but we had a good time! Traveling by train was new, and worked well!",[],{},{"nodeType":148,"data":3576,"content":3577},{},[3578],{"nodeType":68,"value":879,"marks":3579,"data":3580},[],{},{"nodeType":106,"data":3582,"content":3583},{},[3584,3588,3594],{"nodeType":68,"value":3585,"marks":3586,"data":3587},"I visited Amsterdam for a second time. This time I stayed at the Kapitein Anna hotel (it's an old fashioned boat!) as part of my activities on the program committee of ",[],{},{"nodeType":539,"data":3589,"content":3590},{"uri":891},[3591],{"nodeType":68,"value":683,"marks":3592,"data":3593},[],{},{"nodeType":68,"value":3595,"marks":3596,"data":3597},". I was also invited to speak at the C3 conference, so I had an extended stay this time! I attended the conference, but also took some time to wander around in Amsterdam for a day. It's pretty nice to visit some of these sites on your own: going to musea, visiting some sights and just some relaxing. Had a great time with the conference attendees as well during the speakers' diners, conference and after parties! 🥳",[],{},{"nodeType":148,"data":3599,"content":3600},{},[3601],{"nodeType":68,"value":3602,"marks":3603,"data":3604},"Looooong Stay in Bali 🏝️",[],{},{"nodeType":106,"data":3606,"content":3607},{},[3608,3612,3617],{"nodeType":68,"value":3609,"marks":3610,"data":3611},"We had an exceptionally long home exchange stay during the summer: we stayed for ",[],{},{"nodeType":68,"value":3613,"marks":3614,"data":3616},"more than five weeks on Bali",[3615],{"type":73},{},{"nodeType":68,"value":3618,"marks":3619,"data":3620},", in a small (non touristy) village called Blayu. The house was overlooking rice paddies (from the swimming pool) and featured a dog (Charlie) to give walks and play with. We took our time to explore parts of the island: we went snorkeling with dolphins at Lovina, visited some nice waterfalls, unwinded on the Nusas near Bali and stranded on Gili Air.",[],{},{"nodeType":106,"data":3622,"content":3623},{},[3624],{"nodeType":68,"value":3625,"marks":3626,"data":3627},"The most fun we had was interacting with the locals: flying kites in the rice paddies 🪁 and visiting the sites that see very little tourists. This is particularly difficult in Bali, since the island is pretty much overrun with tourism which leaves a visible impact on the island. This is one of the reasons we prefer doing home exchanges over visiting hotels, to at least limit our footprint.",[],{},{"nodeType":106,"data":3629,"content":3630},{},[3631],{"nodeType":68,"value":3632,"marks":3633,"data":3634},"I had some pretty cool dives as well: hanging out with massive sea turtles and seeing reef sharks resting under crevices. 🤿🐢🦈",[],{},{"nodeType":148,"data":3636,"content":3637},{},[3638],{"nodeType":68,"value":3639,"marks":3640,"data":3641},"Visit Bruges & Doel 🇧🇪",[],{},{"nodeType":106,"data":3643,"content":3644},{},[3645],{"nodeType":68,"value":3646,"marks":3647,"data":3648},"As part of a yearly tradition, my father in law, brother in law and my son and I (the \"men\" from my wife's side of the family) plan a short weekend with activities. This year, my son and I were the organizers and we had an awesome itinerary (if I do say so). We spent the weekend in Bruges in Belgium and cooked together on the first evening and played games. Next, we wandered around the old town with an escape route, visited the Fries Museum and did a tour of the canals, followed by some beers and a good diner. The last day we visited the ghost town of Doel and held a laser battle in an abandoned gas station! 🔫 That was such good fun! Especially in the somewhat unsettling and graffitied remains of a small town.",[],{},{"nodeType":148,"data":3650,"content":3651},{},[3652],{"nodeType":68,"value":3653,"marks":3654,"data":3655},"New York City 🗽",[],{},{"nodeType":106,"data":3657,"content":3658},{},[3659],{"nodeType":68,"value":3660,"marks":3661,"data":3662},"This one was a blast! I received an invite to join the conferences of JS Nation and React Summit in New York and decided to add some extra time there, since I've never visited the city before. For the two extra days I've had a full schedule of sights to see, to get the most out of the brief visit. It was a very familiar sight, since I've seen lots of sights already in movies and tv shows. Walking around in Manhattan was a lot of fun!",[],{},{"nodeType":106,"data":3664,"content":3665},{},[3666],{"nodeType":68,"value":3667,"marks":3668,"data":3669},"I particularly loved the old skyscrapers of Midtown and the old brickwork buildings, exploring Central Park and taking in the streets and sights all around Manhattan and a small bit of Brooklyn. I ended my city trip with a nighttime visit of the Empire State Building observatory. It was quiet on the platform, despite the number of people there and with very little wind it was a special moment to quietly soak in the lights, sights and sounds of the city. ",[],{},{"nodeType":148,"data":3671,"content":3672},{},[3673],{"nodeType":68,"value":976,"marks":3674,"data":3675},[],{},{"nodeType":106,"data":3677,"content":3678},{},[3679,3682,3688],{"nodeType":68,"value":983,"marks":3680,"data":3681},[],{},{"nodeType":539,"data":3683,"content":3684},{"uri":988},[3685],{"nodeType":68,"value":991,"marks":3686,"data":3687},[],{},{"nodeType":68,"value":995,"marks":3689,"data":3690},[],{},{"nodeType":106,"data":3692,"content":3693},{},[3694,3697],{"nodeType":68,"value":1002,"marks":3695,"data":3696},[],{},{"nodeType":68,"value":1006,"marks":3698,"data":3701},[3699,3700],{"type":73},{"type":1010},{},{"nodeType":517,"data":3703,"content":3704},{},[3705],{"nodeType":68,"value":1016,"marks":3706,"data":3707},[],{},{"nodeType":106,"data":3709,"content":3710},{},[3711],{"nodeType":68,"value":3712,"marks":3713,"data":3714},"Mostly I've been able to complete at least one workout every week, save for vacations. I formed a small road cycling group with two guys from my area and we had a good rhythm during the sunny Sundays. Again, I did not meet my yearly kilometer goal, so maybe it's time to tone it down a bit to make it more realistic! 😅",[],{},{"nodeType":106,"data":3716,"content":3717},{},[3718],{"nodeType":68,"value":3719,"marks":3720,"data":3721},"I started to use the standup desk more often though, and I do notice that it really reduces the amount of lower back pain I'd normally experience when standing or walking for extended amounts of time. So I'll definitely keep doing this.",[],{},{"nodeType":106,"data":3723,"content":3724},{},[3725,3729,3737],{"nodeType":68,"value":3726,"marks":3727,"data":3728},"I ran again! 🏃💨 Because of an injury, I have quit a long time hobby of mine: running. This year I had a very good reason to try it out again: there's a ",[],{},{"nodeType":539,"data":3730,"content":3732},{"uri":3731},"https://krollenloop.nl/",[3733],{"nodeType":68,"value":3734,"marks":3735,"data":3736},"local race",[],{},{"nodeType":68,"value":3738,"marks":3739,"data":3740}," where the track passes within 25 meters of my house. Every year I saw people running and figured that I should at least complete that race once. This year was the 10th anniversary of the event and I decided to go for it. It was a 10 kilometer run and I had not practiced or trained for it, but I felt that I would have  had a decent shot in completing it. I have decent stamina, I have ran these distances before and I do train (almost) weekly in a gym.",[],{},{"nodeType":106,"data":3742,"content":3743},{},[3744,3748,3756],{"nodeType":68,"value":3745,"marks":3746,"data":3747},"I managed to ",[],{},{"nodeType":539,"data":3749,"content":3751},{"uri":3750},"https://www.strava.com/activities/12813882600/overview",[3752],{"nodeType":68,"value":3753,"marks":3754,"data":3755},"complete the race",[],{},{"nodeType":68,"value":3757,"marks":3758,"data":3759},"! Not my best time, but definitely the best this year! It went as expected: the first 7 kilometers where manageable, but the last kilometers where pretty exhausting. I did make it though, and without injury! Maybe there's room for additional small scale running again! 🤔",[],{},{"nodeType":1041,"data":3761,"content":3762},{},[3763],{"nodeType":68,"value":1045,"marks":3764,"data":3765},[],{},{"nodeType":106,"data":3767,"content":3768},{},[3769],{"nodeType":68,"value":3770,"marks":3771,"data":3772},"My birthday is very close to my daughters'. For the birthday party, we went to a riding school to have a kids-riding-horses-party! Much to my surprise, my wife arranged for me to participate as well: riding a big horse instead of a pony! 🐎 It was a lot of fun and a nice addition to the birthday celebrations.",[],{},{"nodeType":106,"data":3774,"content":3775},{},[3776,3779,3785,3789,3797],{"nodeType":68,"value":1059,"marks":3777,"data":3778},[],{},{"nodeType":539,"data":3780,"content":3781},{"uri":1064},[3782],{"nodeType":68,"value":1067,"marks":3783,"data":3784},[],{},{"nodeType":68,"value":3786,"marks":3787,"data":3788},", a theme park near us, there's a professional theatre production running for some time, called ",[],{},{"nodeType":539,"data":3790,"content":3792},{"uri":3791},"https://www.efteling.com/nl/theater/caro",[3793],{"nodeType":68,"value":3794,"marks":3795,"data":3796},"CARO",[],{},{"nodeType":68,"value":3798,"marks":3799,"data":3800},". I learned that for some parts of the show, they are looking for kids between 7 and 10 to join the show. Both our kids were very enthusiastic and we signed them up. This was the first time to see both my kids on stage during a professional production. Awesome! 🎠",[],{},{"nodeType":106,"data":3802,"content":3803},{},[3804],{"nodeType":68,"value":3805,"marks":3806,"data":3807},"For Father’s Day my wife had a wonderful surprise in store! She arranged for me to get a flying introduction! ✈️ Our kids could join in the backseat of a very small single engine airplane. The pilot / instructor took off and gave some instructions on banking, steering and navigating. After the introduction I could steer the airplane by myself! 🧑‍✈️ It was a great feeling!",[],{},{"nodeType":106,"data":3809,"content":3810},{},[3811],{"nodeType":68,"value":3812,"marks":3813,"data":3814},"We had a perfect day for it: blue skies with some very summery cloud formations. This gave us a wonderful view over the city of Deventer and its surroundings. It was a great experience!",[],{},{"data":3816,"content":3817,"nodeType":371},{},[3818,3824,3863],{"data":3819,"content":3820,"nodeType":517},{},[3821],{"data":3822,"marks":3823,"value":1139,"nodeType":68},{},[],{"data":3825,"content":3826,"nodeType":1204},{},[3827,3845],{"data":3828,"content":3829,"nodeType":1163},{},[3830],{"data":3831,"content":3832,"nodeType":106},{},[3833,3836,3842],{"data":3834,"marks":3835,"value":1127,"nodeType":68},{},[],{"data":3837,"content":3838,"nodeType":539},{"uri":1175},[3839],{"data":3840,"marks":3841,"value":1180,"nodeType":68},{},[],{"data":3843,"marks":3844,"value":1127,"nodeType":68},{},[],{"data":3846,"content":3847,"nodeType":1163},{},[3848],{"data":3849,"content":3850,"nodeType":106},{},[3851,3854,3860],{"data":3852,"marks":3853,"value":1127,"nodeType":68},{},[],{"data":3855,"content":3856,"nodeType":539},{"uri":1195},[3857],{"data":3858,"marks":3859,"value":1200,"nodeType":68},{},[],{"data":3861,"marks":3862,"value":1127,"nodeType":68},{},[],{"data":3864,"content":3865,"nodeType":106},{},[3866],{"data":3867,"marks":3868,"value":1127,"nodeType":68},{},[],[1212,1228],{"metadata":3871,"sys":3874,"fields":3885},{"tags":3872,"concepts":3873},[],[],{"space":3875,"id":3877,"type":16,"createdAt":3878,"updatedAt":3879,"environment":3880,"publishedVersion":3882,"revision":487,"contentType":3883,"locale":28},{"sys":3876},{"type":12,"linkType":13,"id":14},"3OBDEg86lGL7hnhkynHSBC","2024-10-14T11:54:29.101Z","2024-10-14T13:55:35.755Z",{"sys":3881},{"id":20,"type":12,"linkType":21},113,{"sys":3884},{"type":12,"linkType":26,"id":27},{"title":3886,"published":3887,"slug":3888,"heroImage":3889,"body":3911,"tags":4021},"The Great Shortcut in Software Development","2024-10-14","the-great-shortcut-in-software-development",{"metadata":3890,"sys":3893,"fields":3901},{"tags":3891,"concepts":3892},[],[],{"space":3894,"id":3896,"type":41,"createdAt":3897,"updatedAt":3897,"environment":3898,"publishedVersion":3900,"revision":23,"locale":28},{"sys":3895},{"type":12,"linkType":13,"id":14},"5EEU6IgVdP3qaZEZVLkpF3","2022-08-02T12:54:03.487Z",{"sys":3899},{"id":20,"type":12,"linkType":21},8,{"title":3902,"description":3903,"file":3904},"Speed","Image courtesy of Chuttersnap",{"url":3905,"details":3906,"fileName":3910,"contentType":57},"//images.ctfassets.net/mqwrag4of3hk/5EEU6IgVdP3qaZEZVLkpF3/b489a03b05e6e8f28ccce568282071c2/speed-chuttersnap.jpeg",{"size":3907,"image":3908},64967,{"width":496,"height":3909},481,"speed-chuttersnap.jpeg",{"nodeType":371,"data":3912,"content":3913},{},[3914,3921,3928,3935,3942,3949,3965,3972,3979,3986,3993,4000,4007,4014],{"nodeType":106,"data":3915,"content":3916},{},[3917],{"nodeType":68,"value":3918,"marks":3919,"data":3920},"In the fast-paced world of software development, why reinvent the wheel when you can just copy-paste someone else’s? We live in a copy-paste culture, where solving problems often means borrowing what already works.",[],{},{"nodeType":106,"data":3922,"content":3923},{},[3924],{"nodeType":68,"value":3925,"marks":3926,"data":3927},"And that’s exactly what npm packages and tech conference talks have in common. Both are shortcuts. Both exist so you don’t have to reinvent the wheel. Let’s explore how these two seemingly different worlds share the same philosophy of borrowed brilliance.",[],{},{"nodeType":106,"data":3929,"content":3930},{},[3931],{"nodeType":68,"value":3932,"marks":3933,"data":3934},"Software development is sometimes such a copy-paste world, that we don't even think about it. But say you need to implement a feature: Instead of writing every single line of code, you type a few magic words into your terminal and suddenly, the work is 90% done. \nThat's the beauty of npm packages, or any other package ecosystem for that matter! It's like plugging into someone else’s hard-earned experience, letting you skip the grunt work and get straight to the good part, straight to production.",[],{},{"nodeType":106,"data":3936,"content":3937},{},[3938],{"nodeType":68,"value":3939,"marks":3940,"data":3941},"Sure, some packages might feel a bit duct-taped together, with a few quirks that remind you it’s not your original creation. But that’s the trade-off—why spend hours on a custom solution when a pre-built package will get you 90% of the way there?",[],{},{"nodeType":517,"data":3943,"content":3944},{},[3945],{"nodeType":68,"value":3946,"marks":3947,"data":3948},"The Tech Conference Ecosystem",[],{},{"nodeType":106,"data":3950,"content":3951},{},[3952,3956,3961],{"nodeType":68,"value":3953,"marks":3954,"data":3955},"If npm is the shortcut for code, tech conferences are the shortcut for your brain. Just like how npm speeds up coding by using someone else’s work, conferences are like a mental ",[],{},{"nodeType":68,"value":3957,"marks":3958,"data":3960},"npm install",[3959],{"type":2203},{},{"nodeType":68,"value":3962,"marks":3963,"data":3964},"—years of experience, downloaded into your brain in under 45 minutes.\nAttending a talk is like downloading someone else’s experience straight into your brain. You walk into a session with gaping holes in your expertise and leave, miraculously, with a new set of ideas—and hopefully fewer holes. It’s as easy as installing packages for your mind! (Although, let's be honest: your brain might crash after 8 hours of talks.)",[],{},{"nodeType":106,"data":3966,"content":3967},{},[3968],{"nodeType":68,"value":3969,"marks":3970,"data":3971},"There’s something magical about the efficiency of it all. One session of listening to a seasoned professional saves you weeks of trial, error, and entering a maze of rabbit holes on a particular topic.",[],{},{"nodeType":517,"data":3973,"content":3974},{},[3975],{"nodeType":68,"value":3976,"marks":3977,"data":3978},"Abundance",[],{},{"nodeType":106,"data":3980,"content":3981},{},[3982],{"nodeType":68,"value":3983,"marks":3984,"data":3985},"Not everything in the world of packages or  conferences is smooth sailing, mind you. Both come with their version of dependency hell. \nIn software, we’ve all been there: install one package, and suddenly your node_modules folder has grown to the size of a small galaxy, with packages depending on packages, depending on yet more packages, slowly eating away at your disk space.",[],{},{"nodeType":106,"data":3987,"content":3988},{},[3989],{"nodeType":68,"value":3990,"marks":3991,"data":3992},"Similarly, attending too many talks at a conference can lead to mental overload. By the end of the day, your brain feels like it’s got wrapped up in circular dependencies, and you're not sure where to start unwrapping.",[],{},{"nodeType":517,"data":3994,"content":3995},{},[3996],{"nodeType":68,"value":3997,"marks":3998,"data":3999},"Shoulders of Giants",[],{},{"nodeType":106,"data":4001,"content":4002},{},[4003],{"nodeType":68,"value":4004,"marks":4005,"data":4006},"There are plenty of benefits of leveraging the time and effort spent by others. Whether you’re installing a package or soaking up knowledge at a conference, the beauty lies in not having to do it all yourself.",[],{},{"nodeType":106,"data":4008,"content":4009},{},[4010],{"nodeType":68,"value":4011,"marks":4012,"data":4013},"Let others take care of the tedious parts—whether it’s writing a utility function or figuring out the latest industry trend—so you can focus on being creative and getting things done faster.",[],{},{"nodeType":106,"data":4015,"content":4016},{},[4017],{"nodeType":68,"value":4018,"marks":4019,"data":4020},"We’re standing on the shoulders of giants, whether those giants are package maintainers or tech conference speakers. They've done the hard work so we can take the shortcut, and isn’t that what being smart is all about? Use what’s out there, build faster, it's the way we work, after all!",[],{},[1228,4022,2565,3052,4038,4054],{"metadata":4023,"sys":4026,"fields":4035},{"tags":4024,"concepts":4025},[],[],{"space":4027,"id":4029,"type":16,"createdAt":4030,"updatedAt":4030,"environment":4031,"publishedVersion":418,"revision":23,"contentType":4033,"locale":28},{"sys":4028},{"type":12,"linkType":13,"id":14},"1jkxD95KeBFTLHkkYvVrf6","2022-11-08T15:26:54.687Z",{"sys":4032},{"id":20,"type":12,"linkType":21},{"sys":4034},{"type":12,"linkType":26,"id":387},{"title":4036,"slug":4037},"Open Source","open-source",{"metadata":4039,"sys":4042,"fields":4051},{"tags":4040,"concepts":4041},[],[],{"space":4043,"id":4045,"type":16,"createdAt":4046,"updatedAt":4046,"environment":4047,"publishedVersion":418,"revision":23,"contentType":4049,"locale":28},{"sys":4044},{"type":12,"linkType":13,"id":14},"5J2O8LfcxQvPeOLpNe3Ipm","2022-07-11T07:15:17.575Z",{"sys":4048},{"id":20,"type":12,"linkType":21},{"sys":4050},{"type":12,"linkType":26,"id":387},{"title":4052,"slug":4053},"Conference","conference",{"metadata":4055,"sys":4058,"fields":4067},{"tags":4056,"concepts":4057},[],[],{"space":4059,"id":4061,"type":16,"createdAt":4062,"updatedAt":4062,"environment":4063,"publishedVersion":469,"revision":23,"contentType":4065,"locale":28},{"sys":4060},{"type":12,"linkType":13,"id":14},"3SAe5dbaoSBYhl6LiCHv8U","2022-07-07T13:59:41.750Z",{"sys":4064},{"id":20,"type":12,"linkType":21},{"sys":4066},{"type":12,"linkType":26,"id":387},{"title":4068,"slug":4069,"description":4070},"Speaking","speaking",{"nodeType":371,"data":4071,"content":4072},{},[4073],{"nodeType":106,"data":4074,"content":4075},{},[4076],{"nodeType":68,"value":4077,"marks":4078,"data":4079},"All things about talks and speaking at conferences in general.",[],{},{"metadata":4081,"sys":4084,"fields":4094},{"tags":4082,"concepts":4083},[],[],{"space":4085,"id":4087,"type":16,"createdAt":4088,"updatedAt":4088,"environment":4089,"publishedVersion":4091,"revision":23,"contentType":4092,"locale":28},{"sys":4086},{"type":12,"linkType":13,"id":14},"1O8lQT6i7t0TEVK72kTxhk","2024-08-26T13:38:48.566Z",{"sys":4090},{"id":20,"type":12,"linkType":21},120,{"sys":4093},{"type":12,"linkType":26,"id":27},{"title":4095,"published":4096,"slug":4097,"heroImage":4098,"body":4118,"tags":4709},"So, You Want to Rock a Tech Talk? Here’s the Lowdown!","2024-08-25","so-you-want-to-rock-a-tech-talk-heres-the-lowdown",{"metadata":4099,"sys":4102,"fields":4110},{"tags":4100,"concepts":4101},[],[],{"space":4103,"id":4105,"type":41,"createdAt":4106,"updatedAt":4106,"environment":4107,"publishedVersion":4109,"revision":23,"locale":28},{"sys":4104},{"type":12,"linkType":13,"id":14},"3euAsVZtVuOhkSeG3qNG2U","2023-12-06T13:58:35.918Z",{"sys":4108},{"id":20,"type":12,"linkType":21},7,{"title":4111,"description":1127,"file":4112},"Joran at JSNation Amsterdam 2023",{"url":4113,"details":4114,"fileName":4117,"contentType":57},"//images.ctfassets.net/mqwrag4of3hk/3euAsVZtVuOhkSeG3qNG2U/06237a30568d83f05967413027699b0a/121._AS_JSNation_Amsterdam_20230601_1129.jpg",{"size":4115,"image":4116},84755,{"width":496,"height":497},"121. AS_JSNation_Amsterdam_20230601_1129.jpg",{"data":4119,"content":4120,"nodeType":371},{},[4121,4128,4135,4147,4159,4171,4178,4190,4238,4250,4262,4274,4286,4293,4313,4325,4337,4349,4356,4368,4380,4392,4404,4412,4460,4472,4484,4496,4503,4510,4518,4566,4578,4590,4602,4609,4621,4633,4645,4657,4664,4676,4688,4695,4702],{"data":4122,"content":4123,"nodeType":106},{},[4124],{"data":4125,"marks":4126,"value":4127,"nodeType":68},{},[],"Thinking about speaking at a tech conference? That’s awesome! But before you start planning your victory dance 🕺, let’s go over how to make your talk not just good, but downright unforgettable.",{"data":4129,"content":4130,"nodeType":148},{},[4131],{"data":4132,"marks":4133,"value":4134,"nodeType":68},{},[],"Before You Start… 🎤",{"data":4136,"content":4137,"nodeType":106},{},[4138,4143],{"data":4139,"marks":4140,"value":4142,"nodeType":68},{},[4141],{"type":73},"Choose What You're Passionate About",{"data":4144,"marks":4145,"value":4146,"nodeType":68},{},[],"\nFirst things first—pick a topic that gets you fired up. If you're excited, your audience will be too! Enthusiasm is like a good meme—it’s contagious, so spread that energy.",{"data":4148,"content":4149,"nodeType":106},{},[4150,4155],{"data":4151,"marks":4152,"value":4154,"nodeType":68},{},[4153],{"type":73},"Know Your Audience",{"data":4156,"marks":4157,"value":4158,"nodeType":68},{},[],"\nAre you talking to tech newbies or seasoned pros? Understanding your audience’s level of knowledge will help you pitch your talk just right. You wouldn’t give a \"how to cook\" lesson to a master chef, so tailor your content accordingly. If your audience needs additional context, provide it for them!",{"data":4160,"content":4161,"nodeType":106},{},[4162,4167],{"data":4163,"marks":4164,"value":4166,"nodeType":68},{},[4165],{"type":73},"Focus on One Core Message",{"data":4168,"marks":4169,"value":4170,"nodeType":68},{},[],"\nDon’t try to do too much. You’re not a Netflix series that can throw in ten plot twists. Stick to one key takeaway. Trust me, your audience will thank you for it. It will be much easier for you to: just one topic to focus on!",{"data":4172,"content":4173,"nodeType":148},{},[4174],{"data":4175,"marks":4176,"value":4177,"nodeType":68},{},[],"Content Preparation 📋",{"data":4179,"content":4180,"nodeType":106},{},[4181,4186],{"data":4182,"marks":4183,"value":4185,"nodeType":68},{},[4184],{"type":73},"Structure Your Talk",{"data":4187,"marks":4188,"value":4189,"nodeType":68},{},[],"\nJust like your favorite apps, your talk needs a solid structure:",{"data":4191,"content":4192,"nodeType":1204},{},[4193,4208,4223],{"data":4194,"content":4195,"nodeType":1163},{},[4196],{"data":4197,"content":4198,"nodeType":106},{},[4199,4204],{"data":4200,"marks":4201,"value":4203,"nodeType":68},{},[4202],{"type":73},"Introduction",{"data":4205,"marks":4206,"value":4207,"nodeType":68},{},[],": Start with a hook—something that makes them think, \"Hey, this is gonna be good!\"",{"data":4209,"content":4210,"nodeType":1163},{},[4211],{"data":4212,"content":4213,"nodeType":106},{},[4214,4219],{"data":4215,"marks":4216,"value":4218,"nodeType":68},{},[4217],{"type":73},"Body",{"data":4220,"marks":4221,"value":4222,"nodeType":68},{},[],": Break it down into digestible chunks. Case studies, demos, or real-life examples are your friends here.",{"data":4224,"content":4225,"nodeType":1163},{},[4226],{"data":4227,"content":4228,"nodeType":106},{},[4229,4234],{"data":4230,"marks":4231,"value":4233,"nodeType":68},{},[4232],{"type":73},"Conclusion",{"data":4235,"marks":4236,"value":4237,"nodeType":68},{},[],": Wrap it all up with a strong finish. Leave them with something to ponder, or better yet, something to do. ",{"data":4239,"content":4240,"nodeType":106},{},[4241,4246],{"data":4242,"marks":4243,"value":4245,"nodeType":68},{},[4244],{"type":73},"Tell a Story",{"data":4247,"marks":4248,"value":4249,"nodeType":68},{},[],"\nEverybody loves a good story, even in tech! Weave a narrative through your talk to make it relatable and engaging. And hey, don’t be afraid to throw in some humor—just keep it light (no stand-up comedy routines required). People tend to remember stories! 💡",{"data":4251,"content":4252,"nodeType":106},{},[4253,4258],{"data":4254,"marks":4255,"value":4257,"nodeType":68},{},[4256],{"type":73},"Data and Facts",{"data":4259,"marks":4260,"value":4261,"nodeType":68},{},[],"\nNumbers don’t lie, but they can definitely bore. Use data to back up your points, but keep it visual. Think charts, not spreadsheets. If you are keen on numbers, make them meaningful and don't overuse them.",{"data":4263,"content":4264,"nodeType":106},{},[4265,4270],{"data":4266,"marks":4267,"value":4269,"nodeType":68},{},[4268],{"type":73},"Use Analogies",{"data":4271,"marks":4272,"value":4273,"nodeType":68},{},[],"\nGot a complex concept? Analogies are like... (wait for it)... the breadcrumbs leading your audience out of the maze of confusion. (See what I did there?)",{"data":4275,"content":4276,"nodeType":106},{},[4277,4282],{"data":4278,"marks":4279,"value":4281,"nodeType":68},{},[4280],{"type":73},"When in Doubt, Verify",{"data":4283,"marks":4284,"value":4285,"nodeType":68},{},[],"\nNot sure about something? Don’t wing it. Reach out for feedback or plan a dry run. Better safe than sorry, right?",{"data":4287,"content":4288,"nodeType":148},{},[4289],{"data":4290,"marks":4291,"value":4292,"nodeType":68},{},[],"Slide Design 🎨",{"data":4294,"content":4295,"nodeType":106},{},[4296,4301,4305,4310],{"data":4297,"marks":4298,"value":4300,"nodeType":68},{},[4299],{"type":73},"Keep It Simple",{"data":4302,"marks":4303,"value":4304,"nodeType":68},{},[],"\nSlide text should be like a tweet—short and to the point. One idea per slide, please. And remember, there’s no such thing as too many slides—only ",{"data":4306,"marks":4307,"value":4309,"nodeType":68},{},[4308],{"type":73},"too much information on one slide",{"data":4311,"marks":4312,"value":2870,"nodeType":68},{},[],{"data":4314,"content":4315,"nodeType":106},{},[4316,4321],{"data":4317,"marks":4318,"value":4320,"nodeType":68},{},[4319],{"type":73},"Visuals Are Key",{"data":4322,"marks":4323,"value":4324,"nodeType":68},{},[],"\nDiagrams, infographics, and images can make your talk pop! They’re not just eye candy—they help your audience understand and remember your points. As they say: an image is worth a thousand words.",{"data":4326,"content":4327,"nodeType":106},{},[4328,4333],{"data":4329,"marks":4330,"value":4332,"nodeType":68},{},[4331],{"type":73},"Readable Text",{"data":4334,"marks":4335,"value":4336,"nodeType":68},{},[],"\nYour slides should be readable from the back of the room or on a tiny smartphone screen. No one wants to squint at your code snippet. Pay attention to contrast too. So apply the  `a11y` principles!",{"data":4338,"content":4339,"nodeType":106},{},[4340,4345],{"data":4341,"marks":4342,"value":4344,"nodeType":68},{},[4343],{"type":73},"Minimal Animation",{"data":4346,"marks":4347,"value":4348,"nodeType":68},{},[],"\nSave the flashy transitions for your TikTok videos. In your talk, animations should be used sparingly. Some streaming services might not even display them correctly, so keep it simple.",{"data":4350,"content":4351,"nodeType":148},{},[4352],{"data":4353,"marks":4354,"value":4355,"nodeType":68},{},[],"Speaking and Delivery 🗣️",{"data":4357,"content":4358,"nodeType":106},{},[4359,4364],{"data":4360,"marks":4361,"value":4363,"nodeType":68},{},[4362],{"type":73},"Practice, Practice, Practice",{"data":4365,"marks":4366,"value":4367,"nodeType":68},{},[],"\nRehearse your talk until you’re as comfortable with it as you are with your favorite code editor. But don’t worry about sticking to the script—just know your key points and let the rest flow naturally.",{"data":4369,"content":4370,"nodeType":106},{},[4371,4376],{"data":4372,"marks":4373,"value":4375,"nodeType":68},{},[4374],{"type":73},"Clear and Concise Language",{"data":4377,"marks":4378,"value":4379,"nodeType":68},{},[],"\nNo one’s here for a vocabulary test. Keep your language simple and straightforward. Avoid jargon unless you’re sure your audience is familiar with it. Check with your audience if you see confused looks!",{"data":4381,"content":4382,"nodeType":106},{},[4383,4388],{"data":4384,"marks":4385,"value":4387,"nodeType":68},{},[4386],{"type":73},"Pacing",{"data":4389,"marks":4390,"value":4391,"nodeType":68},{},[],"\nTake it easy! Give your audience time to absorb what you’re saying. A well-placed pause can be as powerful as the words themselves. It allows you to catch your breath too. Don't be afraid to sip some water to force yourself some pause.",{"data":4393,"content":4394,"nodeType":106},{},[4395,4400],{"data":4396,"marks":4397,"value":4399,"nodeType":68},{},[4398],{"type":73},"Modulate Your Voice",{"data":4401,"marks":4402,"value":4403,"nodeType":68},{},[],"\nMix up your tone, pitch, and volume to keep things interesting. Think of it like writing clean code—variety helps maintain readability.",{"data":4405,"content":4406,"nodeType":106},{},[4407],{"data":4408,"marks":4409,"value":4411,"nodeType":68},{},[4410],{"type":73},"Body Language",{"data":4413,"content":4414,"nodeType":1204},{},[4415,4430,4445],{"data":4416,"content":4417,"nodeType":1163},{},[4418],{"data":4419,"content":4420,"nodeType":106},{},[4421,4426],{"data":4422,"marks":4423,"value":4425,"nodeType":68},{},[4424],{"type":73},"Posture",{"data":4427,"marks":4428,"value":4429,"nodeType":68},{},[],": Stand tall—confidence is key.",{"data":4431,"content":4432,"nodeType":1163},{},[4433],{"data":4434,"content":4435,"nodeType":106},{},[4436,4441],{"data":4437,"marks":4438,"value":4440,"nodeType":68},{},[4439],{"type":73},"Gestures",{"data":4442,"marks":4443,"value":4444,"nodeType":68},{},[],": Use your hands to emphasize points, but don’t go overboard. You’re not conducting an orchestra.",{"data":4446,"content":4447,"nodeType":1163},{},[4448],{"data":4449,"content":4450,"nodeType":106},{},[4451,4456],{"data":4452,"marks":4453,"value":4455,"nodeType":68},{},[4454],{"type":73},"Eye Contact",{"data":4457,"marks":4458,"value":4459,"nodeType":68},{},[],": Make eye contact with your audience (or look into the camera if you’re virtual) to create a connection.",{"data":4461,"content":4462,"nodeType":106},{},[4463,4468],{"data":4464,"marks":4465,"value":4467,"nodeType":68},{},[4466],{"type":73},"Most importantly: ",{"data":4469,"marks":4470,"value":4471,"nodeType":68},{},[],"At the end of the day, be you! Authenticity resonates more than anything else. If you gesture a lot, gesture a lot! Don't force yourself to be someone else on stage than you are.",{"data":4473,"content":4474,"nodeType":106},{},[4475,4480],{"data":4476,"marks":4477,"value":4479,"nodeType":68},{},[4478],{"type":73},"Interact With the Audience",{"data":4481,"marks":4482,"value":4483,"nodeType":68},{},[],"\nGot a live audience? Engage with them! It’s a great way to keep everyone on their toes.",{"data":4485,"content":4486,"nodeType":106},{},[4487,4492],{"data":4488,"marks":4489,"value":4491,"nodeType":68},{},[4490],{"type":73},"Handling Q&A",{"data":4493,"marks":4494,"value":4495,"nodeType":68},{},[],"\nPrepare for questions, but if you get stumped, it’s okay to say, \"I don’t know, but I’ll find out!\" Honesty is always the best policy.",{"data":4497,"content":4498,"nodeType":148},{},[4499],{"data":4500,"marks":4501,"value":4502,"nodeType":68},{},[],"Virtual-Specific Tips 🖥️",{"data":4504,"content":4505,"nodeType":106},{},[4506],{"data":4507,"marks":4508,"value":4509,"nodeType":68},{},[],"Giving a virtual talk? Some people think this is easier, some think it's harder. It's definitely different though, so take these into consideration:",{"data":4511,"content":4512,"nodeType":106},{},[4513],{"data":4514,"marks":4515,"value":4517,"nodeType":68},{},[4516],{"type":73},"Tech Setup",{"data":4519,"content":4520,"nodeType":1204},{},[4521,4536,4551],{"data":4522,"content":4523,"nodeType":1163},{},[4524],{"data":4525,"content":4526,"nodeType":106},{},[4527,4532],{"data":4528,"marks":4529,"value":4531,"nodeType":68},{},[4530],{"type":73},"Stable Internet Connection:",{"data":4533,"marks":4534,"value":4535,"nodeType":68},{},[]," Because a dropped call is no one’s idea of fun.",{"data":4537,"content":4538,"nodeType":1163},{},[4539],{"data":4540,"content":4541,"nodeType":106},{},[4542,4547],{"data":4543,"marks":4544,"value":4546,"nodeType":68},{},[4545],{"type":73},"Good Lighting: ",{"data":4548,"marks":4549,"value":4550,"nodeType":68},{},[],"Light up your face, not your silhouette.",{"data":4552,"content":4553,"nodeType":1163},{},[4554],{"data":4555,"content":4556,"nodeType":106},{},[4557,4562],{"data":4558,"marks":4559,"value":4561,"nodeType":68},{},[4560],{"type":73},"Declutter: ",{"data":4563,"marks":4564,"value":4565,"nodeType":68},{},[],"Clean up your background, or go for a virtual one—just make sure it doesn’t steal the show.",{"data":4567,"content":4568,"nodeType":106},{},[4569,4574],{"data":4570,"marks":4571,"value":4573,"nodeType":68},{},[4572],{"type":73},"Engage the Audience",{"data":4575,"marks":4576,"value":4577,"nodeType":68},{},[],"\nVirtual talks can feel less personal, so crank up the energy a notch. Monitor the chat if possible, and don’t be afraid to interact!",{"data":4579,"content":4580,"nodeType":106},{},[4581,4586],{"data":4582,"marks":4583,"value":4585,"nodeType":68},{},[4584],{"type":73},"Backup Plan",{"data":4587,"marks":4588,"value":4589,"nodeType":68},{},[],"\nTech fails happen. Have a Plan B ready, like sharing your slides beforehand or having a backup device on hand.",{"data":4591,"content":4592,"nodeType":106},{},[4593,4598],{"data":4594,"marks":4595,"value":4597,"nodeType":68},{},[4596],{"type":73},"Live or Pre recorded?",{"data":4599,"marks":4600,"value":4601,"nodeType":68},{},[],"\nSome conference allow pre recorded sessions. These can be convenient when the conference schedule doesn't align with your personal schedule. Personally, treating it as a live event always forces me to deliver. Pick whatever you're comfortable with though!",{"data":4603,"content":4604,"nodeType":148},{},[4605],{"data":4606,"marks":4607,"value":4608,"nodeType":68},{},[],"General Speaking Pointers 🚀",{"data":4610,"content":4611,"nodeType":106},{},[4612,4617],{"data":4613,"marks":4614,"value":4616,"nodeType":68},{},[4615],{"type":73},"Nerves Are Normal",{"data":4618,"marks":4619,"value":4620,"nodeType":68},{},[],"\nEveryone gets nervous. Channel that energy into enthusiasm for your talk. And don’t forget to breathe!",{"data":4622,"content":4623,"nodeType":106},{},[4624,4629],{"data":4625,"marks":4626,"value":4628,"nodeType":68},{},[4627],{"type":73},"Adapt to Feedback",{"data":4630,"marks":4631,"value":4632,"nodeType":68},{},[],"\nWatch your audience for cues. If they look confused, don’t be afraid to adjust on the fly.",{"data":4634,"content":4635,"nodeType":106},{},[4636,4641],{"data":4637,"marks":4638,"value":4640,"nodeType":68},{},[4639],{"type":73},"Be Yourself",{"data":4642,"marks":4643,"value":4644,"nodeType":68},{},[],"\nThere’s no one-size-fits-all approach. Find your style and own it!",{"data":4646,"content":4647,"nodeType":106},{},[4648,4653],{"data":4649,"marks":4650,"value":4652,"nodeType":68},{},[4651],{"type":73},"Time Management",{"data":4654,"marks":4655,"value":4656,"nodeType":68},{},[],"\nStick to your time limit. There’s nothing worse than having to rush through your last points or, worse, being cut off mid-sentence.",{"data":4658,"content":4659,"nodeType":148},{},[4660],{"data":4661,"marks":4662,"value":4663,"nodeType":68},{},[],"After the Talk 🎉",{"data":4665,"content":4666,"nodeType":106},{},[4667,4672],{"data":4668,"marks":4669,"value":4671,"nodeType":68},{},[4670],{"type":73},"Seek Feedback & Reflect",{"data":4673,"marks":4674,"value":4675,"nodeType":68},{},[],"\nDon’t be afraid to ask for feedback. It’s the best way to get better. Take a moment to think about what went well and what didn’t. Every talk is a learning experience.",{"data":4677,"content":4678,"nodeType":106},{},[4679,4684],{"data":4680,"marks":4681,"value":4683,"nodeType":68},{},[4682],{"type":73},"Follow Up",{"data":4685,"marks":4686,"value":4687,"nodeType":68},{},[],"\nIf you promised resources or slides, be sure to send them out. It’s a great way to keep the conversation going. Is there a way to hang out or chat with attendees? Be sure to be visible and approachable after your talk to gather some feedback and possibly start interesting new conversations.",{"data":4689,"content":4690,"nodeType":517},{},[4691],{"data":4692,"marks":4693,"value":4694,"nodeType":68},{},[],"Find Your Comfort Zone",{"data":4696,"content":4697,"nodeType":106},{},[4698],{"data":4699,"marks":4700,"value":4701,"nodeType":68},{},[],"These tips, the preparations you've made, endless finetuning of your content, they should all help you in getting as comfortable as you can. For virtually everybody, public speaking induces stress. It can be happy stress, but it's stress either way. Being under stressful conditions is not where you deliver your finest work. So try to do anything you can do to reduce the stress factor.",{"data":4703,"content":4704,"nodeType":106},{},[4705],{"data":4706,"marks":4707,"value":4708,"nodeType":68},{},[],"Now that you’re armed with these tips, go forth and conquer the stage! Whether you’re a seasoned pro or a first-time speaker, you’ve got what it takes to deliver a killer tech talk. 🎙️💻",[4038,4054],true,50,0,1774484162796]