[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"contentNavigation":3,"topic-vue":4,"newsletter-stats":9,"articles-feed-\u002Ftopics\u002Fvue-1-vue-":11,"$fQa3xUpnRDPNiFFu2QS4K-DAjYmsapeR9fNhPNBdpkOc":-1,"home-tags":435},[],{"articleCount":5,"color":6,"id":7,"name":8,"slug":8},32,"#10b981","019d6bd8-c9a8-7783-bd22-03145b355427","vue",{"confirmedCount":10},409,{"items":12,"page":432,"pageSize":433,"totalCount":434},[13,44,70,90,114,134,155,177,200,218,238,265,287,308,331,349,366,385,401,416],{"content":14,"createdAt":15,"id":16,"image":17,"isAffiliate":18,"isPublished":19,"publishedAt":20,"slug":21,"sourceId":22,"sourceName":23,"sourceType":24,"summary":25,"title":26,"updatedAt":27,"url":28,"urlHash":29,"tags":30},"As Vue applications grow, keeping the codebase clean becomes increasingly challenging. At first, everyone follows the same conventions. But over time, you start noticing things like: inconsistent component structure multiple ways of solving the same problem different Composition API patterns imports scattered everywhere code that's difficult to review and maintain This is where ESLint becomes much more than a tool for formatting—it becomes a way to enforce your project's architecture and design patterns. In this article, we'll explore: Why ESLint is more than a linter How it helps maintain a consistent architecture Useful Vue-specific rules Examples of enforcing project-wide patterns Best practices for scaling Vue applications Let's dive in. 🤔 ESLint Is More Than a Code Formatter Many developers think ESLint is only used to catch things like; unused variables, missing semicolons, incorrect formatting. While that's true, ESLint can do much more. With the right configuration, it can enforce: coding conventions project architecture Vue best practices Composition API patterns import organization component structure Instead of relying on code reviews to catch inconsistencies, ESLint prevents them before the code is even merged. 🟢 What Problem Does It Solve? Imagine a team of five developers. One component looks like this: &lt;script setup&gt; ... &lt;\u002Fscript&gt; &lt;template&gt; ... &lt;\u002Ftemplate&gt; &lt;style&gt; ... &lt;\u002Fstyle&gt; Another one: &lt;template&gt; ... &lt;\u002Ftemplate&gt; &lt;script setup&gt; ... &lt;\u002Fscript&gt; Someone uses: watch() Someone else always prefers: watchEffect() Some developers use relative imports: ..\u002F..\u002F..\u002Fcomponents\u002FButton.vue Others use aliases: ~\u002Fcomponents\u002FButton.vue None of these are necessarily wrong... but together they create inconsistency across the project. ESLint helps eliminate these differences by enforcing one agreed-upon way of writing code. 🟢 Enforcing Vue Block Order One of the simplest examples is keeping Vue Single File Components organized. Using the vue\u002Fblock-order rule, you can define the exact order of blocks. Example: &lt;template&gt; ... &lt;\u002Ftemplate&gt; &lt;script setup lang=\"ts\"&gt; ... &lt;\u002Fscript&gt; &lt;style scoped&gt; ... &lt;\u002Fstyle&gt; 🟢 Enforcing Composition API Patterns One of the biggest advantages of ESLint is enforcing how developers use Vue APIs. For example, you might decide that your project should always use: &lt;script setup&gt; Composition API defineProps defineEmits And avoid Options API or inconsistent component definitions. This ensures new components follow the same architecture from day one. 🟢 Restricting Specific APIs Sometimes you want to discourage certain patterns altogether. For example, you may decide: ❌ Avoid watch() unless absolutely necessary. Prefer: computed() or watchEffect() ESLint can restrict the use of specific APIs and encourage better alternatives. This keeps reactive logic predictable and easier to maintain. 🟢 Enforcing Import Conventions Large Vue projects often suffer from inconsistent imports. Example: import Button from '..\u002F..\u002F..\u002Fcomponents\u002FButton.vue' vs. import Button from '~\u002Fcomponents\u002FButton.vue' ESLint can enforce: path aliases import ordering grouped imports no duplicate imports The result is cleaner and more consistent code. 🟢 Preventing Architectural Violations ESLint can also help enforce architectural boundaries. For example: Components shouldn't access API clients directly. Feature modules shouldn't import from other features. UI components shouldn't depend on business logic. Using rules such as no-restricted-imports, you can prevent these patterns entirely. Example: 'no-restricted-imports': [ 'error', { patterns: [ '@\u002Fapi\u002F*' ] } ] Now components can't accidentally bypass your intended architecture. 🟢 Creating Custom Rules for Your Team One of ESLint's greatest strengths is extensibility. Beyond built-in rules, you can create custom rules—or use plugins—to enforce project-specific conventions. For example: composables must start with use stores must live in a dedicated folder feature modules cannot import each other utility functions must remain pure internal design system components must be used instead of native HTML elements As your project grows, these automated checks become far more reliable than relying solely on code reviews. 🟢 Why This Matters in Large Vue Applications Small projects can survive without strict rules. Large projects usually can't. Consistency helps: onboard new developers faster simplify code reviews reduce technical debt prevent architectural drift improve long-term maintainability Instead of debating coding style in every pull request ESLint enforces it automatically. 🧪 Best Practices Treat ESLint as an architecture tool—not just a linter Enable Vue-specific rules from eslint-plugin-vue Agree on project conventions early Enforce Composition API patterns consistently Use no-restricted-imports to protect architectural boundaries Automate linting in CI\u002FCD pipelines Keep rules practical—avoid overcomplicating your configuration 📖 Learn more If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below: It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉 🧪 Advance skills A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success. Check out Certificates.dev by clicking this link or by clicking the image below: Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more! ✅ Summary ESLint is much more than a tool for catching syntax errors or enforcing formatting. As Vue applications grow, consistency becomes just as important as functionality. By using ESLint to enforce architectural decisions, you ensure that every new piece of code follows the same standards—making your project easier to understand, review, and maintain for years to come. Take care! And happy coding as always 🖥️","2026-07-06T12:00:09.479Z","019f374c-d2f0-769a-8a4f-180c7f565bd4","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fevhhwr5be00v4h9dmmxi.png",false,true,"2026-07-06T08:38:53.000Z","enforce-better-vue-architecture-with-eslint","019d6bd6-7fe0-7244-80dc-9a4e8751886a","Jakub Andrzejewski","rss","This article discusses how ESLint can be leveraged to enforce a consistent architecture and coding standards in Vue applications. It highlights the importance of using ESLint beyond formatting, showcasing its ability to maintain project-wide patterns, improve code review processes, and ensure best practices in Vue development, particularly with the Composition API.","Enforce Better Vue Architecture with ESLint","2026-07-06T12:00:24.181Z","https:\u002F\u002Fdev.to\u002Fjacobandrewsky\u002Fenforce-better-vue-architecture-with-eslint-3fb0","5987f1e0425bcd09cd7e156b69730144717e56a57baa8243a9f5f2c7670170ef",[31,32,35,38,41],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":33,"name":34,"slug":34},"019f374d-0cc4-71ff-b906-ebaec8b0c343","eslint",{"color":6,"id":36,"name":37,"slug":37},"019d6bd8-ca21-71c5-a236-37d94fe57d24","composition-api",{"color":6,"id":39,"name":40,"slug":40},"019d9cf0-ca04-75bb-ad86-ce8da1c0be23","architecture",{"color":6,"id":42,"name":43,"slug":43},"019d6bd9-010e-772d-b2f0-9378a042a676","best-practices",{"content":45,"createdAt":46,"id":47,"image":48,"isAffiliate":18,"isPublished":19,"publishedAt":49,"slug":50,"sourceId":51,"sourceName":52,"sourceType":24,"summary":53,"title":54,"updatedAt":55,"url":56,"urlHash":57,"tags":58},"This is the written-up version of the talk I gave at Vue MAD 2026 in Madrid: Clean Code Is Sexy Again. Making Your Vue Project AI-Ready. If you would rather watch it, here is the original recording on YouTube. Otherwise, read on. TLDR My main take: what is good for developers is also good for agents. There was never a separate “AI-ready” checklist. There was just good engineering, and now it pays off twice. “You don’t have to write code anymore” is half true. It only works if you know your stack and your codebase is built for an agent to work in. An agent is not magic. It is a loop: read context, pick a tool, run it, read the result, repeat. Once you have built one you stop asking “how does the magic work” and start asking “why does the same loop fly in one repo and fall apart in another.” Three things every Vue project should invest in: context (AGENTS.md, skills, hooks, a brain\u002F), feedback loops (types, lint, tests, a real browser), and discoverability (vertical feature slices). When the agent gets something wrong, fix the factory, not the PR. Add the lint rule, update AGENTS.md, tighten the prompt. The PR fix is one bug. The factory fix prevents the next hundred. The line everyone keeps repeating Everyone keeps saying the same thing: you don’t have to write code anymore. I think that’s half true. In some of my repos AI 10x’d me. In others it produced complete garbage. Same person, same agent, same model, different codebases. It only works if two things are true. First, you have real experience with the stack. I would not let an agent write Rust for me, because I have no idea what good Rust looks like and I could not review it. Second, the codebase has to be shaped so an agent can work in it. A greenfield project is easy. A brownfield project with no tests and 10,000-line components is a mess that AI makes worse, not better, until you clean it up. A good frame for “where are we” comes from Dan Shapiro’s post on the levels of AI-assisted development. It reads like driving automation. Level 0 is spicy autocomplete, the first Copilot. Then agents arrive and it gets a lot better. At the top is the software factory where the agent defines, ships, and fixes on its own. I put myself at level three. The agent writes most of the code, and I spend my time reviewing and reading every line. Sometimes I feel like the bottleneck. I would not recommend level four or five for anything serious yet, but the pace is real. Two weeks before the talk, the creator of Bun started using Claude Code to rewrite Bun from Zig to Rust. A million lines, in days, almost entirely by an agent. Triumph or disaster, I don’t know. What I know is this is the world we ship into. What an agent actually is Most Vue devs treat agents as a magic box. Magic is the wrong mental model. The best tip I can give you to get better at AI is to build your own coding agent once. Then it stops being magic, and you get a feel for why it does the right thing sometimes and the wrong thing other times. I wrote up the full build in Building Your Own Coding Agent From Scratch, but here is the whole picture in one image. The agent is bounded by three things: its context window, the tools you give it, and its ability to verify what it did. That is it. The analogy that unlocks everything is treating the agent like a new engineer joining your team. You would not throw a new hire into your worst legacy module and expect a feature in a week. Same with an agent. Strip the magic and a tool is just a function. Three fields: a description, a schema for the arguments, and the function that runs. type Tool = { description: string schema: Record&lt;string, string&gt; execute: (args: Record&lt;string, unknown&gt;) =&gt; Promise&lt;string&gt; } const TOOLS = new Map&lt;string, Tool&gt;([ ['read', { description: 'Read file with line numbers (not a directory)', schema: { path: 'string', offset: 'number?', limit: 'number?' }, execute: read, }], ['edit', { description: 'Replace old with new in file (old must be unique)', schema: { path: 'string', old: 'string', new: 'string' }, execute: edit, }], ['bash', { description: 'Run shell command', schema: { cmd: 'string' }, execute: bash, }], ]) Here is the part that demystifies everything: the model only ever sees the description and the schema. The execute function never leaves your machine. The model cannot run read(), it cannot even see it. So how does it “use” a tool? It reads the description and emits a request: “call read with path src\u002FApp.vue.” Your loop runs the real function and feeds the result back. Which means the description is the prompt. A vague description is a tool the model misuses. Tool descriptions are engineering, not docs. And the loop is just recursion. async function agentLoop(messages, systemPrompt, tools = TOOLS) { const response = await callApi(messages, systemPrompt, tools) const toolResults = await processToolCalls(response.content) const newMessages = [ ...messages, { role: 'assistant', content: response.content }, ] \u002F\u002F No tool calls → the agent is done if (toolResults.length === 0) return newMessages \u002F\u002F Tool calls → loop with results as the next user turn return agentLoop( [...newMessages, { role: 'user', content: toolResults }], systemPrompt, tools, ) } Call the API. The model replies with text and maybe some tool requests. Run each one, append the assistant reply and the tool results, and loop. When the model returns no tool calls, it is done. And messages is not a database or a session store. It is an array of { role, content }. That array is the agent’s memory. Every turn you append to it. I built a tiny version of this a few months ago and called it nanocode, around 350 lines of TypeScript. It is not perfect, but building it is what made the whole thing click. Once you see an agent this way, the question stops being “how does the magic work” and becomes “why does the same simple loop work brilliantly in one repo and fall apart in another?” That is the rest of this post. Clean code isn’t nice-to-have anymore I have been in plenty of projects where people told me “we don’t have time to write tests.” That argument is over. You do not need new patterns for AI. The patterns you already fight for in code review, the ones the senior dev keeps insisting on, are exactly the patterns that make agents work. A codebase that is hard for humans is hard for agents. Sprawl, hidden coupling, magical state: humans hate it, agents fail at it. In Vue, three things are worth investing in: context, feedback loops, and discoverability. Part 1: Context The agent is Leonard from Memento. Every new chat, the context resets. No long-term memory, no yesterday. So, like Leonard, it has to tattoo the rules where it will read them every single turn. That tattoo is AGENTS.md (or CLAUDE.md). It is the first thing you can optimize. But the tattoo space is finite, and most of it is already used before you write a word. Every model has a context window, and it works best when it is not full. Models degrade as the window fills: recall drops, reasoning slips, the agent starts confusing files. And the window is not empty when you start. The system prompt and the tool definitions already cost around 20k tokens before you type anything. AGENTS.md, skills, MCP servers, and sub-agents all spend from the same pool. In Claude Code you can see exactly where it goes by typing \u002Fcontext. This is why the biggest mistake with AGENTS.md is dumping everything into it: every coding rule, every bug post-mortem, every gotcha, 2000 lines that load on every single turn. A better shape is a thin doorway: # AGENTS.md Run `pnpm lint:fix &amp;&amp; pnpm typecheck` after changes. ## Stack Nuxt 4, @nuxt\u002Fcontent v3, @nuxt\u002Fui v3 ## Structure - `app\u002F` — Vue application - `content\u002F` — Markdown files ## Further reading **IMPORTANT:** read the relevant doc below before starting any task. - `docs\u002Fnuxt-content-gotchas.md` - `docs\u002Ftesting-strategy.md` The agent loads testing-strategy.md only when it writes a test, nuxt-content-gotchas.md only when it touches content. That is progressive disclosure: the right context at the right time. Two filters before a line goes into AGENTS.md. Can a tool enforce it? Then do not write prose about it. Is it universal or situational? Situational goes in docs\u002F. I go deeper on the AGENTS.md-versus-skills split in my Claude Code customization guide, and on why context fills up the way it does in reverse-engineering HumanLayer’s context engineering. brainmaxxing Forget looksmaxxing. We are brainmaxxing: maxing the one thing the agent has, its context. brainmaxxing is an open-source kit from a Cursor developer. It is a framework for giving an agent a documented memory, and it has three pieces. First, a brain\u002F folder. Plain markdown. The agent reads from it and writes back to it. There is one index.md with wiki-links describing the documentation that exists, and the rest is markdown files for codebase notes, plans, and principles. People found out you do not need RAG or anything complex. The simplest approach, wiki-links and markdown files, works best, and now the agent has a memory. (If you want the theory of why files beat a vector database here, I wrote it up in the four types of memory for coding agents.) Second, skills. A skill is like a prompt that lives in a markdown file with a name and a description. When you start Claude Code, only the name and description enter the context. When your prompt matches, the body loads. When the body calls a script, the script loads. Three levels of lazy loading, so skills scale. brainmaxxing’s \u002Freflect skill is a good example: at the end of a session it reviews the conversation and persists what mattered back into brain\u002F. So when the agent uses the wrong command and you correct it, you just say “remember this,” and it updates its own memory. Third, hooks. Vue has lifecycle hooks like onMounted. Claude Code has lifecycle hooks too. brainmaxxing wires a SessionStart hook that cats index.md into every new session, so the agent boots up already knowing the map. There are many more events. PreToolUse can block a destructive command or forbid reading your .env. PostToolUse can re-lint after an edit. SessionEnd could even send you a notification. I cover skills and hooks hands-on in my Vue workout tracker walkthrough. brainmaxxing also ships principles, around 16 markdown files describing how you want code written. One is boundary discipline: business logic lives in pure functions, the shell is thin and mechanical. The agent reads them and develops a better taste for your code. You can write your own too. Claude Code itself now ships something similar, called auto memory: it writes markdown notes about your project automatically. The catch is those files only live on your machine. That is exactly why I like keeping brain\u002F in Git. Check it in and the whole team’s agent boots up with the same memory on day one. The new hire on Monday starts where the team is, not from zero. Want VueUse-style code? Give the agent VueUse One more trick, and it is bigger than memory. You want the agent to use VueUse or Nuxt UI, but its training data is out of date and it does not know the current API. So give it the source. Clone the library into your repo as a git subtree: git subtree add --prefix=repos\u002Fvueuse \\ https:\u002F\u002Fgithub.com\u002Fvueuse\u002Fvueuse main --squash Then point AGENTS.md at it: ## Reference repositories - `repos\u002Fvueuse\u002F` — when writing new composables, mirror the patterns in `repos\u002Fvueuse\u002Fpackages\u002Fcore\u002Fuse*\u002F`. Now the agent’s pattern matching is anchored on real source instead of stale docs. Agents are post-trained on reading code, not prose. A subtree beats a submodule (no clone-time pain, just files) and beats pointing at node_modules (compiled and flattened, the structure is gone). One refinement: tell your editor to ignore repos\u002F so you do not accidentally auto-import VueUse internals, and have the agent distill what it learned into a short agent-patterns\u002Fvueuse.md so it does not re-explore 800 composables every session. This sounds stupid, but once you try it, it works far better than MCPs in my experience. The pattern comes from the Effect team’s post, The One Weird Git Trick That Makes Coding Agents More Effect-ive. Part 2: Feedback loops If an agent does not know when it broke something, it ships whatever compiles. So you give it deterministic ways to check its own work. Type safety is the first lie-detector. A strict tsconfig is non-negotiable, and noUncheckedIndexedAccess and exactOptionalPropertyTypes catch what default strict mode lets through. Types are a compile-time fiction, though, so parse with Zod or Valibot at every untyped boundary: fetch responses, route params, env vars, form input. Lint and format with Oxlint and Oxfmt. They are roughly 50x and 30x faster than ESLint and Prettier, fast enough to run on every save instead of batching at the end. Two Vue lint rules in particular keep components agent-friendly, because nobody, human or agent, can read a 3000-line component: 'vue\u002Fmax-template-depth': ['error', { maxDepth: 8 }] 'vue\u002Fmax-props': ['error', { maxProps: 6 }] A 12-prop component is a god object pretending to be one. I wrote up my full set in my opinionated ESLint setup for Vue projects, including custom local rules. Then tests. Vitest for units, and the big 2026 win, Vitest browser mode, which runs component tests in a real Chromium via Playwright instead of jsdom. Hover, focus, layout, scroll, all behave like production. The agent can finally trust that “passes in tests” means “works in a browser.” I go deep on this in the Vue testing pyramid with Vitest browser mode. Those are four layers. There are 11 more: API mocking, contract tests, E2E, accessibility, visual regression, performance, dead-code detection, and so on. Every one is a signal the agent can chase to green on its own. The cheap ones at the center run on every save, the expensive ones at the edge run in CI. What I now do in a new project is hand the agent my own write-up and say “set up the layers that make sense here.” The full breakdown lives in the modern frontend quality pipeline. The agent as a user Static checks can be green and the feature can still be broken. Did the modal open? Did the chart render? You need the agent to be the user. Vercel’s agent-browser is a browser CLI shaped for agents. One install and the agent has a real Chromium it can drive from the command line. npm i -g agent-browser agent-browser install agent-browser open localhost:5173 agent-browser snapshot -i # DOM tree with @refs agent-browser click @e2 # click by ref agent-browser screenshot --annotate agent-browser console # read page console The snapshot returns the DOM as plain text with refs, the agent clicks by ref, screenshots come back annotated, console errors come back as text. So when there is a bug, you say “reproduce it with agent-browser,” and once the agent can reproduce something, fixing it is easy. The same thing a good developer would do. For this to work the app has to be agent-runnable: the dev server is one command, the port is stable, there is a way to know the server is ready, and test data is seeded so the agent does not hit a login wall. Then “types pass” is no longer the bar. “Works in a browser” is. I built a full version of this into CI in automated QA with Claude Code, agent-browser, and GitHub Actions. Finally, put a gate at commit time. Lefthook (or Husky) runs lint, typecheck, and the related tests on every commit, so bad code does not reach main. I prefer Lefthook because it runs jobs in parallel and the config is YAML the agent can read and edit, not a shell-script soup. The one rule: no --no-verify escape hatch. The whole point of the gate is that it does not open. # lefthook.yml pre-commit: parallel: true jobs: - run: pnpm oxlint - run: pnpm vue-tsc --build - run: pnpm vitest related --run {staged_files} Part 3: Discoverability Most Vue apps start flat. You run create vue and you get components\u002F, composables\u002F, stores\u002F, views\u002F, router\u002F. Everything is grouped by what a file is. That is fine for small apps, but in a real application that components\u002F folder grows to 80+ files, and a single “checkout” change is scattered across three folders. The agent has the same problem you do: it greps across the whole tree and most of what it pulls back is noise. Feature slicing groups by what files do, not by what they are. First you find the domains. Imagine a workout tracker: the domains are workout, timers, exercises, and settings. Then each domain owns its own components, composables, and store: src\u002Ffeatures\u002F ├── workout\u002F │ ├── components\u002F │ ├── composables\u002F │ └── store.ts ├── timers\u002F ├── exercises\u002F └── settings\u002F Finding the domains is the hard part on a big codebase, but once you have them, “change the settings page” means opening one folder. Same files, same code, different addressing. And the win for the agent is concrete. Ask it to “add a streak counter to the active workout.” In a flat layout it greps components\u002F and composables\u002F and pulls back SettingsForm, TimerDisplay, useSettings, maybe 40% relevant. In a feature layout it lists features\u002Fworkout\u002F and gets exactly the files that matter, 100% relevant. No grep, no guess, tokens go to output instead of search. Folders alone do not keep the agent honest, so add three import rules. Arrows only point down the layers. Sibling features never import each other; if they share something, it moves to a shared layer like components\u002F or lib\u002F. And a page that uses two features composes them at the page level rather than letting one feature reach into another. The most important rule is the second one: features stay decoupled. As a bonus, a codebase split this way is already shaped for a micro-frontend approach if you ever need it. Where this is heading AFK coding (away from keyboard) is already here. You write a spec, kick off an agent, and walk away. It runs the tests, hits a failure, fixes itself, runs again, and opens a draft PR with a summary. You review. The work is no longer “me typing.” It is “me deciding what should exist, and reviewing what came back.” The loop in practice has humans at the edges and agents in the middle. You align with the business on the spec, the agent breaks the big ticket into vertical sub-tickets, one agent works each slice with TDD inside, a dedicated refactor pass runs (the step LLMs always skip), a QA agent drives the real browser, and then you read the PR. I wrote the long version in how to do AFK coding. The most important thing in this loop is what you do when it goes wrong. The agent ships a bug, and the instinct is to fix the bug, merge, and move on. That instinct is wrong. Fix the factory, not the PR. A bug is not a bug, it is a factory defect. Add an ESLint rule that catches that whole class of mistake. Update AGENTS.md so the convention is written down. Tighten the slash command or the prompt if that is where it leaked. The PR fix is one bug. The factory fix prevents the next hundred. And if the codebase is messy in the first place, use the agent to refactor it before you expect any of this to work. Every PR review teaches the factory, and the codebase gets smarter over time. As a test of all this, the week before the talk I tried to port React Ink (declarative components for terminal UIs) to Vue, using AI only. It worked surprisingly well. The approach combined everything above. I vendored Ink, Vue core, and VueUse into repos\u002F as read-only source. I used a brain\u002F vault for gotchas and an api-tracker. And because React Ink has a lot of tests, I ported the tests first: each Ava scenario became a Vitest test at the behavior level, not the React implementation. Run it, red, no implementation yet. Then translate the implementation, JSX to SFC, hooks to composables. Run it, green. Then reflect the learnings back into brain\u002F so the loop sharpens itself. I would not publish it as a real library without going back and understanding every line first, but as a proof that you can port a well-tested React library to Vue mostly AFK, it holds up. I even added a Stop hook that fires when a turn ends and spawns a second, headless Claude in the background to read the session transcript and write only new durable learnings into brain\u002F. The one gotcha is that the child also ends a turn, which would fire the hook forever, so an env flag marks the child and the hook bails when it sees it. The project updates its own docs while I get coffee. The twist This talk was not really about AI. I tricked you. None of it is new. Testing, TDD, feature-based architecture, strict types, small components: these are the things senior engineers have fought for in code review for twenty years. They were good before a single agent existed. The only thing that changed is the payoff. The same discipline that used to make a codebase pleasant for the next human now also makes it tractable for an agent, so every hour you spent caring about architecture quietly started earning twice. That is the whole bet. Tight context, plenty of feedback loops, real discoverability. Which of them is your project missing? Come find me and tell me what your AGENTS.md looks like.","2026-06-27T16:00:02.356Z","019f09cf-3518-7096-8fef-95033e6e53c2","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F9bKMqvFRvvI\u002Fhqdefault.jpg","2026-06-27T00:00:00.000Z","clean-code-is-sexy-again-making-your-vue-project-ai-ready","019d70dd-e3e7-76db-84a4-87b896dea004","alexop.dev","The article discusses the importance of clean code in making Vue projects ready for AI integration, emphasizing that good engineering practices benefit both developers and AI agents. It highlights the need for context, feedback loops, and discoverability in projects to enable effective AI assistance, while cautioning that AI's effectiveness depends on the developer's familiarity with the stack and the structure of the codebase.","Clean Code Is Sexy Again: Making Your Vue Project AI-Ready","2026-06-29T20:00:17.397Z","https:\u002F\u002Falexop.dev\u002Fposts\u002Fclean-code-is-sexy-again-vue-ai-ready\u002F","308ed1fc6ac401b781ff16aa2e321e0a152bfe1110030261e6875e67b16f015c",[59,60,63,66,69],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":61,"name":62,"slug":62},"019d9d20-e07b-7685-9ebb-fae0b963f243","ai",{"color":6,"id":64,"name":65,"slug":65},"019f09cf-5bcd-751c-8d46-9e123bd784af","clean-code",{"color":6,"id":67,"name":68,"slug":68},"019dafe9-8a6d-7218-81f1-37052cbe9b78","development",{"color":6,"id":42,"name":43,"slug":43},{"content":71,"createdAt":72,"id":73,"image":74,"isAffiliate":19,"isPublished":19,"publishedAt":75,"slug":76,"sourceId":77,"sourceName":78,"sourceType":79,"summary":80,"title":81,"updatedAt":82,"url":83,"urlHash":84,"tags":85},"A walkthrough of rstore, the reactive data store for Vue with normalized caching, typed queries, and a plugin system.","2026-06-24T16:00:01.514Z","019efa5c-1dcf-7449-b141-49f59d41bfa3","https:\u002F\u002Fapi.certificates.dev\u002Fstorage\u002F6T1G3YTDa1KvET0HBRnJMoBZe7vaRZ4YdfvKCPrp.png","2026-06-24T06:00:00.000Z","getting-started-with-rstore-in-vue","019d9eed-d835-729a-a029-7e6320cb67ed","Certificates.dev","certificatesdev","This article provides a comprehensive introduction to rstore, a reactive data store designed for Vue. It covers features like normalized caching, typed queries, and the plugin system, making it a valuable resource for developers looking to enhance their Vue applications.","Getting Started with rstore in Vue","2026-06-24T16:00:11.531Z","https:\u002F\u002Fcertificates.dev\u002Fblog\u002Fgetting-started-with-rstore-in-vue?friend=MOKKAPPS","92673f6bbece73fdf566b6c5a264e5ec9209284ad7a6995ef38bcec30f095340",[86,87],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":88,"name":89,"slug":89},"019da076-78fb-706b-9a4c-cee0c989cfff","state-management",{"content":91,"createdAt":92,"id":93,"image":94,"isAffiliate":18,"isPublished":19,"publishedAt":95,"slug":96,"sourceId":22,"sourceName":23,"sourceType":24,"summary":97,"title":98,"updatedAt":99,"url":100,"urlHash":101,"tags":102},"Performance has become one of the most important aspects of modern frontend development. Users expect websites to be fast and Google rewards fast websites. And yet... even experienced Vue developers still introduce performance issues that can significantly impact user experience. The tricky part? Most applications work perfectly fine during development. Problems usually appear later: larger datasets slower devices poor network conditions increased application complexity In this article, we'll look at 10 common Vue performance mistakes I still see in production applications and how to fix them. Let's dive in. 🤔 Why Vue Performance Matters Vue is already a highly optimized framework. However, even the best framework cannot compensate for inefficient application code. Poor performance can lead to: slow page loads delayed interactions poor Core Web Vitals scores increased battery usage frustrated users The good news? Most performance issues can be fixed with relatively small changes. 🟢 Mistake #1: Using Deep Watchers Everywhere A common mistake is enabling deep watchers on large objects. Example: watch( userData, () =&gt; { saveDraft() }, { deep: true } ) Deep watchers force Vue to traverse the entire object tree. For large datasets this can become very expensive. Instead: watch specific properties split large objects use computed values when possible 🟢 Mistake #2: Making Everything Reactive Not every piece of data needs reactivity. I often see code like this: const hugeDataset = ref(largeArray) When the data rarely changes, Vue still needs to create reactive proxies. For large collections this introduces unnecessary overhead. A better approach: const hugeDataset = shallowRef(largeArray) Or even: const hugeDataset = markRaw(largeArray) when reactivity isn't needed at all. 🟢 Mistake #3: Creating New Objects Inside Computed Properties Consider this: const userInfo = computed(() =&gt; ({ name: user.value.name, role: user.value.role })) A brand-new object is created every time the computed runs. This can trigger unnecessary component updates. Instead, prefer returning primitives when possible or memoizing expensive transformations. 🟢 Mistake #4: Using v-if Instead of v-show for Frequently Toggled Elements Many developers use: &lt;div v-if=\"isOpen\"&gt; Content &lt;\u002Fdiv&gt; But if the element is shown and hidden frequently, Vue must repeatedly: mount render destroy A better option: &lt;div v-show=\"isOpen\"&gt; Content &lt;\u002Fdiv&gt; This simply toggles CSS visibility. For frequently toggled UI elements, it's usually much faster. 🟢 Mistake #5: Rendering Huge Lists Without Virtualization Rendering thousands of DOM nodes is expensive. Example: &lt;div v-for=\"user in users\" :key=\"user.id\" &gt; {{ user.name }} &lt;\u002Fdiv&gt; This might work with 100 items. It won't feel great with 10,000. Instead consider: virtual scrolling pagination infinite loading Libraries like Vue Virtual Scroller can dramatically improve performance. 🟢 Mistake #6: Lazy Loading Nothing Many applications ship their entire codebase on the first page load. Example: import UserSettings from '.\u002FUserSettings.vue' This increases: bundle size download time parse time Instead: const UserSettings = defineAsyncComponent( () =&gt; import('.\u002FUserSettings.vue') ) Users only download code when it's actually needed. 🟢 Mistake #7: Fetching Data Sequentially A surprisingly common issue: const users = await fetchUsers() const posts = await fetchPosts() const comments = await fetchComments() Each request waits for the previous one. A faster approach: const [users, posts, comments] = await Promise.all([ fetchUsers(), fetchPosts(), fetchComments() ]) This can reduce loading times significantly. 🟢 Mistake #8: Forgetting About Image Optimization Images are often the largest assets on a page. Yet many applications still serve: oversized images uncompressed formats images outside the viewport For Vue and Nuxt applications: use WebP or AVIF lazy load images generate responsive sizes Image optimization frequently provides the biggest performance wins. 🟢 Mistake #9: Ignoring Component Re-Renders A component may render far more often than expected. For example: &lt;ExpensiveChart :data=\"chartData\" \u002F&gt; If chartData changes reference on every update, the chart keeps re-rendering. Common solutions: stabilize references use shallowRef avoid unnecessary reactive updates profile components with Vue DevTools Small changes here can have a huge impact. 🟢 Mistake #10: Never Measuring Performance The biggest mistake? Not measuring anything. Many teams optimize blindly. Instead, regularly check: Lighthouse Core Web Vitals Vue DevTools Chrome Performance Panel Network waterfalls Performance work should be data-driven. You can't improve what you don't measure. 🟢 Performance Checklist Before shipping a Vue application, ask yourself: ✅ Am I using deep watchers only when necessary? ✅ Do all objects really need reactivity? ✅ Are large lists virtualized? ✅ Are routes and components lazy loaded? ✅ Are API requests running in parallel? ✅ Are images optimized? ✅ Have I measured actual performance? If any answer is \"no\", there may be easy performance wins available. 🧪 Best Practices Use shallowRef for large datasets Avoid deep watchers whenever possible Lazy load routes and heavy components Virtualize large lists Optimize images aggressively Profile real-world user flows Monitor Core Web Vitals Measure before and after every optimization 📖 Learn more If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below: It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉 🧪 Advance skills A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success. Check out Certificates.dev by clicking this link or by clicking the image below: Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more! ✅ Summary Vue is fast by default. But performance problems often come from how we use the framework rather than the framework itself. In this article, you learned: 10 common Vue performance mistakes Why they impact real-world applications How to identify them Practical ways to fix them Best practices for building faster Vue apps Many of these issues are easy to overlook during development but become expensive at scale. By avoiding these mistakes and measuring performance regularly, you can build applications that feel fast, responsive, and enjoyable to use. Take care! And happy coding as always 🖥️","2026-06-15T08:00:09.697Z","019eca4b-8dce-754e-ad17-a0f9b1aef338","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidhps7seqfikj9j24oz3.png","2026-06-15T07:08:48.000Z","10-vue-performance-mistakes-i-still-see-in-production-apps","This article discusses ten common performance mistakes that Vue developers often make in production applications, highlighting issues such as using deep watchers unnecessarily and making everything reactive. It emphasizes the importance of optimizing performance to enhance user experience and offers practical solutions to improve application efficiency.","10 Vue Performance Mistakes I Still See in Production Apps","2026-06-15T08:00:29.794Z","https:\u002F\u002Fdev.to\u002Fjacobandrewsky\u002F10-vue-performance-mistakes-i-still-see-in-production-apps-52a1","4bad7a0b92210da78523e2dbba139490f2eade4aa9b344635bb1bb7b69b6959a",[103,104,107,110,113],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":105,"name":106,"slug":106},"019d6bd8-ca26-775c-b9b5-c3439dbe5789","performance",{"color":6,"id":108,"name":109,"slug":109},"019e3af5-4a35-705c-8ab1-4404b653e0e8","optimization",{"color":6,"id":111,"name":112,"slug":112},"019daac3-2f85-7393-b891-9da3891267ca","reactivity",{"color":6,"id":42,"name":43,"slug":43},{"content":115,"createdAt":116,"id":117,"image":118,"isAffiliate":19,"isPublished":19,"publishedAt":119,"slug":120,"sourceId":77,"sourceName":78,"sourceType":79,"summary":121,"title":122,"updatedAt":123,"url":124,"urlHash":125,"tags":126},"A hands-on walkthrough of TresJS, the Vue custom renderer for Three.js. From a blank canvas to a reactive 3D scene.","2026-06-16T16:11:23.030Z","019ed133-a3ff-777b-adc9-d4611efcce78","https:\u002F\u002Fapi.certificates.dev\u002Fstorage\u002FJzzmU8odS8xTY4oUOFA5dKGDUZ9t1KTrC32UQtOD.png","2026-06-10T06:00:00.000Z","building-3d-scenes-with-tresjs","This article provides a hands-on guide to using TresJS, a Vue custom renderer for Three.js, to create reactive 3D scenes. It walks through the process from starting with a blank canvas to building interactive 3D visuals.","Building 3D Scenes with TresJS","2026-06-16T16:11:31.024Z","https:\u002F\u002Fcertificates.dev\u002Fblog\u002Fbuilding-3d-scenes-with-tresjs?friend=MOKKAPPS","2e1b1561dca4ab364f3836c76e19030b82096d6ba565f6dc48db6e10c7ad2f55",[127,128,131],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":129,"name":130,"slug":130},"019ed133-c390-75bf-8f1a-5c57cd221f14","threejs",{"color":6,"id":132,"name":133,"slug":133},"019d6bd8-ca8b-709c-b9a5-77d4910da162","ui-components",{"content":135,"createdAt":136,"id":137,"image":138,"isAffiliate":18,"isPublished":19,"publishedAt":139,"slug":140,"sourceId":22,"sourceName":23,"sourceType":24,"summary":141,"title":142,"updatedAt":143,"url":144,"urlHash":145,"tags":146},"As frontend applications become more complex, debugging production issues becomes increasingly difficult. A user reports: \"The page feels slow.\" or: \"The dashboard sometimes freezes.\" But when you check your logs... everything looks fine. The problem is that traditional frontend monitoring often tells you what failed, but not why it happened. This is where observability comes in. And one of the most popular tools for modern observability is OpenTelemetry. In this article, we'll explore: What frontend observability is How it differs from traditional monitoring Why OpenTelemetry is becoming the industry standard How to add OpenTelemetry to a Vue application Best practices for collecting useful telemetry Let's dive in. 🤔 What Is Frontend Observability? Observability is the ability to understand what's happening inside your application by collecting telemetry data. Typically, this includes: traces metrics logs Unlike traditional monitoring, observability helps answer questions like: Why is this page slow? Which API request caused the delay? What happened before the error occurred? Which users are affected? Instead of simply knowing that something failed... 👉 You can understand the entire chain of events that led to the problem. 🟢 Why Is Frontend Observability Important? Most teams invest heavily in backend observability. They track: database queries API latency server errors infrastructure metrics But users interact with the frontend. And many issues happen before the request even reaches the backend. For example: slow component rendering blocked main thread failed network requests routing issues third-party script delays Without frontend observability these problems are often invisible. 🟢 What Is OpenTelemetry? OpenTelemetry (often called OTel) is an open-source observability framework used to collect and export telemetry data. It provides a standard way to collect: traces metrics logs And send them to tools such as: Grafana Jaeger Datadog New Relic Honeycomb Elastic The biggest advantage? Vendor-neutral instrumentation. You can change observability providers without rewriting your instrumentation. 🟢 How OpenTelemetry Helps Vue Applications Imagine a user loads a dashboard. Several things happen: Route change ↓ Component mounts ↓ API request starts ↓ Data is fetched ↓ UI renders Normally these events are disconnected. With OpenTelemetry you can trace the entire flow. This helps answer questions like: Which API call slowed down the page? How long did rendering take? Which routes are causing performance issues? 🟢 Setting Up OpenTelemetry in Vue Let's look at a simplified setup. Install the required packages: npm install \\ @opentelemetry\u002Fapi \\ @opentelemetry\u002Fsdk-trace-web \\ @opentelemetry\u002Finstrumentation-fetch \\ @opentelemetry\u002Finstrumentation-xml-http-request Basic initialization import { WebTracerProvider } from '@opentelemetry\u002Fsdk-trace-web' const provider = new WebTracerProvider() provider.register() This creates a tracer that can collect telemetry from the browser. 🟢 Creating Custom Traces One of the most powerful features is custom tracing. Example: import { trace } from '@opentelemetry\u002Fapi' const tracer = trace.getTracer('vue-app') Inside a component: const span = tracer.startSpan('load-users') try { await fetchUsers() } finally { span.end() } Now you'll see exactly how long that operation took. This becomes extremely useful when debugging production issues. 🟢 Tracking Route Performance Vue Router is another excellent place to add tracing. Example: router.beforeEach((to, from, next) =&gt; { performance.mark('navigation-start') next() }) router.afterEach(() =&gt; { performance.measure( 'navigation', 'navigation-start' ) }) Combined with OpenTelemetry exporters, this can help identify slow routes and navigation bottlenecks. 🟢 Monitoring API Requests Many performance problems originate from network calls. OpenTelemetry provides automatic instrumentation for: Fetch API XMLHttpRequest Example: registerInstrumentations({ instrumentations: [ new FetchInstrumentation() ] }) Now requests can automatically generate traces. You can see: request duration failures dependencies between actions without manually instrumenting every API call. 🧪 Best Practices Instrument critical user flows first Trace important API requests Avoid collecting unnecessary telemetry Sample traces in high-traffic applications Correlate frontend traces with backend traces Monitor route transitions and rendering bottlenecks Focus on actionable insights rather than collecting everything 📖 Learn more If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below: It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉 🧪 Advance skills A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success. Check out Certificates.dev by clicking this link or by clicking the image below: Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more! ✅ Summary Frontend observability helps you understand not just what went wrong, but why it happened. As applications grow in complexity, logs and error tracking alone are often no longer enough. OpenTelemetry gives you deeper visibility into your Vue application, helping you identify bottlenecks, improve performance, and deliver a better user experience. Take care! And happy coding as always 🖥️","2026-06-08T12:00:03.683Z","019ea71a-ac51-7489-bbe0-07745fbb62d0","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiajryi395e201bloufp6.png","2026-06-08T08:59:35.000Z","frontend-observability-in-vue-apps-with-opentelemetry","This article discusses the importance of frontend observability in Vue applications, emphasizing how traditional monitoring falls short in diagnosing performance issues. It introduces OpenTelemetry as a solution for collecting telemetry data, providing insights into application behavior and performance. The article also includes a guide on setting up OpenTelemetry in Vue apps to enhance observability.","Frontend Observability in Vue Apps with OpenTelemetry","2026-06-10T14:35:13.766Z","https:\u002F\u002Fdev.to\u002Fjacobandrewsky\u002Ffrontend-observability-in-vue-apps-with-opentelemetry-3fb0","c8c141c41435740358afc38ce5d160217a0beb69c216de4d15879d516b3259e9",[147,148,151,154],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":149,"name":150,"slug":150},"019ea71a-dc95-72b8-a7e3-70f9e2ac3710","opentelemetry",{"color":6,"id":152,"name":153,"slug":153},"019ea71a-dc9d-7607-9cfa-df0f31ab5876","observability",{"color":6,"id":105,"name":106,"slug":106},{"content":156,"createdAt":157,"id":158,"image":159,"isAffiliate":18,"isPublished":19,"publishedAt":160,"slug":161,"sourceId":22,"sourceName":23,"sourceType":24,"summary":162,"title":163,"updatedAt":164,"url":165,"urlHash":166,"tags":167},"Animations can make an application feel faster, smoother, and more polished. However, many developers think animations are only useful for things like: page transitions modals enter\u002Fleave effects But Vue provides another powerful pattern - State-driven animations. Instead of animating when elements are added or removed from the DOM, you animate changes in reactive state. This allows you to create rich interactive experiences while keeping your code declarative and easy to maintain. In this article, we'll explore: What state-driven animations are How they differ from regular Vue transitions What problems they solve How to implement them in Vue Best practices for creating smooth UI interactions Let's dive in. 🤔 What Are State-Driven Animations? Most Vue developers are familiar with the &lt;Transition&gt; component. Example: &lt;Transition&gt; &lt;Modal v-if=\"isOpen\" \u002F&gt; &lt;\u002FTransition&gt; This animates an element when it enters or leaves the DOM. But what if the element already exists and only its state changes? For example: a progress bar grows a card expands a chart updates a panel changes size a value changes position This is where state-driven animations shine. Instead of animating DOM insertion or removal, you animate changes caused by reactive state. 🟢 What Problem Do State-Driven Animations Solve? Without animations, state changes can feel abrupt. Example: &lt;div :style=\"{ width: progress + '%' }\"&gt;&lt;\u002Fdiv&gt; When progress changes: progress.value = 80 The width instantly jumps. This works technically... but it doesn't feel great. 🟢 A Simple Example Let's create an animated progress bar. &lt;script setup lang=\"ts\"&gt; const progress = ref(20) function increase() { progress.value += 20 } &lt;\u002Fscript&gt; &lt;template&gt; &lt;button @click=\"increase\"&gt; Increase Progress &lt;\u002Fbutton&gt; &lt;div class=\"progress-container\"&gt; &lt;div class=\"progress-bar\" :style=\"{ width: `${progress}%` }\" \u002F&gt; &lt;\u002Fdiv&gt; &lt;\u002Ftemplate&gt; CSS: .progress-container { width: 100%; height: 12px; background: #eee; } .progress-bar { height: 100%; background: #42b883; transition: width 0.3s ease; } Now whenever progress changes, the bar animates smoothly. The animation is entirely driven by reactive state. 🟢 Animating Multiple Properties State-driven animations are not limited to width. Example: &lt;div class=\"card\" :style=\"{ transform: expanded ? 'scale(1.1)' : 'scale(1)', opacity: expanded ? 1 : 0.7 }\" \u002F&gt; CSS: .card { transition: transform 0.3s ease, opacity 0.3s ease; } Now changing: expanded.value = true animates scale and opacity at the same time. 🟢 Using Vue Reactivity with Animations One of the biggest advantages is that animations stay connected to Vue's reactivity system. Example: &lt;script setup lang=\"ts\"&gt; const isActive = ref(false) &lt;\u002Fscript&gt; &lt;template&gt; &lt;button @click=\"isActive = !isActive\"&gt; Toggle &lt;\u002Fbutton&gt; &lt;div class=\"box\" :class=\"{ active: isActive }\" \u002F&gt; &lt;\u002Ftemplate&gt; CSS: .box { width: 100px; height: 100px; transition: all 0.4s ease; } .box.active { transform: rotate(180deg); } Vue handles state. CSS handles animation. The result is clean and maintainable. 🧪 Best Practices Keep animations subtle and purposeful Prefer CSS transitions for simple effects Avoid animating expensive properties when possible Use transforms instead of layout-changing properties when appropriate Don't animate everything Keep durations short (typically 200–400ms) Use animations to communicate state changes, not distract users 📖 Learn more If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below: It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉 🧪 Advance skills A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success. Check out Certificates.dev by clicking this link or by clicking the image below: Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more! ✅ Summary State-driven animations are a powerful way to create smooth and engaging user experiences in Vue. While &lt;Transition&gt; is perfect for entering and leaving elements, state-driven animations excel when existing elements need to react smoothly to changing data. Used thoughtfully, they can make your applications feel significantly more responsive and professional. Take care! And happy coding as always 🖥️","2026-06-01T12:00:05.566Z","019e830e-2fa7-74ed-8c74-71fc2c69cb52","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvih3y2fdc8upo7ni9m42.png","2026-06-01T09:54:37.000Z","state-driven-animations-in-vue-create-smooth-ui-transitions-with-reactive-state","This article explores state-driven animations in Vue, highlighting how they enhance UI transitions by animating changes in reactive state rather than just DOM insertion or removal. It provides examples and best practices for implementing these animations to create smoother, more interactive user experiences.","State-Driven Animations in Vue: Create Smooth UI Transitions with Reactive State","2026-06-10T14:35:13.767Z","https:\u002F\u002Fdev.to\u002Fjacobandrewsky\u002Fstate-driven-animations-in-vue-create-smooth-ui-transitions-with-reactive-state-d3i","b6046ff3585c584d9e28b56411b296d962249089895ddbb6902902fabcfdafec",[168,169,172,173,174],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":170,"name":171,"slug":171},"019e830e-5378-722b-929b-a57d67bcf605","animation",{"color":6,"id":111,"name":112,"slug":112},{"color":6,"id":132,"name":133,"slug":133},{"color":6,"id":175,"name":176,"slug":176},"019d6bd8-fba5-743f-8f9f-4e23c0b31581","tutorial",{"content":178,"createdAt":179,"id":180,"image":181,"isAffiliate":18,"isPublished":19,"publishedAt":182,"slug":183,"sourceId":51,"sourceName":52,"sourceType":24,"summary":184,"title":185,"updatedAt":186,"url":187,"urlHash":188,"tags":189},"Claude Code shipped workflows recently, and the docs describe a lot of machinery: deterministic orchestration, parallel and pipeline, journaling and resume, adversarial verify patterns. I wanted to understand it rather than skim the feature list, and the way I learn a tool is to build the smallest real thing with it. So I picked a task with an obvious fan-out shape: “what happened in the Vue and Nuxt ecosystem this week.” Many independent sources to check, then a merge, then a write-up. I wrote a ~130-line workflow that spawns nine agents in parallel, each scouring a different source, collects their findings into one list, ranks them by impact, and writes a digest. It’s a throwaway, but building it taught me how the whole feature fits together. This post is what I learned. A workflow is the newest piece of Claude Code’s orchestration story. In my post on agent teams I traced the progression from subagents to teams. Workflows are the next rung, and they solve a different problem than either: when you want the control flow itself to be deterministic, not decided turn-by-turn by a model. If you want a sense of the ceiling before the toy example, Jarred Sumner credited dynamic workflows and adversarial code review for porting Bun from Zig to Rust in six days: &lt;TLDR items={[ “A workflow is a plain JavaScript script that orchestrates subagents deterministically: you own the loops and fan-out, agents do the thinking”, “The shape that generalizes: fan out → reduce → synthesize”, “agent() runs one subagent (use a schema for validated JSON), parallel() is a barrier, pipeline() streams items through stages with no barrier”, “Default to pipeline(); reach for a parallel() barrier only when a stage needs all prior results at once”, “Compose verify\u002Fjudge\u002Floop-until-dry patterns for confidence, not more agents”, “It’s opt-in and token-hungry, so reach for it when a job needs breadth, verification, or scale a single context can’t hold”, ]} \u002F&gt; Table of Contents Where Workflows Fit Most of the time a single Claude Code session works turn-by-turn: read a file, decide, call a tool, look at the result, decide again. That loop is the right tool for most work. Some jobs don’t fit one head and one context window though: Comprehensive jobs: “review every file in this diff”, “audit all 40 dependencies”. Confidence-critical jobs: “find the bug, then have three independent skeptics try to refute it”. Scale jobs: migrations, sweeps, anything bigger than one context can hold. Subagents and agent teams can attack these, but there’s a subtle difference in who holds the plan. Subagents Agent Teams Workflows What it is A worker Claude spawns Independent Claude sessions A script the runtime executes Who decides what’s next Claude, turn by turn Claude and the teammates The script Where results live Claude’s context Each session’s context Script variables What’s repeatable The worker definition The team setup The orchestration itself Scale A few per turn A handful of sessions Dozens to hundreds of agents With subagents and skills, Claude is the orchestrator. It decides turn by turn what to spawn, and every result lands back in its context window. A workflow moves the plan into code. The script holds the loop, the branching, and the intermediate results, so Claude’s context only ever sees the final answer. That is what lets a workflow scale to hundreds of agents without drowning the conversation. The Core Idea A normal agent decides the control flow as it goes. A workflow inverts that. You write the control flow as plain code, and each individual step is delegated to a fresh subagent. The orchestration is deterministic; only the work inside each agent() call is model-powered. That distinction is the whole point. When you write this: const results = await parallel(files.map((f) =&gt; () =&gt; agent(`Review ${f}`))); You know exactly one agent runs per file, they all run concurrently, and you get an array back. There are no emergent “the model decided to skip three files” surprises. You get determinism in the orchestration and model judgment inside each step. The shape that keeps showing up is fan out → reduce → synthesize: &lt;Mermaid chart={graph LR A[fan out] --&gt; B[agent 1] A --&gt; C[agent 2] A --&gt; D[agent ...] A --&gt; E[agent N] B --&gt; F[reduce: dedupe + rank] C --&gt; F D --&gt; F E --&gt; F F --&gt; G[synthesize: write the result]} \u002F&gt; Swap the sources and prompts and the same skeleton becomes a market scan, a dependency audit, a code review, or a research report. The Example I Built to Learn It Here is the workflow I wrote. I picked the newsletter task because it forces you to use every part of the feature: a wide fan-out, a reduce step, and a synthesis step. Every script starts with a meta block that must be a pure literal, then a body using the orchestration primitives. export const meta = { name: \"vue-newsletter\", description: \"Research Vue\u002FNuxt sources in parallel and synthesize a newsletter\", phases: [ { title: \"Research\", detail: \"one agent per source\" }, { title: \"Curate\", detail: \"dedupe + rank by impact\" }, { title: \"Write\", detail: \"synthesize the newsletter\" }, ], }; 1. Fan out with parallel() Nine sources, nine agents, all at once. Each returns structured JSON validated against a schema, so the model retries on mismatch and I never parse free text: phase(\"Research\"); const raw = await parallel( SOURCES.map((s) =&gt; () =&gt; agent(s.prompt, { label: `research:${s.key}`, phase: \"Research\", schema: ITEM_SCHEMA, \u002F\u002F forces validated structured output agentType: \"general-purpose\", }), ), ); The SOURCES array is just data: one entry per source with a prompt. GitHub core releases, the Nuxt ecosystem, the official blogs, Hacker News, Reddit, dev.to, key people like Evan You and Anthony Fu, and the newsletter\u002Fpodcast circuit. 2. Reduce with plain JavaScript Flattening, deduping, and filtering is just code. No agent needed: const collected = raw.filter(Boolean); \u002F\u002F skipped\u002Ffailed agents become null const flatItems = collected.flatMap((c) =&gt; c.items); log(`Collected ${flatItems.length} items`); 3. Synthesize with sequential agent() calls phase(\"Curate\"); const curated = await agent(curatePrompt, { phase: \"Curate\", schema: CURATED_SCHEMA }); phase(\"Write\"); const newsletter = await agent(writePrompt, { phase: \"Write\" }); return { newsletter, itemCount: flatItems.length, curated }; The run I did while testing pulled together a Nuxt UI release, a Vue Router v5 minor, a Vue core patch, and a Madrid conference recap: seventeen items across nine sources in about three minutes. Good enough to convince me the orchestration worked, which was the whole point of building it. The `schema` option forces a subagent to call a structured-output tool, and validation happens at the tool-call layer so the model retries on mismatch. This is far more reliable than asking an agent to \"please return JSON\" and hoping. Reach for it whenever a downstream stage consumes the result. The Primitives A handful of functions do all the work. agent(prompt, opts?) spawns one subagent. Without options it returns the agent’s final text. The options worth knowing: schema: a JSON Schema. The subagent is forced to return validated structured data. label: the display name in the progress UI. phase: assigns the agent to a progress group. Use it inside parallel() and pipeline() to avoid racing on the global phase() state. model: override the model for this one call. Default is to omit it so the agent inherits your session model. agentType: use a custom subagent type instead of the default workflow agent. isolation: \"worktree\": run the agent in its own git worktree. Only when agents write files in parallel and would otherwise conflict. parallel(thunks) runs tasks concurrently. It is a barrier: it waits for every thunk before returning. A thunk that throws resolves to null rather than rejecting the whole call, so always .filter(Boolean) the results. You can pass a hundred thunks and they’ll all complete, but only a handful run at once: concurrency is capped at roughly your core count, and the excess queue. pipeline(items, ...stages) runs each item through all stages independently, with no barrier between stages. Item A can be in stage 3 while item B is still in stage 1. Each stage callback receives (prevResult, originalItem, index). workflow(nameOrRef, args?) runs another workflow inline as a sub-step and returns whatever it returns. Pass a name to invoke a saved workflow, or { scriptPath } to run a script file. This is composition: a research workflow can call \u002Fdeep-research as one of its stages instead of reimplementing the fan-out. The child shares the parent’s concurrency cap, agent counter, and token budget, and shows up as its own group in \u002Fworkflows. Nesting is one level deep: a workflow() call inside a child throws. \u002F\u002F inside a script: hand a sub-question off to the bundled deep-research workflow const report = await workflow(\"deep-research\", { question: topic }); The rest are small helpers: phase(title) starts a progress group, log(msg) emits a narrator line, args carries the JSON you passed in when launching, and budget exposes the token target so you can scale depth dynamically (it’s null when you launch without a target, so guard any loop-until-budget on budget.total or it runs to the agent cap). `Date.now()`, `Math.random()`, and an argless `new Date()` all throw inside a workflow. Workflows journal every `agent()` call so a run can resume, and non-determinism would invalidate that cache. If you need a timestamp, pass it through `args`. If you need variety across agents, vary the prompt or label by index. pipeline vs parallel: The Decision That Matters This trips people up, so here is the rule I follow. Default to pipeline(). Reach for a parallel() barrier between stages only when a stage needs all prior results at once. Legitimate reasons for a barrier: ✅ Dedupe or merge across the full result set before expensive downstream work. ✅ Early-exit on the total (“0 findings, skip verification entirely”). ✅ A prompt that references “the other findings” for comparison. Not legitimate: ❌ “I need to flatten or filter first.” Do it inside a pipeline stage. ❌ “The stages feel conceptually separate.” Separate is not the same as synchronized. ❌ “It’s cleaner code.” Barrier latency is real wall-clock waste. The smell test: if you wrote parallel → transform → parallel, and that middle transform has no cross-item dependency, you should have used a pipeline. The newsletter example does use a barrier, and correctly: curation has to see every source before it can dedupe and rank across them. Quality Patterns The primitives compose into reusable harnesses. This is the real value over spawning more agents: the structure is what produces confidence. A few I lean on: Adversarial verify: for each finding, spawn N independent skeptics prompted to refute it. Kill it unless a majority survive. Stops plausible-but-wrong findings from shipping. Perspective-diverse verify: give each verifier a distinct lens (correctness, security, performance, does-it-reproduce) instead of N identical ones. Diversity catches failure modes redundancy can’t. Judge panel: generate N attempts from different angles, score with parallel judges, synthesize from the winner while grafting the best of the runners-up. Loop-until-dry: for unknown-size discovery, keep spawning finders until K consecutive rounds surface nothing new. Here is loop-until-dry with a diverse-lens verify, condensed: const seen = new Set(); const confirmed = []; let dry = 0; while (dry &lt; 2) { const found = (await parallel(FINDERS.map((f) =&gt; () =&gt; agent(f.prompt, { phase: \"Find\", schema: BUGS })))).filter(Boolean).flatMap((r) =&gt; r.bugs); const fresh = found.filter((b) =&gt; !seen.has(key(b))); if (!fresh.length) { dry++; continue; } dry = 0; fresh.forEach((b) =&gt; seen.add(key(b))); const judged = await parallel(fresh.map((b) =&gt; () =&gt; parallel([\"correctness\", \"security\", \"repro\"].map((lens) =&gt; () =&gt; agent(`Judge \"${b.desc}\" via the ${lens} lens — real?`, { phase: \"Verify\", schema: VERDICT }))) .then((vs) =&gt; ({ b, real: vs.filter(Boolean).filter((v) =&gt; v.real).length &gt;= 2 })))); confirmed.push(...judged.filter((v) =&gt; v.real).map((v) =&gt; v.b)); } One detail makes or breaks this: dedupe against everything seen, not just confirmed results. Otherwise rejected findings reappear every round and the loop never converges. A Shipped Example: How \u002Fdeep-research Works My newsletter generator is a toy. If you want to see these patterns in a real, bundled workflow, run \u002Fdeep-research. It takes a question and returns a cited report, and under the hood it’s the same fan out → reduce → synthesize skeleton with an adversarial verify pass bolted on. It’s the quality pattern from the section above, running in production. When you launch it the workflow announces its plan and runs in the background while you keep working: It moves through five phases: Scope: one agent decomposes your question into five distinct search angles, so the searches don’t all chase the same wording. Search: five web searches run in parallel, one per angle. This is the fan-out. Fetch: dedupe the URLs across angles, pull the top ~15 sources, and extract individual claims from them. Verify: the interesting part. Each claim gets an adversarial three-vote check, with skeptics trying to refute it. Claims that don’t survive never reach the report. Synthesize: one final agent writes the cited report from the claims that held up. Map that onto the primitives and you can almost see the script: a single agent() for scope, a parallel() fan-out for the five searches, plain JavaScript to dedupe in fetch, a per-claim verify pass (the same parallel() of skeptics from the loop-until-dry example), and a closing agent() to synthesize. The phases show up in \u002Fworkflows as named groups (Scope 1\u002F1, Search 0\u002F5, Fetch, Verify, Synthesize), each with its own agent count, token total, and elapsed time, so you can drill into any single search or verification and read its prompt and result. This is the difference between “ask Claude to research something” and a workflow. A single agent doing web research holds every half-read source in one context and never checks its own claims. \u002Fdeep-research decomposes the search so coverage is wide, keeps the intermediate sources out of your conversation, and runs a verification pass a single turn-by-turn agent would never run against itself. Triggering and Watching a Run Worth saying plainly: from Claude Code’s side, a workflow is a tool. There’s a Workflow tool the same way there’s a Read or Bash tool, and “running a workflow” means Claude calls that tool with a script. The runtime executes the script in the background while your session stays responsive, which is why you can keep chatting while dozens of agents churn away. There are a few ways a workflow gets written and launched: Say “workflow” in your prompt. Include the word and Claude writes a workflow script for the task instead of working through it turn by turn. Run a saved or bundled command. A workflow you saved to the project, or the built-in \u002Fdeep-research covered above. Turn on ultracode. Claude plans a workflow for every substantial task in the session. Run a workflow to audit every API endpoint under src\u002Froutes\u002F for missing auth checks. Spawn one agent per route file, then have a second pass verify each finding before reporting. When a run does what you wanted, you can save it: Claude Code writes the script into .claude\u002Fworkflows\u002F in your repo as a &lt;name&gt;.js file (the appendix below is exactly that file for my newsletter). Because it lives in the repo, it’s version-controlled and anyone who clones it can launch it by name and pass arguments: Run the vue-newsletter workflow with args `{\"weekStart\":\"2026-06-04\",\"weekEnd\":\"2026-06-11\"}` Runs happen in the background, and \u002Fworkflows is how you watch them: it lists every run, including which ones are currently running, and opens a progress view showing each phase with its agent count, token total, and elapsed time. You can drill into a phase, then into a single agent, to read its prompt and result, pause or stop a run, or press s to save a good one’s script as a reusable \u002F&lt;name&gt; command under .claude\u002Fworkflows\u002F. When to Reach for One &lt;Mermaid chart={graph TD A[Does the job need breadth,&lt;br\u002F&gt;verification, or scale?] --&gt;|No| B[Single session&lt;br\u002F&gt;or a subagent] A --&gt;|Yes| C[Do you want the control flow&lt;br\u002F&gt;to be deterministic and repeatable?] C --&gt;|No| D[Agent team] C --&gt;|Yes| E[Write a workflow]} \u002F&gt; Good fit ✅ Decomposing a job so every part is covered in parallel (audits, reviews, sweeps). Anything you want to re-run with the same structure (a weekly competitor scan, a release checklist). Confidence-critical work where a repeatable verify or judge pass beats one model’s first answer. Bad fit ❌ An ordinary task one agent can do turn by turn. Let one agent do it. Work that needs you to weigh in between every stage. A workflow can’t take mid-run input; only agent permission prompts pause it. Anything where the token cost of dozens of agents isn’t justified by breadth or scale. A workflow spawns many agents, so one run can use meaningfully more tokens than doing the same task in conversation, and it counts toward your plan's usage. Every agent uses your session's model unless the script routes a stage elsewhere, so check `\u002Fmodel` before a large run and consider routing cheap stages to a smaller model. Conclusion A workflow is a JavaScript script that orchestrates subagents deterministically. You own the control flow, agents do the thinking, and the plan lives in code so the conversation only sees the final answer. The shape that generalizes is fan out → reduce → synthesize. The newsletter generator I built is a deliberately small instance of it. agent() runs one (use a schema for validated structured output), parallel() is a barrier, pipeline() streams items through stages with no barrier. Default to pipeline. The leverage is the repeatable quality patterns: adversarial verify, diverse lenses, judge panels, loop-until-dry. It is opt-in and token-hungry. Reach for it when a job needs breadth, independent verification, or scale a single context can’t hold. Otherwise let one agent do the work. If you’ve already worked through subagents and skills, workflows are the natural next tool. The fastest way to understand them is the same way I did: pick a small task with a clear fan-out shape and build the throwaway version. Mine was a newsletter generator I won’t run again. The point was never the newsletter; it was seeing how the pieces fit, so that when a job needs breadth or verification, reaching for a workflow is obvious. Appendix: The Full Script Everything above is excerpts. Here is the complete .claude\u002Fworkflows\u002Fvue-newsletter.js in one piece, so you can see how the meta block, the schemas, the source list, and the three phases fit together. It’s plain JavaScript: no imports, no filesystem access, inputs via args, results via return. export const meta = { name: 'vue-newsletter', description: 'Research Vue\u002FNuxt ecosystem sources in parallel for a given week and synthesize a newsletter', whenToUse: 'Generate a weekly Vue\u002FNuxt newsletter. Pass args {weekStart, weekEnd, label} as ISO dates (e.g. {\"weekStart\":\"2026-05-21\",\"weekEnd\":\"2026-05-28\"}). With no args, agents cover the past 7 days from today.', phases: [ { title: 'Research', detail: 'one agent per source — releases, blogs, social, people' }, { title: 'Curate', detail: 'dedupe + rank items by impact' }, { title: 'Write', detail: 'synthesize the final newsletter' }, ], } \u002F\u002F Args are optional. Pass {weekStart, weekEnd, label} as ISO dates to scope a specific week. \u002F\u002F With no args, agents are told to cover \"the past 7 days from today\" (they resolve the date via web search). const hasRange = args &amp;&amp; args.weekStart &amp;&amp; args.weekEnd const weekStart = hasRange ? args.weekStart : null const weekEnd = hasRange ? args.weekEnd : null const label = (args &amp;&amp; args.label) || (hasRange ? `Week of ${weekStart}–${weekEnd}` : 'this week') const window = hasRange ? `between ${weekStart} and ${weekEnd}` : 'within the past 7 days from today' const ITEM_SCHEMA = { type: 'object', additionalProperties: false, properties: { source: { type: 'string' }, items: { type: 'array', items: { type: 'object', additionalProperties: false, properties: { title: { type: 'string' }, url: { type: 'string' }, summary: { type: 'string', description: '1-3 sentence plain summary of what changed \u002F why it matters' }, category: { type: 'string', enum: ['release', 'article', 'tooling', 'discussion', 'tutorial', 'people', 'other'] }, date: { type: 'string', description: 'ISO date if known, else empty' }, impact: { type: 'string', enum: ['high', 'medium', 'low'] }, }, required: ['title', 'url', 'summary', 'category', 'impact'], }, }, }, required: ['source', 'items'], } \u002F\u002F Each source is researched by its own agent in parallel. const SOURCES = [ { key: 'core-releases', prompt: `Find releases\u002Fchangelogs published ${window} for these GitHub repos: vuejs\u002Fcore, vuejs\u002Frouter (vue-router), vuejs\u002Fpinia, vueuse\u002Fvueuse, vitejs\u002Fvite, vitejs\u002Fvitest. For each new release in that window, give the version, the highlights, and the release URL. Skip anything outside the date window.`, }, { key: 'nuxt-releases', prompt: `Find releases\u002Fchangelogs published ${window} for the Nuxt ecosystem on GitHub: nuxt\u002Fnuxt, nuxt\u002Fui, nuxt\u002Fimage, nuxt\u002Fcontent, unjs\u002Fnitro, unjs\u002Fh3. Give version, highlights, and URL for each release in that window only.`, }, { key: 'vue-blog', prompt: `Check the official Vue.js blog (blog.vuejs.org) and Vue.js news for posts published ${window}. Summarize each post with its URL.`, }, { key: 'nuxt-blog', prompt: `Check the official Nuxt blog (nuxt.com\u002Fblog) for posts published ${window}. Summarize each with URL.`, }, { key: 'hackernews', prompt: `Search Hacker News (news.ycombinator.com) for stories about Vue, Nuxt, Vite, or Pinia that were active\u002Fposted ${window}. Include the HN discussion URL and the linked article. Note points\u002Fcomments if visible.`, }, { key: 'reddit', prompt: `Search Reddit r\u002Fvuejs and r\u002FNuxt for notable threads posted ${window} — announcements, releases, popular discussions, showcased projects. Give the reddit thread URL for each.`, }, { key: 'devto', prompt: `Search dev.to for the most useful Vue and Nuxt tagged articles published ${window} (tutorials, deep-dives, tips). Give URLs.`, }, { key: 'people', prompt: `Look for notable updates, posts, or talks ${window} from key Vue\u002FNuxt people: Evan You (@youyuxi \u002F VoidZero), Daniel Roe (Nuxt lead), Anthony Fu (VueUse\u002FVitesse\u002FSlidev), Eduardo San Martin Morote (posva — router\u002Fpinia), Sébastien Chopin (Nuxt\u002FNuxtLabs). Include VoidZero and NuxtLabs company news too. Give URLs.`, }, { key: 'newsletters-podcasts', prompt: `Find Vue\u002FNuxt newsletter issues and podcast episodes published ${window}: Vue.js Newsletter (news.vuejs.org), This Week in Vue, Michael Thiessen's newsletter, DejaVue podcast, Deox\u002FVue Mastery content. Summarize and give URLs.`, }, ] phase('Research') const raw = await parallel( SOURCES.map((s) =&gt; () =&gt; agent( `You are researching the Vue.js \u002F Nuxt ecosystem for a weekly newsletter covering ${label} (${window}).\\n\\n${s.prompt}\\n\\nUse web search and fetch real URLs. Only include items genuinely within the date window. Return real, verifiable URLs — never invent links. If you find nothing in the window, return an empty items array. Set impact based on how much the average Vue developer should care.`, { label: `research:${s.key}`, phase: 'Research', schema: ITEM_SCHEMA, agentType: 'general-purpose' }, ), ), ) const collected = raw.filter(Boolean) const flatItems = collected.flatMap((c) =&gt; (c.items || []).map((it) =&gt; ({ ...it, source: c.source }))) log(`Collected ${flatItems.length} items across ${collected.length} sources`) phase('Curate') const CURATED_SCHEMA = { type: 'object', additionalProperties: false, properties: { highlights: { type: 'array', items: { type: 'string' }, description: '2-4 sentence TLDR bullets of the biggest stories this week' }, items: { type: 'array', items: { type: 'object', additionalProperties: false, properties: { title: { type: 'string' }, url: { type: 'string' }, summary: { type: 'string' }, category: { type: 'string' }, impact: { type: 'string' }, }, required: ['title', 'url', 'summary', 'category', 'impact'], }, }, }, required: ['highlights', 'items'], } const curated = await agent( `Here are raw newsletter candidate items gathered from multiple sources for the Vue\u002FNuxt week of ${label}:\\n\\n${JSON.stringify(flatItems, null, 2)}\\n\\nCurate them:\\n1. Remove duplicates (same release\u002Farticle surfaced by multiple sources — keep the best canonical URL).\\n2. Drop low-quality, off-topic, or spammy entries.\\n3. Rank by impact (high first).\\n4. Write 3-5 punchy \"highlights\" bullets capturing the week's biggest stories.\\nKeep every URL exactly as provided — do not fabricate or alter links.`, { phase: 'Curate', schema: CURATED_SCHEMA }, ) phase('Write') const newsletter = await agent( `Write a polished weekly Vue.js \u002F Nuxt newsletter in Markdown for ${label}.\\n\\nUse this curated data:\\n${JSON.stringify(curated, null, 2)}\\n\\nStructure:\\n- A title with the week range and a one-paragraph intro setting the tone.\\n- \"📌 This Week's Highlights\" — the highlights bullets.\\n- \"🚀 Releases\" — version bumps with what changed (group Vue core + Nuxt + tooling).\\n- \"📝 Articles &amp; Tutorials\".\\n- \"🛠️ Tooling &amp; Ecosystem\".\\n- \"💬 Community &amp; Discussion\".\\n- \"👤 From the Core Team &amp; Community\" — people\u002Fcompany news.\\n- A short friendly sign-off.\\n\\nEvery item must be a markdown link to its real URL. Keep summaries tight and developer-focused. Omit any empty section. Output ONLY the markdown newsletter.`, { phase: 'Write' }, ) return { newsletter, itemCount: flatItems.length, curated }","2026-05-28T20:00:03.329Z","019e702c-2ae7-7659-a2b2-f994793c0dea","https:\u002F\u002Falexop.dev\u002Fposts\u002Fclaude-code-workflows-deterministic-multi-agent-orchestration\u002Findex.png","2026-05-28T00:00:00.000Z","claude-code-workflows-deterministic-multi-agent-orchestration","The article explores Claude Code's new workflows feature, which allows for deterministic orchestration of multi-agent tasks. By building a workflow to aggregate information from the Vue and Nuxt ecosystem, the author demonstrates how workflows can efficiently manage complex tasks through parallel processing and structured control flow. This hands-on approach highlights the practical applications and benefits of using Claude Code's orchestration capabilities.","Claude Code Workflows: Deterministic Multi-Agent Orchestration","2026-05-28T20:00:12.948Z","https:\u002F\u002Falexop.dev\u002Fposts\u002Fclaude-code-workflows-deterministic-orchestration\u002F","b15c964848800d569bbde2a08be74221a0132ff8a55b66063b640550f303d835",[190,191,194,197],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":192,"name":193,"slug":193},"019d6bd8-fad3-70a9-a74d-ab96e3a2f45d","nuxt",{"color":6,"id":195,"name":196,"slug":196},"019e129e-3490-7739-a218-5454a8c15d6e","workflow",{"color":6,"id":198,"name":199,"slug":199},"019e702c-50d7-74eb-8849-8b1cebcf411e","orchestration",{"content":201,"createdAt":202,"id":203,"image":204,"isAffiliate":19,"isPublished":19,"publishedAt":205,"slug":206,"sourceId":77,"sourceName":78,"sourceType":79,"summary":207,"title":208,"updatedAt":209,"url":210,"urlHash":211,"tags":212},"Vite 8 replaced both esbuild and Rollup with Rolldown. Here's what that means for your Vue project in practice.","2026-05-27T12:00:00.450Z","019e694e-4fa0-7469-bfd2-3f6ebe3d830f","https:\u002F\u002Fapi.certificates.dev\u002Fstorage\u002FS7YSA0njipizzfbLK8yznLoWH5klbT1gMA2tMFUO.png","2026-05-27T06:00:00.000Z","rolldown-and-vite-8-what-changed","Vite 8 introduces Rolldown, replacing esbuild and Rollup, which significantly impacts Vue projects. This change aims to enhance performance and streamline the build process for developers using Vite with Vue.","Rolldown and Vite 8: What Changed","2026-05-27T12:00:17.146Z","https:\u002F\u002Fcertificates.dev\u002Fblog\u002Frolldown-and-vite-8-what-changed?friend=MOKKAPPS","59ea330c63cf36f923ea96c371f9b4a320dc0b74e1159db9b6080693f9bb0af8",[213,216,217],{"color":6,"id":214,"name":215,"slug":215},"019d9cf0-c9f8-7411-beed-02265d8271db","vite",{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":105,"name":106,"slug":106},{"content":219,"createdAt":220,"id":221,"image":222,"isAffiliate":18,"isPublished":19,"publishedAt":223,"slug":224,"sourceId":22,"sourceName":23,"sourceType":24,"summary":225,"title":226,"updatedAt":227,"url":228,"urlHash":229,"tags":230},"When building Vue applications, performance usually feels great by default - Vue’s reactivity system is incredibly efficient. But as applications grow larger, you may eventually run into situations where: components re-render too often large lists become expensive UI updates feel sluggish unnecessary computations happen repeatedly This is where memoization becomes useful. And in Vue, one of the easiest ways to optimize rendering is with v-memo. In this article, we’ll explore: What memoization is What problem it solves How v-memo works in Vue Real-world examples Best practices and common mistakes Let’s dive in. 🤔 What Is Memoization? Memoization is an optimization technique where results are cached and reused instead of recalculating them again. Instead of: recomputing re-rendering recalculating You simply use the cached version. 🟢 What Problem Does Memoization Solve? In reactive applications, updates can trigger many re-renders even when most data has not changed for example: Parent component updates Entire list re-renders Hundreds of child components update unnecessarily This can hurt performance, responsiveness, and even battery usage on mobile devices. Without memoization every update causes new rendering work - even for unchanged content. With memoization Vue can skip rendering when dependencies stay the same which reduces DOM operations, Virtual DOM diffing, and in general component work. 🟢 What Is v-memo in Vue? v-memo is a Vue directive that memoizes part of a template. Basic example: &lt;div v-memo=\"[value]\"&gt; {{ expensiveContent }} &lt;\u002Fdiv&gt; Vue will only re-render this block when value changes. Otherwise Vue reuses the previous rendered result. Let’s imagine a large user list. Without v-memo &lt;script setup lang=\"ts\"&gt; const users = ref([ { id: 1, name: 'John' }, { id: 2, name: 'Alice' } ]) const counter = ref(0) &lt;\u002Fscript&gt; &lt;template&gt; &lt;button @click=\"counter++\"&gt; {{ counter }} &lt;\u002Fbutton&gt; &lt;div v-for=\"user in users\" :key=\"user.id\" &gt; {{ user.name }} &lt;\u002Fdiv&gt; &lt;\u002Ftemplate&gt; Every counter update re-renders the whole list even though users never changed. With v-memo we can: &lt;script setup lang=\"ts\"&gt; const users = ref([ { id: 1, name: 'John' }, { id: 2, name: 'Alice' } ]) const counter = ref(0) &lt;\u002Fscript&gt; &lt;template&gt; &lt;button @click=\"counter++\"&gt; {{ counter }} &lt;\u002Fbutton&gt; &lt;div v-for=\"user in users\" :key=\"user.id\" v-memo=\"[user.id]\" &gt; {{ user.name }} &lt;\u002Fdiv&gt; &lt;\u002Ftemplate&gt; And now counter updates still happen but unchanged list items are skipped. This becomes extremely valuable for large lists, dashboards, or tables. 🟢 When NOT to Use It v-memo is not needed everywhere as Vue is already highly optimized. Avoid using it for tiny components, static content, or premature optimization as overusing memoization can: reduce readability make debugging harder introduce stale UI bugs 🧪 Best Practices Use v-memo only for measurable bottlenecks Great for large dynamic lists Keep dependency arrays minimal Avoid premature optimization Profile performance before optimizing Combine with virtual scrolling for huge datasets Prefer stable keys and predictable state updates 📖 Learn more If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below: It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉 🧪 Advance skills A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success. Check out Certificates.dev by clicking this link or by clicking the image below: Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more! ✅ Summary Memoization is a powerful optimization technique that helps avoid unnecessary work. In this article, you learned: What memoization is What problem it solves How Vue’s v-memo works Practical examples for lists and components When to use it — and when not to Take care! And happy coding as always 🖥️","2026-05-18T12:00:05.150Z","019e3af5-2608-71df-9da8-92a67430a7ef","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7b8usfxc7u7injpn8yor.png","2026-05-18T09:21:34.000Z","avoid-unnecessary-re-renders-in-vue-with-v-memo","This article discusses the use of the `v-memo` directive in Vue to optimize rendering by memoizing parts of a template, which helps avoid unnecessary re-renders, especially in large applications. It explains the concept of memoization, its benefits, and provides examples and best practices for effective use in Vue components.","Avoid Unnecessary Re-renders in Vue with `v-memo`","2026-06-10T14:35:13.762Z","https:\u002F\u002Fdev.to\u002Fjacobandrewsky\u002Favoid-unnecessary-re-renders-in-vue-with-v-memo-49bo","15f62df5f7c0b28470c39c37cedc4db4537ead55e3c1365af313657060bac4f8",[231,232,233,236,237],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":105,"name":106,"slug":106},{"color":6,"id":234,"name":235,"slug":235},"019e3af5-4a29-759a-81b0-b6d502b2449e","v-memo",{"color":6,"id":108,"name":109,"slug":109},{"color":6,"id":175,"name":176,"slug":176},{"content":239,"createdAt":240,"id":241,"image":242,"isAffiliate":19,"isPublished":19,"publishedAt":243,"slug":244,"sourceId":245,"sourceName":246,"sourceType":247,"summary":248,"title":249,"updatedAt":250,"url":251,"urlHash":252,"tags":253},"This entry is part 1 of 2 in the series Vue Component DesignGuess what!? We’ve just published a new course all about component design patterns in Vue.js. It’s sure to improve your Vue codebase with battle-tested patterns for scalability and maintainability. We created the course primarily for beginners to help them up their component development skills, but even more learned Vue devs might find a new pattern or two. Go checkout the course now or keep reading for an overview of some of the patterns discussed in the videos. 1. The Branching Component Design Pattern Extract complex conditional rendering into separate components. Instead of multiple v-if branches in one component, create dedicated components for each state. The resulting code is easier to read and maintain over time. &lt;!-- Before --&gt; &lt;template&gt; &lt;div&gt; &lt;div v-if=&quot;loading&quot;&gt;Loading...&lt;\u002Fdiv&gt; &lt;div v-else-if=&quot;error&quot;&gt;Error: {{ error }}&lt;\u002Fdiv&gt; &lt;div v-else&gt; &lt;!-- Complex content --&gt; &lt;\u002Fdiv&gt; &lt;\u002Fdiv&gt; &lt;\u002Ftemplate&gt; &lt;!-- After --&gt; &lt;template&gt; &lt;div&gt; &lt;LoadingState v-if=&quot;loading&quot; \u002F&gt; &lt;ErrorState v-else-if=&quot;error&quot; :message=&quot;error&quot; \u002F&gt; &lt;ContentState v-else :data=&quot;data&quot; \u002F&gt; &lt;\u002Fdiv&gt; &lt;\u002Ftemplate&gt; 2. Slots and Template Props Design Pattern Whenever you have a prop that gets passed directly to the template, that’s a good sign you should be using a slot instead. Why? They serve the same purpose, but the slot allows more flexibility. &lt;!-- AppButton.vue --&gt; &lt;!--Before--&gt; &lt;script setup&gt; defineProps({ label: { type: String, default: &quot;Click Me&quot; } }) &lt;\u002Fscript&gt; &lt;template&gt; &lt;button class=&quot;btn&quot;&gt; &lt;!-- the label makes a beeline to the template and makes no stops along the way--&gt; {{ label }} &lt;\u002Fbutton&gt; &lt;\u002Ftemplate&gt; &lt;!--After--&gt; &lt;template&gt; &lt;button class=&quot;btn&quot;&gt; &lt;!-- ahh, that&#039;s better now we can pass in markup, icons, components whatever--&gt; &lt;slot&gt;&lt;\u002Fslot&gt; &lt;\u002Fbutton&gt; &lt;\u002Ftemplate&gt; Thanks Michael Thiessen for this wonderful pattern and a memorable name to boot! 3. List with ListItem Component Pattern Separate list logic and item display into distinct components. This allows for bundling up list empty state, content, controls, and more into a contained List component. Extracting each item in the list to it’s own ListItem component, makes the List component easy to read, and provides more focus when developing and styling each item. &lt;!-- UsersList.vue --&gt; &lt;script setup&gt; const props = defineProps({ users: { type: Array, required: true } }); const filter = ref(&quot;&quot;) const filteredUsers = computed(()=&gt;{ \u002F\u002F filter logic here }) &lt;\u002Fscript&gt; &lt;template&gt; &lt;div&gt; &lt;!-- List Controls --&gt; &lt;UserFilters v-model=&quot;filter&quot; \u002F&gt; &lt;!-- List Content --&gt; &lt;ul v-if=&quot;filteredUsers.length&quot;&gt; &lt;!-- items extracted to their own component (see below) --&gt; &lt;UserListItem v-for=&quot;user in filteredUsers&quot; :key=&quot;user.id&quot; :user=&quot;user&quot; \u002F&gt; &lt;\u002Ful&gt; &lt;!-- Empty State--&gt; &lt;EmptyState v-else message=&quot;No users found&quot; \u002F&gt; &lt;\u002Fdiv&gt; &lt;\u002Ftemplate&gt; &lt;!-- UserListItem.vue --&gt; &lt;script setup&gt; defineProps({ user: { type: Object, required: true } }) &lt;\u002Fscript&gt; &lt;template&gt; &lt;li class=&quot;user-item&quot;&gt; &lt;img :src=&quot;user.avatar&quot; \u002F&gt; &lt;span&gt;{{ user.name }}&lt;\u002Fspan&gt; &lt;\u002Fli&gt; &lt;\u002Ftemplate&gt; 4. Smart vs Dumb Components Pattern Separate data handling from presentation. Smart components manage logic and data fetching, dumb components simply take in props to handle display. Furthermore, base components provide the fundamental building blocks of your application (such as cards, buttons, etc) and by convention start with v, base, or app. &lt;!-- Smart Component --&gt; &lt;script setup&gt; import { ref } from &#039;vue&#039; const users = ref([]) const loading = ref(true) async function fetchUsers() { users.value = await api.getUsers() loading.value = false } function createUser(){ \u002F\u002F open modal to create user or whatever } &lt;\u002Fscript&gt; &lt;template&gt; &lt;AppButton @click=&quot;createUser&quot; &gt;Create User&lt;\u002FAppButton&gt; &lt;UserList :users=&quot;users&quot; :loading=&quot;loading&quot; \u002F&gt; &lt;\u002Ftemplate&gt; &lt;!-- Dumb Component --&gt; &lt;script setup&gt; defineProps({ users: Array, loading: Boolean }) &lt;\u002Fscript&gt; &lt;template&gt; &lt;div class=&quot;user-list&quot;&gt; &lt;!-- Pure presentation logic --&gt; &lt;\u002Fdiv&gt; &lt;\u002Ftemplate&gt; 5. Form Component Design Pattern v-model on native input fields is awesome! We can do similar with whole forms. This approach accounts for the way users interact with forms: they expect committed data only after click of submit. It also works like a charm with native input validation as the submit event never fires until native validation passes. &lt;script setup&gt; \u002F\u002F support v-model const user = defineModel() \u002F\u002F clone the modelValue to local data \u002F\u002F and provide a fallback user if none provided const form = ref(clone(user) || { name: &#039;&#039;, emaill: &#039;&#039; }) \u002F\u002F only update the modelValue when the form is submitted function handleSubmit() { user.value = clone(form.value); } \u002F\u002F Reset form when prop changes watch(user, () =&gt; form.value = clone(user.value)) const clone = (obj)=&gt; JSON.parse(JSON.stringify(obj)) &lt;\u002Fscript&gt; &lt;template&gt; &lt;form @submit.prevent=&quot;handleSubmit&quot;&gt; &lt;!-- Bind the form inputs to the local data instead of the modelValue --&gt; &lt;input v-model=&quot;form.name&quot; required\u002F&gt; &lt;input v-model=&quot;form.email&quot; \u002F&gt; &lt;!-- Bonus! You can even have dynamic submit button labels based on the modelValue passed in--&gt; &lt;button type=&quot;submit&quot;&gt; {{ user ? &#039;Update&#039; : &#039;Create&#039; }} User &lt;\u002Fbutton&gt; &lt;\u002Fform&gt; &lt;\u002Ftemplate&gt; Looking for More Patterns? We cover all these patterns discussed above in more detail in our course: Vue Component Design. Plus get a preview of some more advanced patterns like the Tightly Coupled Components Pattern, Recursive Components, and Lazy Dynamic Components. Besides our own course, Michael Thiessen’s Clean Components Toolkit is a great resource for further exploring not only component patterns but also patterns for stores, composables, and more.","2026-05-14T12:00:11.684Z","019e265b-cf92-75c7-bb8d-65f5cb9a819d","https:\u002F\u002Fblog.vueschool.io\u002Fwp-content\u002Fuploads\u002F2024\u002F12\u002FVS_5-Component-Design-Patterns-to-Boost-Your-Vue.js-Applications-1.png","2026-05-14T08:00:26.000Z","5-component-design-patterns-to-boost-your-vuejs-applications","019d6bd5-87de-77ef-ac92-98aa56cda920","VueSchool","vueschool","This article introduces a new course focused on component design patterns in Vue.js, aimed at enhancing scalability and maintainability of Vue applications. It outlines several design patterns, such as the Branching Component Design Pattern and the use of slots, which can help developers improve their code structure and readability.","5 Component Design Patterns to Boost Your Vue.js Applications","2026-05-14T12:00:21.296Z","https:\u002F\u002Fblog.vueschool.io\u002Fvuejs-tutorials\u002F5-component-design-patterns-to-boost-your-vue-js-applications\u002F?friend=MOKKAPPS","998659ef4f9a67af7ef263b481fc23eaa61736efd82e77946c3a11812701ff78",[254,255,258,261,264],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":256,"name":257,"slug":257},"019e265b-f569-71d8-a02a-a17ec8180644","component-design",{"color":6,"id":259,"name":260,"slug":260},"019e265b-f571-7677-a537-2f7e96a490bf","scalability",{"color":6,"id":262,"name":263,"slug":263},"019e265b-f579-71cd-84b2-ac385b5225ae","maintainability",{"color":6,"id":175,"name":176,"slug":176},{"content":266,"createdAt":267,"id":268,"image":269,"isAffiliate":18,"isPublished":19,"publishedAt":270,"slug":271,"sourceId":22,"sourceName":23,"sourceType":24,"summary":272,"title":273,"updatedAt":274,"url":275,"urlHash":276,"tags":277},"When developers think about performance optimization, they usually focus on things like: lazy loading caching image optimization bundle size And while those things absolutely matter there’s another area that heavily impacts user experience -&gt; Loading states and layout stability. A badly implemented loading experience can make an app feel slow, jumpy, or frustrating to use. This is strongly connected to an important Core Web Vital metric Cumulative Layout Shift (CLS). In this article, we’ll explore: What CLS is Why loaders are critical for perceived performance How poor loading states hurt UX Practical examples in Vue Best practices for stable layouts Let’s dive in. 🤔 What Is Cumulative Layout Shift (CLS)? CLS measures how much elements unexpectedly move during page loading. Example of bad CLS: Text suddenly jumps down Buttons move while you try to click Images appear late and push content around We’ve all experienced websites like this: 👉 You try to click something… and suddenly the layout shifts. Extremely annoying. Why does this happen? Usually because: content loads asynchronously elements have no reserved space loaders are missing images don’t define dimensions components suddenly appear Why does CLS matter? Because it affects user experience, accessibility, or mobile usability (and obviously Google Core Web Vitals). Even if your app is technically fast poor layout stability can make it feel slow. 👉 Users care more about perceived performance than actual milliseconds. A good loader communicates progress, prevents layout jumping, and makes apps feel responsive A bad or missing loader creates uncertainty. Users start thinking: “Did the app freeze?” “Is something broken?” “Why is everything moving?” 🟢 Implementing proper loaders in Vue Let's take a look at the following example: &lt;script setup lang=\"ts\"&gt; const users = ref([]) const loading = ref(true) onMounted(async () =&gt; { users.value = await fetchUsers() loading.value = false }) &lt;\u002Fscript&gt; &lt;template&gt; &lt;div v-if=\"loading\" class=\"skeleton-list\"&gt; &lt;div v-for=\"n in 5\" :key=\"n\" class=\"skeleton-card\" \u002F&gt; &lt;\u002Fdiv&gt; &lt;UserCard v-else v-for=\"user in users\" :key=\"user.id\" :user=\"user\" \u002F&gt; &lt;\u002Ftemplate&gt; &lt;style scoped&gt; .skeleton-card { height: 120px; border-radius: 12px; margin-bottom: 16px; } &lt;\u002Fstyle&gt; We fetch users, but when the fetch is in progress we display the same hard coded number of loaders\u002Fskeletons. When the users are loaded there is no layout shift as it occupies the same space improving perceived performance and User Experience. If we don't know how many results there will be, we have to assume some number but it is still better than not having skeletons at all :) Many apps still use simple spinners or text\u002Ficon loaders like: &lt;div&gt;Loading...&lt;\u002Fdiv&gt; But modern UX usually prefers Skeleton loaders because they mimic final layout, reduce layout shift, and improve perceived speed. 🧪 Best Practices Prefer skeleton loaders over tiny spinners Reserve space before content loads Keep loading and final layouts similar Always define image dimensions Avoid injecting large content suddenly Test CLS using Lighthouse or Core Web Vitals tools Think about perceived performance — not just raw speed 📖 Learn more If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below: It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉 🧪 Advance skills A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success. Check out Certificates.dev by clicking this link or by clicking the image below: Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more! ✅ Summary Loaders are much more important than most developers realize. In this article, you learned: What Cumulative Layout Shift (CLS) is Why poor loading states hurt UX How skeleton loaders improve perceived performance How to avoid layout jumping in Vue and other frameworks Best practices for stable, responsive interfaces Fast apps are great. But apps that feel smooth and stable are what users truly remember. Take care! And happy coding as always 🖥️","2026-05-11T12:00:12.770Z","019e16e8-bfd2-7191-94bc-00d70b24a540","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbym0bvla6v4jibn66jc3.png","2026-05-11T09:29:43.000Z","why-loaders-matter-for-performance","This article discusses the importance of loaders in enhancing perceived performance and user experience in web applications, particularly focusing on the concept of Cumulative Layout Shift (CLS). It highlights how proper implementation of loaders in Vue can prevent layout shifts and improve user engagement by providing a stable loading experience. The article also offers practical examples and best practices for implementing effective loaders.","Why Loaders Matter for Performance","2026-06-10T14:35:13.764Z","https:\u002F\u002Fdev.to\u002Fjacobandrewsky\u002Fwhy-loaders-matter-for-performance-4b8a","d90fb6c45448cd6496f59658878a5381e26f71ac1b914ec7c7c4c29bf64f2c6e",[278,279,280,283,286],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":105,"name":106,"slug":106},{"color":6,"id":281,"name":282,"slug":282},"019e16e8-dbfa-76d6-bb2d-793aee049186","loading",{"color":6,"id":284,"name":285,"slug":285},"019e16e8-dc00-714d-911a-a5bf39238587","user-experience",{"color":6,"id":42,"name":43,"slug":43},{"content":288,"createdAt":289,"id":290,"image":291,"isAffiliate":19,"isPublished":19,"publishedAt":292,"slug":293,"sourceId":77,"sourceName":78,"sourceType":79,"summary":294,"title":295,"updatedAt":296,"url":297,"urlHash":298,"tags":299},"Using Nuxt vs Not Using Nuxt: A side-by-side comparison of building the same features in plain Vue and Nuxt, so you can see exactly what the framework gives you.","2026-05-06T16:00:00.560Z","019dfe04-7e11-74b9-afab-712f6aaea36a","https:\u002F\u002Fapi.certificates.dev\u002Fstorage\u002FovVwybvutSj93lna8vUfweBOvwB1Yc7UKfb9c15V.png","2026-05-06T06:00:00.000Z","is-nuxt-something-for-me","This article compares building features in plain Vue versus using Nuxt, highlighting the advantages and capabilities that Nuxt offers as a framework. It aims to help readers determine if Nuxt is the right choice for their projects.","Is Nuxt something for “me”?","2026-05-06T16:00:17.061Z","https:\u002F\u002Fcertificates.dev\u002Fblog\u002Fis-nuxt-something-for-me?friend=MOKKAPPS","d6c054e0717f4acd9f0eb26b42e043780f93b554aa376883a550c004f244aff1",[300,301,302,305],{"color":6,"id":192,"name":193,"slug":193},{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":303,"name":304,"slug":304},"019dfe04-bee8-7384-bc58-a712f677807c","comparison",{"color":6,"id":306,"name":307,"slug":307},"019dfe04-beee-7481-b8e7-4034640e840a","frameworks",{"content":309,"createdAt":310,"id":311,"image":312,"isAffiliate":18,"isPublished":19,"publishedAt":313,"slug":314,"sourceId":315,"sourceName":316,"sourceType":317,"summary":318,"title":319,"updatedAt":320,"url":321,"urlHash":322,"tags":323},"KNIME has spent years evolving a large Java-based desktop application, used by 300k users in 60 countries, into a modern web ...","2026-05-05T12:00:07.304Z","019df802-8278-7658-be80-e86a602f62cf","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F2-O08Aw1KeM\u002Fhqdefault.jpg","2026-05-05T10:00:27.000Z","jakob-schröter-helian-rivera---from-desktop-to-web-rebuilding-our-data-science-platform-with-vue-amp","019d9ce0-e8f2-774a-ba57-a61c19469fe1","Vuejs Amsterdam","youtube","KNIME is transitioning its extensive Java-based desktop application into a modern web platform using Vue, aiming to enhance accessibility and user experience for its 300,000 users worldwide. This shift represents a significant evolution in their data science tools, leveraging the capabilities of Vue for a more interactive web experience.","Jakob Schröter, Helian Rivera - From Desktop to Web Rebuilding our Data Science Platform with Vue &amp;","2026-05-05T12:00:17.036Z","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=2-O08Aw1KeM","e79377eef86b6335999a27910ae97e018c8e28360509f8764b7afb54c83ee304",[324,325,328],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":326,"name":327,"slug":327},"019df802-a8b6-74d2-a0cd-b0509cf502fa","web-development",{"color":6,"id":329,"name":330,"slug":330},"019df802-a8bb-775a-b843-93d883c7dfc5","data-science",{"content":332,"createdAt":333,"id":334,"image":335,"isAffiliate":18,"isPublished":19,"publishedAt":336,"slug":337,"sourceId":315,"sourceName":316,"sourceType":317,"summary":338,"title":339,"updatedAt":340,"url":341,"urlHash":342,"tags":343},"The Model Context Protocol (MCP), and, therefore, MCP servers, are being increasingly used to integrate AI capabilities into ...","2026-05-03T12:00:07.340Z","019dedb5-ca95-740b-aa53-523499fbd77f","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fee6EoOpq8s8\u002Fhqdefault.jpg","2026-05-03T10:00:06.000Z","elise-patrikainen---how-to-build-an-mcp-server-for-vue","Elise Patrikainen discusses the integration of AI capabilities into Vue applications through the Model Context Protocol (MCP) and provides insights on building an MCP server specifically for Vue. This article highlights the growing relevance of MCP in enhancing Vue's functionality with AI features.","Elise Patrikainen - How to build an MCP server for Vue?","2026-05-03T12:00:17.253Z","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=ee6EoOpq8s8","bc24e54d8b8c8eecbc59213aaa83bd2de58bf0ffe8c8af7a3677072fb4525846",[344,345,348],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":346,"name":347,"slug":347},"019d6bd8-fb46-77ef-a3b6-bd2d30ab8919","api",{"color":6,"id":39,"name":40,"slug":40},{"content":350,"createdAt":351,"id":352,"image":353,"isAffiliate":18,"isPublished":19,"publishedAt":354,"slug":355,"sourceId":315,"sourceName":316,"sourceType":317,"summary":356,"title":357,"updatedAt":358,"url":359,"urlHash":360,"tags":361},"Even experienced developers fall into common traps when working with Nuxt and Vue. In this talk, we'll explore performance ...","2026-05-02T12:00:07.346Z","019de88f-6ea2-70a9-9b59-ed5b77339c68","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FNZn_YY2wCZI\u002Fhqdefault.jpg","2026-05-02T10:00:06.000Z","julien-huang---stop-making-these-nuxt-amp-vue-mistakes-introducing-nuxthints-10","Julien Huang discusses common mistakes developers make while using Nuxt and Vue, introducing the @nuxt\u002Fhints 1.0 tool to help avoid these pitfalls and improve performance. The talk aims to enhance the development experience by addressing frequent issues faced by both new and seasoned developers.","Julien Huang - Stop making these Nuxt &amp; Vue mistakes: introducing @nuxt\u002Fhints 1.0","2026-05-02T12:00:23.318Z","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=NZn_YY2wCZI","d468b007f85431c35301d8f1481694bdff471425503175fdc5c8ccd2d48bb322",[362,363,364,365],{"color":6,"id":192,"name":193,"slug":193},{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":105,"name":106,"slug":106},{"color":6,"id":175,"name":176,"slug":176},{"content":367,"createdAt":368,"id":369,"image":370,"isAffiliate":18,"isPublished":19,"publishedAt":371,"slug":372,"sourceId":315,"sourceName":316,"sourceType":317,"summary":373,"title":374,"updatedAt":375,"url":376,"urlHash":377,"tags":378},"Tree-shaking is widely regarded as a performance optimization technique in the Vue and Nuxt ecosystem—but have you ever ...","2026-05-01T12:00:08.125Z","019de369-15ab-754a-8e04-da461cb7068b","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FYXG514QueOc\u002Fhqdefault.jpg","2026-05-01T10:00:06.000Z","serko-vincent-ngai---when-tree-shaking-fails-security-risks-in-nuxt-amp-vue","The article discusses the security risks associated with tree shaking in the Vue and Nuxt frameworks, highlighting potential vulnerabilities that can arise when this optimization technique fails. It emphasizes the importance of understanding these risks to maintain secure applications.","SerKo Vincent Ngai - When Tree Shaking Fails: Security Risks in Nuxt &amp; Vue","2026-05-01T12:00:16.190Z","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=YXG514QueOc","305f1c090af38f6fa7ea715fff88cec084c05ba031f23220f80d6639a9a0f86a",[379,380,381,384],{"color":6,"id":192,"name":193,"slug":193},{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":382,"name":383,"slug":383},"019dcdf3-fc84-73aa-a0be-6b7196c5a2e9","security",{"color":6,"id":105,"name":106,"slug":106},{"content":386,"createdAt":387,"id":388,"image":389,"isAffiliate":18,"isPublished":19,"publishedAt":390,"slug":391,"sourceId":315,"sourceName":316,"sourceType":317,"summary":392,"title":393,"updatedAt":394,"url":395,"urlHash":396,"tags":397},null,"2026-04-30T12:00:02.889Z","019dde42-a535-7402-94ba-a1dfc1f9ac89","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002FMMQl0HiNV8w\u002Fhqdefault.jpg","2026-04-30T10:00:06.000Z","reza-bar---reactivity-in-vue-thinking-in-signals","The article discusses the concept of reactivity in Vue.js, focusing on the use of signals as a way to manage state and reactivity in applications. It explores how signals can enhance the reactivity model in Vue, providing a new perspective on state management.","Reza Bar - Reactivity in Vue Thinking in Signals","2026-04-30T12:00:11.580Z","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=MMQl0HiNV8w","14abc936dca2f0684fdef3675153a32f57853fa196ea1fa4363eeedb905571eb",[398,399,400],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":111,"name":112,"slug":112},{"color":6,"id":88,"name":89,"slug":89},{"content":402,"createdAt":403,"id":404,"image":405,"isAffiliate":18,"isPublished":19,"publishedAt":406,"slug":407,"sourceId":315,"sourceName":316,"sourceType":317,"summary":408,"title":409,"updatedAt":410,"url":411,"urlHash":412,"tags":413},"For many developers, learning about security in Vue can sound intimidating or boring. This session is designed to flip that ...","2026-04-29T12:00:01.783Z","019dd91c-44e3-71bc-8fb7-b1a6f1b7e5d0","https:\u002F\u002Fi.ytimg.com\u002Fvi\u002Fy752-F2vWvk\u002Fhqdefault.jpg","2026-04-29T10:00:06.000Z","ramona-schwering-vue-tiful-defense-let39s-draw-security","This article discusses a session aimed at making security in Vue more engaging and accessible for developers. It emphasizes the importance of understanding security practices in Vue applications.","Ramona Schwering   Vue tiful Defense Let&#39;s draw Security","2026-04-29T12:00:12.310Z","https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=y752-F2vWvk","52ac6b29860f72ca87b5c2c480e623dc245f8606ea2b094d4fbd10ce273c96b9",[414,415],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":382,"name":383,"slug":383},{"content":417,"createdAt":418,"id":419,"image":420,"isAffiliate":19,"isPublished":19,"publishedAt":421,"slug":422,"sourceId":77,"sourceName":78,"sourceType":79,"summary":423,"title":424,"updatedAt":425,"url":426,"urlHash":427,"tags":428},"Using Vue plainly or adding Nuxt to it:  side-by-side comparison of building the same features in plain Vue and Nuxt, so you can see exactly what the framework gives you.","2026-04-30T04:18:53.710Z","019ddc9c-727b-76e6-bbe9-2e57c4783354","https:\u002F\u002Fapi.certificates.dev\u002Fstorage\u002FHnWHeIb9HLni5mNy5Zx4DoLdS9NquZGL4xFDyMR4.png","2026-04-29T06:00:00.000Z","plain-vue-or-going-meta","This article provides a side-by-side comparison of building features using plain Vue versus using Nuxt, highlighting the advantages and additional capabilities that Nuxt offers. It aims to help developers decide whether to use Vue alone or to incorporate Nuxt for their projects.","Plain Vue or going Meta?","2026-04-30T04:19:02.039Z","https:\u002F\u002Fcertificates.dev\u002Fblog\u002Fplain-vue-or-going-meta?friend=MOKKAPPS","fc38b56c8a637ec563a6ea40daeaf83218a14d09ff989566709fcabc9fd085c2",[429,430,431],{"color":6,"id":7,"name":8,"slug":8},{"color":6,"id":192,"name":193,"slug":193},{"color":6,"id":175,"name":176,"slug":176},1,20,31,{"tags":436},[437,442,446,449,453,455,458,460,464,468,472,476,481,483,487,491,495,499,501,505,509,513,517,521,525,527,529,533,535,539,543,547,549,553,557,561,563,567,571,575,579,581,585,587,591,595,599,603,607,611,613,617,619,623,627,631,635,639,643,647,651,655,658,662,664,668,670,672,674,677,681,685,689,693,697,701,703,707,711,715,717,721,723,727,731,735,739,743,748,752,754,758,762,766,770,774,776,780,783,787,789,791,793,797,801,803,807,811,813,817,821,824],{"articleCount":438,"color":6,"createdAt":439,"id":440,"name":441,"slug":441,"updatedAt":439},0,"2026-04-30T04:19:02.605Z","019ddc9c-954c-7703-8288-76d562fec577","accelerator",{"articleCount":432,"color":6,"createdAt":443,"id":444,"name":445,"slug":445,"updatedAt":443},"2026-04-08T06:47:43.120Z","019d6bd8-caef-76b9-bacd-363e31e6d2a9","accessibility",{"articleCount":447,"color":6,"createdAt":448,"id":61,"name":62,"slug":62,"updatedAt":448},8,"2026-04-17T20:27:50.780Z",{"articleCount":438,"color":6,"createdAt":450,"id":451,"name":452,"slug":452,"updatedAt":450},"2026-05-05T00:00:19.031Z","019df56f-8257-752e-a918-cdbb07c32b86","ai-agents",{"articleCount":432,"color":6,"createdAt":454,"id":170,"name":171,"slug":171,"updatedAt":454},"2026-06-01T12:00:14.713Z",{"articleCount":456,"color":6,"createdAt":457,"id":346,"name":347,"slug":347,"updatedAt":457},4,"2026-04-08T06:47:55.499Z",{"articleCount":447,"color":6,"createdAt":459,"id":39,"name":40,"slug":40,"updatedAt":459},"2026-04-17T19:35:19.300Z",{"articleCount":438,"color":6,"createdAt":461,"id":462,"name":463,"slug":463,"updatedAt":461},"2026-04-23T12:00:11.615Z","019dba36-435e-765d-bfb2-c5be05362c27","astro",{"articleCount":438,"color":6,"createdAt":465,"id":466,"name":467,"slug":467,"updatedAt":465},"2026-06-01T20:00:15.958Z","019e84c5-cc55-7377-9e5d-77240ea8a880","authentication",{"articleCount":438,"color":6,"createdAt":469,"id":470,"name":471,"slug":471,"updatedAt":469},"2026-05-05T00:00:19.020Z","019df56f-824c-7031-9e34-2f47ad139eb6","automation",{"articleCount":438,"color":6,"createdAt":473,"id":474,"name":475,"slug":475,"updatedAt":473},"2026-06-11T16:00:12.019Z","019eb769-9af2-7471-b482-3f1a404f802e","azure",{"articleCount":477,"color":6,"createdAt":478,"id":479,"name":480,"slug":480,"updatedAt":478},2,"2026-04-17T20:27:50.776Z","019d9d20-e077-71cc-a605-8ac2a1566143","backend",{"articleCount":456,"color":6,"createdAt":482,"id":42,"name":43,"slug":43,"updatedAt":482},"2026-04-08T06:47:56.976Z",{"articleCount":438,"color":6,"createdAt":484,"id":485,"name":486,"slug":486,"updatedAt":484},"2026-06-06T00:00:11.711Z","019e9a3a-e5be-74b3-a01a-92c1f9427a2c","beta",{"articleCount":438,"color":6,"createdAt":488,"id":489,"name":490,"slug":490,"updatedAt":488},"2026-06-10T13:53:29.711Z","019eb1cf-3e6e-70f0-a761-0fb9b61d5675","budgeting",{"articleCount":432,"color":6,"createdAt":492,"id":493,"name":494,"slug":494,"updatedAt":492},"2026-06-16T16:11:31.438Z","019ed133-c4ee-70bb-8e21-7dc86e8adee4","bun",{"articleCount":438,"color":6,"createdAt":496,"id":497,"name":498,"slug":498,"updatedAt":496},"2026-05-19T20:00:14.559Z","019e41d3-1ade-77b0-9e4f-e9b97a6361ca","cdn",{"articleCount":432,"color":6,"createdAt":500,"id":64,"name":65,"slug":65,"updatedAt":500},"2026-06-27T16:00:12.237Z",{"articleCount":432,"color":6,"createdAt":502,"id":503,"name":504,"slug":504,"updatedAt":502},"2026-05-16T18:48:40.777Z","019e321e-8248-75cc-9b69-59c2db6dd846","cli",{"articleCount":438,"color":6,"createdAt":506,"id":507,"name":508,"slug":508,"updatedAt":506},"2026-05-05T00:00:19.014Z","019df56f-8246-747f-be4b-a716863a93ea","cloud-platform",{"articleCount":432,"color":6,"createdAt":510,"id":511,"name":512,"slug":512,"updatedAt":510},"2026-06-16T16:11:31.289Z","019ed133-c458-74d8-a5c9-654f77837e7c","cloudflare",{"articleCount":432,"color":6,"createdAt":514,"id":515,"name":516,"slug":516,"updatedAt":514},"2026-07-27T18:11:45.304Z","019fa4c6-93c3-76ea-baa3-7d5fe541ac5b","cms",{"articleCount":432,"color":6,"createdAt":518,"id":519,"name":520,"slug":520,"updatedAt":518},"2026-04-30T04:19:02.045Z","019ddc9c-931c-743d-a1cb-e4449630fe47","collaboration",{"articleCount":432,"color":6,"createdAt":522,"id":523,"name":524,"slug":524,"updatedAt":522},"2026-06-10T13:53:29.567Z","019eb1cf-3dde-776d-9398-4863764f9ac3","community",{"articleCount":432,"color":6,"createdAt":526,"id":303,"name":304,"slug":304,"updatedAt":526},"2026-05-06T16:00:17.128Z",{"articleCount":432,"color":6,"createdAt":528,"id":256,"name":257,"slug":257,"updatedAt":528},"2026-05-14T12:00:21.354Z",{"articleCount":432,"color":6,"createdAt":530,"id":531,"name":532,"slug":532,"updatedAt":530},"2026-07-18T20:00:18.730Z","019f76d0-bb29-72d6-8d0b-05ffd1d3c8ed","composables",{"articleCount":456,"color":6,"createdAt":534,"id":36,"name":37,"slug":37,"updatedAt":534},"2026-04-08T06:47:42.915Z",{"articleCount":432,"color":6,"createdAt":536,"id":537,"name":538,"slug":538,"updatedAt":536},"2026-06-27T12:00:13.113Z","019f08f3-a538-74ed-82c5-038edce7100a","copilot",{"articleCount":438,"color":6,"createdAt":540,"id":541,"name":542,"slug":542,"updatedAt":540},"2026-04-25T12:00:12.674Z","019dc482-ff81-73ac-9b1c-6ad47f0afde0","data-management",{"articleCount":438,"color":6,"createdAt":544,"id":545,"name":546,"slug":546,"updatedAt":544},"2026-06-04T20:00:17.367Z","019e9438-e5d7-731f-bf47-8dcd86c6655c","data-privacy",{"articleCount":432,"color":6,"createdAt":548,"id":329,"name":330,"slug":330,"updatedAt":548},"2026-05-05T12:00:17.083Z",{"articleCount":438,"color":6,"createdAt":550,"id":551,"name":552,"slug":552,"updatedAt":550},"2026-06-11T16:00:12.028Z","019eb769-9afb-7709-8a67-2a12f5e557c7","deepseek",{"articleCount":432,"color":6,"createdAt":554,"id":555,"name":556,"slug":556,"updatedAt":554},"2026-05-25T08:00:12.834Z","019e5e26-0e21-7366-87c7-0b1334180b0a","dependency-cruiser",{"articleCount":432,"color":6,"createdAt":558,"id":559,"name":560,"slug":560,"updatedAt":558},"2026-04-18T04:30:00.710Z","019d9eda-5005-7329-a463-189572e25635","deployment",{"articleCount":477,"color":6,"createdAt":562,"id":67,"name":68,"slug":68,"updatedAt":562},"2026-04-21T12:00:11.373Z",{"articleCount":432,"color":6,"createdAt":564,"id":565,"name":566,"slug":566,"updatedAt":564},"2026-06-29T08:00:12.101Z","019f1264-9f44-762d-b5fd-837839fdc586","devtools",{"articleCount":438,"color":6,"createdAt":568,"id":569,"name":570,"slug":570,"updatedAt":568},"2026-05-29T20:00:13.197Z","019e7552-ad8c-731f-ad8b-49253ed0e1b9","docker",{"articleCount":432,"color":6,"createdAt":572,"id":573,"name":574,"slug":574,"updatedAt":572},"2026-06-27T12:00:13.081Z","019f08f3-a518-7607-aa8c-782b4f10c2ed","documentation",{"articleCount":432,"color":6,"createdAt":576,"id":577,"name":578,"slug":578,"updatedAt":576},"2026-04-30T04:19:02.055Z","019ddc9c-9327-744f-a2da-31b64c7b6ba4","editor",{"articleCount":432,"color":6,"createdAt":580,"id":33,"name":34,"slug":34,"updatedAt":580},"2026-07-06T12:00:24.261Z",{"articleCount":438,"color":6,"createdAt":582,"id":583,"name":584,"slug":584,"updatedAt":582},"2026-05-02T00:00:23.123Z","019de5fc-7e52-740a-807c-d322c373865b","firewall",{"articleCount":432,"color":6,"createdAt":586,"id":306,"name":307,"slug":307,"updatedAt":586},"2026-05-06T16:00:17.134Z",{"articleCount":438,"color":6,"createdAt":588,"id":589,"name":590,"slug":590,"updatedAt":588},"2026-04-08T06:47:56.883Z","019d6bd9-00b2-7199-8e88-2530ef258032","generics",{"articleCount":432,"color":6,"createdAt":592,"id":593,"name":594,"slug":594,"updatedAt":592},"2026-07-27T18:11:45.390Z","019fa4c6-9419-7657-844e-58ec868ed664","git",{"articleCount":477,"color":6,"createdAt":596,"id":597,"name":598,"slug":598,"updatedAt":596},"2026-07-15T00:00:22.207Z","019f6313-12bf-7151-81f2-c8b43b09d979","html",{"articleCount":438,"color":6,"createdAt":600,"id":601,"name":602,"slug":602,"updatedAt":600},"2026-05-06T00:00:17.012Z","019dfa95-d673-71ef-be4a-8761512ffe5c","infrastructure",{"articleCount":432,"color":6,"createdAt":604,"id":605,"name":606,"slug":606,"updatedAt":604},"2026-06-16T16:11:31.264Z","019ed133-c43f-704f-8c1a-fbc299c8a3e5","javascript",{"articleCount":432,"color":6,"createdAt":608,"id":609,"name":610,"slug":610,"updatedAt":608},"2026-07-13T08:00:18.266Z","019f5a7d-bf5a-76e0-903a-c87435cc3e09","lazy-loading",{"articleCount":432,"color":6,"createdAt":612,"id":281,"name":282,"slug":282,"updatedAt":612},"2026-05-11T12:00:19.963Z",{"articleCount":438,"color":6,"createdAt":614,"id":615,"name":616,"slug":616,"updatedAt":614},"2026-04-25T12:00:12.682Z","019dc482-ff8a-7698-8af5-95db54a26d6b","local-first",{"articleCount":432,"color":6,"createdAt":618,"id":262,"name":263,"slug":263,"updatedAt":618},"2026-05-14T12:00:21.370Z",{"articleCount":432,"color":6,"createdAt":620,"id":621,"name":622,"slug":622,"updatedAt":620},"2026-05-10T16:00:18.613Z","019e129e-34b4-7107-acfb-27f6b8604eb0","management",{"articleCount":432,"color":6,"createdAt":624,"id":625,"name":626,"slug":626,"updatedAt":624},"2026-06-27T12:00:13.065Z","019f08f3-a508-7334-aa03-12b281698ea8","markdown",{"articleCount":432,"color":6,"createdAt":628,"id":629,"name":630,"slug":630,"updatedAt":628},"2026-07-28T12:00:27.878Z","019fa899-02e6-758e-bdcb-8a4a923507df","mcp",{"articleCount":432,"color":6,"createdAt":632,"id":633,"name":634,"slug":634,"updatedAt":632},"2026-06-17T12:00:12.439Z","019ed574-0a96-7485-9c90-522e4be3e092","meta-tags",{"articleCount":438,"color":6,"createdAt":636,"id":637,"name":638,"slug":638,"updatedAt":636},"2026-05-26T08:00:14.598Z","019e634c-7105-7073-bc86-c32fa0a4401b","microfrontends",{"articleCount":438,"color":6,"createdAt":640,"id":641,"name":642,"slug":642,"updatedAt":640},"2026-05-19T16:00:13.516Z","019e40f7-5ccc-729c-92ba-bcc0aad8a16f","microvm",{"articleCount":438,"color":6,"createdAt":644,"id":645,"name":646,"slug":646,"updatedAt":644},"2026-05-05T00:00:19.025Z","019df56f-8250-768c-a659-b9f524ff902c","multi-tenant",{"articleCount":438,"color":6,"createdAt":648,"id":649,"name":650,"slug":650,"updatedAt":648},"2026-05-08T04:00:17.998Z","019e05be-4c4d-759e-a51e-8ac760f82f6d","nextjs",{"articleCount":432,"color":6,"createdAt":652,"id":653,"name":654,"slug":654,"updatedAt":652},"2026-04-17T19:35:19.293Z","019d9cf0-c9fc-76a0-8c4e-b818a89c3774","nitro",{"articleCount":656,"color":6,"createdAt":657,"id":192,"name":193,"slug":193,"updatedAt":657},27,"2026-04-08T06:47:55.381Z",{"articleCount":432,"color":6,"createdAt":659,"id":660,"name":661,"slug":661,"updatedAt":659},"2026-04-30T04:19:02.038Z","019ddc9c-9315-735e-a7e8-8424790e8859","nuxt-ui",{"articleCount":432,"color":6,"createdAt":663,"id":152,"name":153,"slug":153,"updatedAt":663},"2026-06-08T12:00:16.030Z",{"articleCount":438,"color":6,"createdAt":665,"id":666,"name":667,"slug":667,"updatedAt":665},"2026-05-04T20:00:20.503Z","019df493-ce17-76ed-bd80-2a3914e0f409","open-source",{"articleCount":432,"color":6,"createdAt":669,"id":149,"name":150,"slug":150,"updatedAt":669},"2026-06-08T12:00:16.022Z",{"articleCount":456,"color":6,"createdAt":671,"id":108,"name":109,"slug":109,"updatedAt":671},"2026-05-18T12:00:14.389Z",{"articleCount":432,"color":6,"createdAt":673,"id":198,"name":199,"slug":199,"updatedAt":673},"2026-05-28T20:00:13.016Z",{"articleCount":675,"color":6,"createdAt":676,"id":105,"name":106,"slug":106,"updatedAt":676},16,"2026-04-08T06:47:42.920Z",{"articleCount":432,"color":6,"createdAt":678,"id":679,"name":680,"slug":680,"updatedAt":678},"2026-06-10T13:53:29.575Z","019eb1cf-3de7-7326-87d9-c55ad1c0fa39","personalization",{"articleCount":432,"color":6,"createdAt":682,"id":683,"name":684,"slug":684,"updatedAt":682},"2026-04-17T19:35:19.263Z","019d9cf0-c9de-70b2-9057-76d771c3379e","pinia",{"articleCount":438,"color":6,"createdAt":686,"id":687,"name":688,"slug":688,"updatedAt":686},"2026-05-02T00:00:23.112Z","019de5fc-7e47-7075-8aeb-9e90f7689f57","postgres",{"articleCount":438,"color":6,"createdAt":690,"id":691,"name":692,"slug":692,"updatedAt":690},"2026-05-19T20:00:14.575Z","019e41d3-1aee-70c8-a07c-cec870115d14","pricing",{"articleCount":432,"color":6,"createdAt":694,"id":695,"name":696,"slug":696,"updatedAt":694},"2026-05-10T16:00:18.603Z","019e129e-34aa-723b-a568-45737915c7bf","qa",{"articleCount":432,"color":6,"createdAt":698,"id":699,"name":700,"slug":700,"updatedAt":698},"2026-05-08T04:00:18.013Z","019e05be-4c5c-75ad-8df5-602b3db57983","react",{"articleCount":456,"color":6,"createdAt":702,"id":111,"name":112,"slug":112,"updatedAt":702},"2026-04-20T12:00:11.653Z",{"articleCount":456,"color":6,"createdAt":704,"id":705,"name":706,"slug":706,"updatedAt":704},"2026-04-17T20:27:50.585Z","019d9d20-dfb9-7041-9973-39c545b33a2d","release",{"articleCount":438,"color":6,"createdAt":708,"id":709,"name":710,"slug":710,"updatedAt":708},"2026-05-26T08:00:14.619Z","019e634c-711a-728f-9b63-20f2c8b37ccb","routing",{"articleCount":438,"color":6,"createdAt":712,"id":713,"name":714,"slug":714,"updatedAt":712},"2026-05-19T16:00:13.509Z","019e40f7-5cc4-72e1-8f8b-692dd29fc716","sandbox",{"articleCount":432,"color":6,"createdAt":716,"id":259,"name":260,"slug":260,"updatedAt":716},"2026-05-14T12:00:21.362Z",{"articleCount":438,"color":6,"createdAt":718,"id":719,"name":720,"slug":720,"updatedAt":718},"2026-05-04T20:00:20.521Z","019df493-ce28-75e9-93d5-13251407a27b","scanning",{"articleCount":456,"color":6,"createdAt":722,"id":382,"name":383,"slug":383,"updatedAt":722},"2026-04-27T08:00:12.420Z",{"articleCount":432,"color":6,"createdAt":724,"id":725,"name":726,"slug":726,"updatedAt":724},"2026-06-17T12:00:12.428Z","019ed574-0a8b-7566-976f-8c281c820ed0","seo",{"articleCount":432,"color":6,"createdAt":728,"id":729,"name":730,"slug":730,"updatedAt":728},"2026-06-17T12:00:12.433Z","019ed574-0a91-74d8-b806-56681bb4b477","sitemap",{"articleCount":432,"color":6,"createdAt":732,"id":733,"name":734,"slug":734,"updatedAt":732},"2026-07-18T16:00:27.576Z","019f75f5-23b8-72eb-a2bf-79dd1fed3863","software-development",{"articleCount":432,"color":6,"createdAt":736,"id":737,"name":738,"slug":738,"updatedAt":736},"2026-04-17T19:35:19.297Z","019d9cf0-ca00-749d-9101-1c63bf62e215","spas",{"articleCount":477,"color":6,"createdAt":740,"id":741,"name":742,"slug":742,"updatedAt":740},"2026-06-03T16:00:12.620Z","019e8e36-bd4b-740d-b23a-81858b24025b","ssg",{"articleCount":744,"color":6,"createdAt":745,"id":746,"name":747,"slug":747,"updatedAt":745},9,"2026-04-08T06:47:43.020Z","019d6bd8-ca89-735e-a52a-ee53a80a77a9","ssr",{"articleCount":438,"color":6,"createdAt":749,"id":750,"name":751,"slug":751,"updatedAt":749},"2026-04-30T04:19:02.613Z","019ddc9c-9555-7544-a3e3-0605d2c1ea82","startup",{"articleCount":456,"color":6,"createdAt":753,"id":88,"name":89,"slug":89,"updatedAt":753},"2026-04-18T12:00:12.027Z",{"articleCount":438,"color":6,"createdAt":755,"id":756,"name":757,"slug":757,"updatedAt":755},"2026-06-06T00:00:11.717Z","019e9a3a-e5c5-76d3-86e4-576c151a87b3","storage",{"articleCount":432,"color":6,"createdAt":759,"id":760,"name":761,"slug":761,"updatedAt":759},"2026-06-17T12:00:12.446Z","019ed574-0a9e-7712-8bc5-a0102787fe48","structured-data",{"articleCount":432,"color":6,"createdAt":763,"id":764,"name":765,"slug":765,"updatedAt":763},"2026-05-10T16:00:18.597Z","019e129e-34a4-771a-844d-09a7edefcd64","tdd",{"articleCount":438,"color":6,"createdAt":767,"id":768,"name":769,"slug":769,"updatedAt":767},"2026-06-04T20:00:17.351Z","019e9438-e5c6-7681-8704-897c7b499eb4","terms-of-service",{"articleCount":477,"color":6,"createdAt":771,"id":772,"name":773,"slug":773,"updatedAt":771},"2026-04-09T06:11:45.799Z","019d70de-3c07-76bf-9688-9619e1b0d427","testing",{"articleCount":432,"color":6,"createdAt":775,"id":129,"name":130,"slug":130,"updatedAt":775},"2026-06-16T16:11:31.088Z",{"articleCount":438,"color":6,"createdAt":777,"id":778,"name":779,"slug":779,"updatedAt":777},"2026-05-02T00:00:23.130Z","019de5fc-7e59-7426-8d46-e79e4bcf0d56","tls",{"articleCount":781,"color":6,"createdAt":782,"id":175,"name":176,"slug":176,"updatedAt":782},10,"2026-04-08T06:47:55.591Z",{"articleCount":456,"color":6,"createdAt":784,"id":785,"name":786,"slug":786,"updatedAt":784},"2026-04-08T06:47:56.778Z","019d6bd9-0049-72ba-8cfa-139b1c1b249d","typescript",{"articleCount":788,"color":6,"createdAt":745,"id":132,"name":133,"slug":133,"updatedAt":745},5,{"articleCount":432,"color":6,"createdAt":790,"id":284,"name":285,"slug":285,"updatedAt":790},"2026-05-11T12:00:19.969Z",{"articleCount":432,"color":6,"createdAt":792,"id":234,"name":235,"slug":235,"updatedAt":792},"2026-05-18T12:00:14.379Z",{"articleCount":438,"color":6,"createdAt":794,"id":795,"name":796,"slug":796,"updatedAt":794},"2026-04-30T04:19:02.228Z","019ddc9c-93d3-763e-ad3c-d3ad78642de7","vercel",{"articleCount":432,"color":6,"createdAt":798,"id":799,"name":800,"slug":800,"updatedAt":798},"2026-07-13T08:00:18.274Z","019f5a7d-bf61-746b-a44b-5c0a16ff57d3","video",{"articleCount":456,"color":6,"createdAt":802,"id":214,"name":215,"slug":215,"updatedAt":802},"2026-04-17T19:35:19.289Z",{"articleCount":432,"color":6,"createdAt":804,"id":805,"name":806,"slug":806,"updatedAt":804},"2026-04-25T18:08:02.132Z","019dc5d3-c054-70e2-bca4-08e2a2b9a096","vitest",{"articleCount":432,"color":6,"createdAt":808,"id":809,"name":810,"slug":810,"updatedAt":808},"2026-06-27T12:00:13.107Z","019f08f3-a532-7049-a02c-c17a4fd99306","vscode",{"articleCount":5,"color":6,"createdAt":812,"id":7,"name":8,"slug":8,"updatedAt":812},"2026-04-08T06:47:42.793Z",{"articleCount":432,"color":6,"createdAt":814,"id":815,"name":816,"slug":816,"updatedAt":814},"2026-04-18T12:00:12.007Z","019da076-78e6-76bd-b0d4-4e0597d36378","vue-router",{"articleCount":438,"color":6,"createdAt":818,"id":819,"name":820,"slug":820,"updatedAt":818},"2026-05-04T20:00:20.510Z","019df493-ce1d-7039-811a-ed57bf081d26","vulnerability",{"articleCount":822,"color":6,"createdAt":823,"id":326,"name":327,"slug":327,"updatedAt":823},3,"2026-05-05T12:00:17.078Z",{"articleCount":822,"color":6,"createdAt":825,"id":195,"name":196,"slug":196,"updatedAt":825},"2026-05-10T16:00:18.576Z"]