The New Default. Your hub for building smart, fast, and sustainable AI software

See now
Thumbnail for interview with Eduardo.

State, Routing, and the Future of Vue. Eduardo San Martin Morote, Creator of Pinia

Jakub Andrzejewski
|   Mar 31, 2026

If you've ever used Vue Router or Pinia, you've used Eduardo San Martin Morote's work even if you didn't know his name. As a Vue.js core team member, Eduardo is the person behind two of the most essential pieces of the Vue ecosystem, and he's been shaping how developers build Vue apps for years.

In this episode of MonteTalks, Jakub Andrzejewski sat down with Eduardo to chat about his journey from AngularJS side projects to the Vue core team, the philosophy behind Pinia (and why it's named after a pineapple), the surprisingly tricky world of maintaining a router used by millions of apps, and where Vue is headed next, including how AI is changing the way we write and ship code.

Whether you're deep in the Vue ecosystem or just curious about what goes into building and maintaining the tools we all rely on, there's a lot to take away here.

Read the transcript below, or watch the full podcast on YouTube: https://www.youtube.com/watch?v=ng7JSla1Vaw

Introduction

Jakub Andrzejewski: Welcome to another episode of MonteTalks! Today we will be talking a lot about routing, a lot about state management, and overall best practices for building Vue applications. Your host today is me, Jakub, a Senior Fullstack Developer and Advocate from Monterail. And joining me today we have a special guest, Eduardo. Eduardo, if you could tell a bit about yourself to our audience.

Eduardo: So my name is Eduardo, full name San Martin Morote. I go as Posva on GitHub, and I'm a member of the Vue core team. I work mostly on the router and Pinia, which are the projects I have authored in the past. Not the only ones, but the ones that take most of my time and that I'm very committed to maintain.

Eduardo's journey as developer, from Angular.js to Vue.js

Sure. So tell me, how did you end up working on, contributing to, and maintaining things within Vue? Why Vue, to be more specific?

In the time of AngularJS becoming very popular and people realizing that it had its limitations, Vue was one of the libraries that was out there, and I immediately had a click when working with Vue. That was Vue 0.12 that had just come out at the time. It was pre-version one — almost version one, very similar. And I remember that I was 22 at the time, I think 22 or 23, and I was building side projects in the evenings. AngularJS was the library I was using at work, and I could feel some limitations or things that were bothering me. So in my side projects, I was simply exploring other libraries out there. I came across Vue, and as I started building stuff, I felt very comfortable very quickly. Every time I wanted to add something new, it just felt natural — or rather, I had an intuition of how to do it, and then I would check the documentation and it would be that way. So that's what made me stick.

Then I started trying to organize the Vue meetups. I started to push using Vue at the company as well, which we ended up doing for a few projects. And then one thing led to another — I managed to get more active in the discussions. At the time it was issues, but people would ask questions, so it required a lot of triaging. I did a lot of triaging on Vue 1, Vue 2. I think you can search that on GitHub — you will see that I'm the person with the most comments.

Or maybe the bots now have more. But if you remove the bots, I should be first. And yeah, one thing led to another. Evan created a core team, asked for people to join. I applied — it was like a form, I think, or maybe I don't remember exactly. I think it was a form. I applied, and then I found myself in a Slack channel the next day or two days after, with a bunch of people. That was 2017, I think. Maybe 2017.

Throwback to how Pinia and Vue Router became ecosystem pillars

Probably 2017. Sounds amazing. In some way, from zero to hero, right? You started just building with it and then you realized that you can help the community, help it grow, help the project grow. And that's what I wanted to also ask about — the projects you mentioned, right? Pinia and Vue Router. So when you were first building those things, did you ever think that they would become such core parts of the Vue framework, of the Vue ecosystem? Or were they more like side projects that maybe would be used by someone, but you weren't sure?

Yeah, with Pinia I wasn't sure at all. It was more of a scratching-my-own-itch kind of thing. TypeScript support with Vuex was really bad, because Vuex was created before TypeScript was really popular — and Vue as well. So a lot of the difficulties in typing Vuex are intrinsic to its syntax and API. My idea was to create something that could benefit from type inference in TypeScript, which is the most powerful feature it has, I think. So that was just my own project and it was very small at the beginning. I remember that VitePress was one of the first few projects using it, right at the very beginning.

Vue Router, on the other hand, was a bit different, because when I started writing Vue Router 4, which is for Vue 3, I was already maintaining Vue Router 3 for a long time. My goal was — I had a very good knowledge about how the codebase worked, all the difficulties, what could change, what had to change, all the things that made people confused using the router. And I know that nowadays there are still a lot of things that confuse people in routing because it's a complicated topic, but it improved compared to before.

So I was already kind of maintaining Vue Router 3. I was responsible for the project, so I knew more or less — or at least I had the hope, right? That was my goal: I was creating something to become the next official version. It was meant to be the official version, so it was more in the plans, more as a goal, part of the idea.

With Pinia, I was really free to do whatever I wanted. It didn't matter if the API was completely different. I could come up with some crazy ideas. If I hit a wall, it didn't matter.

Facing the complexity and generics of TypeScript

Sounds great. I remember one of your talks. I think it was at Vue.js DE, but not the recent one in Bonn — it was the one in Berlin a few years ago. You had a talk about the TypeScript hell of routing, I think.

Oh yeah, something similar. "Stop writing your own routes," I think.

Yeah, exactly! And it was amazing when you were showing those spaghetti types. It was a nightmare, I suppose, to maintain. [laughter]

Yeah, it's okay as long as you don't have to touch them two weeks later. It's types that — I think nowadays you can just ask the LLM to write them for you, because the syntax is so heavy. It's only ternaries. Doing logic with ternaries is a bit difficult to read, because loops and conditions have to be done that way. You have a few tricks. I name a lot of variables with very verbose names, so it ends up having long, long names. But it is easier to handle it that way than having short names for the type params when you have generics. But otherwise, yeah, this is unmaintainable. And some of those types never made it. Others, less complicated, made it to the codebase, because if you really want a really good developer-facing experience in libraries, you need to face these difficult choices using TypeScript.

Yeah, I completely agree. From the maintaining perspective, in my case it's obviously on a much smaller scale, because the Nuxt modules that I maintain are much smaller, much less complicated — more focused on solving specific, smaller issues. But still, if you get people to join you as contributors, community members who are reporting issues, trying to figure out how to do certain things, helping you improve the documentation, or in general how to improve the module or the package by adding new features — the amount of things you have to learn and how to think about the project you created grows so much. Because there are so many people, so many ideas, and you have to become some sort of project manager, trying to manage how the project goes, which are the priorities. It's really complex stuff that we as developers who use the tools usually don't even think about. We just think that this happens out of the box, right?

Yeah. And you see the results. I think that's how it's meant to be. You don't want to be bothered with all the details of why things went one specific way. So most of the time you don't need to know the "why" of some of the decision choices.

Agreed. And at this point, when we mentioned the TypeScript generics and the ternary types, I remember a video I watched some time ago about the guy who created Doom the game in TypeScript. And how he was showcasing the whole process of building it — from Michigan TS, right? I think so. I think now it's met in person. Really cool — the whole process of building it, the problems he needed to overcome, like the limitations of the compiler, memory size. He needed to overcome so many issues along the way to make it work. And I think at the end the compilation took around 15 hours or something like that. It's so crazy, you know, waiting 15 hours to see if you haven't made a typo. [laughter]

Lessons learned from building Vuex and the philosophy behind Pinia

You mentioned, for example, that Vuex didn't have good TypeScript support. So when building Pinia in the first place, what were the lessons that you learned from Vuex? The things that Vuex, for example, didn't do that well, so that you could make them better in Pinia?

I think most of the things were connected to TypeScript in a way. Dynamic module registration is one of the things that was pretty much impossible to have automatically inferred, because of the way it works — the way you access the store is global, and the way you registered stores was also in a way global. So I wanted to move away from that and go closer to function-based calling.

And with function-based calling, in the worst case scenario, you can have a forced type where in the library you basically write a fake type. You just do as any as Something — or I mean as unknown as Something — and you force the type, because you know it's going to be that type and you don't have to handle all the complicated things. This works for injections, for example, which also go through a global channel and cannot be type-safe purely speaking, but we force them as type-safe because that's easier.

This is one of the reasons the modules, or the way stores are created in Pinia, are independent. There is no one root store per se — you have a root state where everything is connected, but I think even that I could have not had. It was just easier to handle. It was more of an implementation detail in the end, because then you serialize the state and you just have one variable to serialize. But maybe there are versions where you don't do that and it's even better.

So for me, the way things were registered and disconnected really made me realize that that way of handling things was really nice in JavaScript because it was powerful and you could easily extend things. I think this is one of the big things in JavaScript that you could see also with libraries like jQuery, for example. But if you wanted to have TypeScript, it involved hacks — in the worst case, hacks. In most case scenarios, it was just not possible to type.

I think that's the biggest lesson for me. It really stayed as a thing I think about sometimes when I'm implementing APIs. The way I shape these APIs is to try to minimize the amount of global registrations and the decoupling that can happen, because I know that in those scenarios I will have to hardcode some of the types somewhere else if I want to have type safety — which nowadays is a given.

The inspiration behind the name and logo of Pinia

I see. So maybe you can also answer one question. You've probably answered it quite a few times already, but maybe for our audience: what was the inspiration for both the name and the icon of Pinia?

The icon — okay. So first the name, because it makes more sense. The name is "pineapple" in Spanish, but not exactly, because you have a character called eñe, which is just the N with a little wave on the top. Instead of pronouncing the word as "P-I-N-A" — so that would be "pina" if you pronounce it like a regular N — but because it's an eñe, it's "piña." So it's a different sound.

That's not available on npm, so you have to use a regular character. I just chose a name that was available and that was very close to the pronunciation, which is with an I: "Pinia." Because in English it sounds very close to "piña."

The reason I chose "piña" is for two reasons. The inspiration comes from a Spanish expression that says something like "we are a pineapple," and this means "we are a group" — we are together, as multiple people. Not something romantic or anything like that, more like a team.

But also because the pineapple itself — and I think this metaphor is really beautiful — is a multiple fruit. It's a multi-fruit plant. You have multiple flowers that give multiple fruits, and as they grow, they fuse into one single big fruit, which is the pineapple that we have in the end. And I think this matches very well the image of stores that are all created independently but are connected to the same state, so they become one in the end. I thought that was a nice metaphor.

Yeah, for sure. I think I heard part of the story somewhere, but hearing it now is even better. And yeah, most of the time people think it's just because you like the fruit or something.

Which I do — I like all fruit. So...

Diving into Pinia Colada beginnings and goal

And there is an addition to it — Pinia Colada, which was also released. Can you share a bit about that?

Yeah. And also the Pinia logo — I paid a designer for it. I contacted her on Twitter. She was doing designs that had a vibe that I liked. It was really about the vibe, the mood that the character has. I asked her to create something, we had a few iterations, and that was it. I think I've done iterations on it myself — like closing the eyes and moving things — but that's it.

And then Pinia Colada is another library. I started building that two years ago, or one and a half maybe. It's part of my Mastering Pinia course in a way, where we build a more simplified, barebones version of it. My goal was to distill in one library all the things I've learned about state management and make it very small and extensible for Vue — really adapted for Vue and the Vue ecosystem.

So it's very light. It's less than three kilobytes gzipped and minified if you only use the queries. And it's about three kilobytes gzipped and minified if you have both mutations and queries, which is very, very small. Pinia itself is about one and a half kilobytes gzipped and minified.

And the name is obviously the cocktail. I don't have a deep metaphor — I could come up with one if I wanted, like "you just have to chill about your state" or anything. I often use this. But it's just that the name is so easily recognizable. It's pop culture — because of "If You Like Piña Coladas" and the song, and with the Marvel movies, it became a lot more visible. So I thought it was a good reference that would click immediately for anybody, and people would just smile when they see it.

The logo, I designed that myself when I was at the hospital with my daughter. She was six months old and having bronchitis, so it wasn't really a good time, but she just needed to rest. So I had a lot of time at the hospital with my computer. I opened Figma and just started working on it.

The biggest challenges in maintaining a router used by millions of apps

That's a story that I'm not sure you've told anywhere yet. If not, we are unique! So if we can now move into routing, which I'm also really interested in. Routing, or in general, maintaining libraries such as Vue Router, which is used in so many different applications, is probably a really difficult task, right? Because there are so many use cases and edge cases that you need to somehow be able to cover — like the classic Vue SPA, Nuxt with server-side rendering, hybrid rendering in general, probably even some different scenarios like static site generators. So what, in your opinion, is the biggest challenge of maintaining such a library?

I think the challenges change over time and they will probably keep changing. In the past, it was definitely browser compatibility and having to check all the inconsistencies, because we were supporting a lot of browsers. This included Internet Explorer 11, but also older versions of Firefox, Chrome, and Safari.

Nowadays this is no longer an issue, because now we have browsers that auto-update. On Can I Use, you can see that for the features we depend on, 95% of users are using a browser that is consistent and supports modern features — a behavior that feels standard. Because that was the difficult part at the beginning: a lot of things felt like there was no agreement between the browsers on how it should work.

Nowadays, especially with the Navigation API, which is entering every browser — Safari still doesn't support the pre-commit handler, which is just a feature that allows you to hook into the navigation before the URL changes. For an SPA, this is critical because you don't want to change the URL until you are sure that you're going to display the new page at the same time. If you have any relative resource that uses a path that is relative, the URL change will affect that relative resource location. Small detail, but I'm pretty confident they will ship it soon.

I think that because it was included in Interop 2025, they wanted to at least ship most of it to kind of mark it as shipped. But I would argue it's not shipped until the pre-commit handler is shipped as well.

Anyway, this API is consistent, it's standard, it has the behavior described in the spec, and this is what makes the API usable — you don't have to worry about every single browser implementing it the same way. You don't worry about typeof something being different in different browsers.

So that's changing for sure. And nowadays, what makes it more difficult is agreeing on good and bad practices, and spending time adapting to the new standards — especially finding ways to use these new standards in a way that more applications can benefit from.

You don't want to — I know this is a little abstract — but you want to make easy patterns that really empower good user experience. And on the opposite side, you don't want to spend bundle budget making your library big to empower patterns that are not that great.

One example I can give is modals. In Vue Router, you can have modals that change the URL, and if you reload the page, you stay with the modal. But if you share the page, you're going to end up on a different page. I think Twitter did this at some point — they don't do it anymore. I think Instagram may have done it. Personally, I think this is not really a good pattern. It's not that useful. You just change the URL if you need to. You can add a query parameter if you want.

So it has been possible for four or five years in Vue Router, but it's not really well documented. It's shown in an example somewhere, and every year or so someone opens an issue or says "hey, this new router is doing it and we cannot do it in Vue Router." And I have to say, "yes, you can do it, here is an example," but I don't have good documentation to actually showcase it.

This is one of those examples where you don't want to put too much effort. This can be bundle size, API surface — you don't want to make APIs that are very specific to features that are only going to be used in very specific scenarios. But you still want to let it be possible. You want to build APIs that are low-level enough to be usable for complex use cases, but you still want to find a middle ground where you expose an API surface that covers most of the use cases.

With the new APIs, this is a challenge because you need to rethink this API surface. What things can go away? What things can you add? What things can be changed? You have to think about what a new API offers that wasn't possible before. And I think for the Navigation API specifically, I would imagine that most people would migrate away from the History API once it becomes baseline — which means stable in every browser that has been out for two years, if I'm not mistaken.

Anyway, a bit long, but I think this is the difficult part nowadays: here are the new APIs, we haven't used them too much yet. How do we figure out what API surface makes sense? What do we change in the existing APIs? What new patterns might emerge? And what new patterns do we want to promote?

Keeping the balance between adding new things vs. long-term stability of the package

Sure. And on top of that, I'm really interested in learning from you, because you mentioned new APIs, probably some kind of innovation to the existing library. How do you balance adding new things — especially when some of them can still be experimental — with the long-term stability of the package that you need to maintain? Because there are multiple versions, multiple frameworks. You need the package to be stable, but you also want to push new features and new APIs. How do you maintain this?

So in the past, I would be very cautious about any new API that I wanted to add. I basically stayed very lean when it came to new things in both Pinia and Vue Router.

One exception is anything that can be tree-shaken. If a function can be fully tree-shaken, then most of the time it's fine, because if it really is a common use case, the function can also in a lot of cases be written in the user's codebase. But if it's really common, then it's better to have it as an official version. And if it can be tree-shaken, then it doesn't force users to use it.

One example is storeToRefs in Pinia. storeToRefs is not necessary, but a lot of people like this version, and it's fully tree-shakeable. Most of the time, the runtime code is very small. But it doesn't add anything to the size of Pinia when compared, because it's not part of the minimal needed to have a functional and feature-complete Pinia.

In new versions, I'm also exploring the experimental path. So in Vue Router, you have this new experimental export — vue-router/experimental — that exposes new APIs that are not following semver. So if you use them, you need to pay attention to the changelog.

I've shipped through these the new custom resolvers, which is going to be one of the topics I'll be talking about at conferences this year. In Amsterdam, I'll be talking about this. It's more about Vue Router version 6. Currently we have version 4. Version 5 is going to be a simple, easy migration, which I released just before this podcast. And version 6 is more about moving these features forward — still as experimental — becoming stable in 7, because 6 is also about having ESM-only, which is another topic.

So the idea is: if I can play around with this new export, people can use them, I can get feedback, and it's easier to iterate. Especially with AI, people are able sometimes to ship a lot, so they can experiment with things very often. It's easier to get feedback, it's easier to build things, it's faster to build things. People are more likely to build things they wouldn't build manually, and they can just experiment with the APIs as long as they have some documentation to feed the LLM.

My goal here is to have a shorter feedback loop and be able to release these features as non-experimental faster.

Another one is data loaders, also coming as experimental. And the other way of shipping things without having issues with stability was to release them as a separate package. So unplugin-vue-router, for example, which made it back into the core, into Vue Router, and it affected Vue Router development as well because I adapted types — but everything without having any breaking change.

And anything that still requires some thinking — for example, scroll behavior — is an interesting API. With the Navigation API, we could expect this to just work out of the box. And it does work out of the box if you use data loaders, so that the data loading happens before the navigation. When you're on the page, everything is ready to be displayed, then the scroll works because you let the browser just handle the scroll.

The thing is that you will always find edge cases, like "but I have multiple containers and I have this horizontal scroll, vertical scroll, and I want to save them all." So you need a way to handle that, and you don't want to ship a feature like that for everybody because it's very niche — most applications are not going to use multiple scrolls.

I remember that two or three years ago, with Anthony Fu, when he was in Paris, he needed something for the scroll behavior. He created a library and asked me a few questions about some doubts he had, and I helped him on a few points. Now there is this library that is out — which is Vue Router scroll behavior, probably. And I think this is a good example of seeing adoption on features, seeing how many people are using it. You can iterate on it independently, it has a different version that you can pin in your package so it doesn't break — plugins are not going to rely on it. So you're way safer going with this approach of a separate package.

Sorry, I think that went very long.

The alignment between core frameworks and meta-frameworks like Nuxt

But it answers my questions! [laughter] In terms of stability — and about that, because you mentioned mainly Vue Router or Vue in general — but how do you also maintain not just the stability but also the alignment between, for example, Vue as a core framework and a meta-framework such as Nuxt? Because probably there are some differences in how the routing is handled in a classic SPA versus in Nuxt.

So yeah, server-side rendering is more complicated than SPA, right? So if you handle SSR by default, then the SPA just becomes an edge case. That's how it's been handled from the beginning. When I started working on Vue Router 4, SSR was already a concern from the ground up — I mean, from building the library. So it was taken into account from the beginning.

And then Nuxt is free to use the router and extend it in any way they see fit, and sometimes to experiment with new ideas. For example, one of the things that bothers me a little bit — more because if I create integrations that rely on this behavior not changing — but is also interesting to experiment with, is the automatic suspense in Nuxt. Nuxt is able to allow you to use suspense with their own data fetching. What they do, in a way, is render a copy of your application to render that part, which is necessary. It ends up having a very nice API for what I think are simple data-fetching scenarios. It makes for very succinct, simple code to write. And in the best case, when things work well, it's just very simple code.

It does require this double render, which in most applications shouldn't be an issue. Having a double render of the main page shouldn't be a problem. In very specific cases, it can be an issue. But for me, it means that the useRoute composable that they use is different from Vue Router, because they need a route that is different in order to render these two different trees of different pages at the same time.

So we discuss about it and I adapt things if needed on the router. Most of the time, the people on the Nuxt team are very good, and I'm very close to them anyway, so we talk about anything needed and just adapt. Sometimes I also want to push features in Nuxt that exist in Vue Router. For example, the typed pages is something that they incorporated, and I adapted the plugin for Vue Router so that they could use it in a way that didn't break their file-based routing, because they have their own conventions.

I created unplugin-vue-router, which I intentionally made very close to Nuxt. I think we have a few differences — maybe related to optional params, because I remember that I came up with my own syntax. I don't know if it's the same nowadays. But for example, we have named views in unplugin-vue-router, which is not something that exists in the Nuxt file-based system, because I think they don't need it or it's not something they want to use.

My goal is — I know they are aware of things, and as they evolve, I talk to them when I know that some things could be useful for them. Then we collaborate if we need to implement any changes together, so that things are easy and very close between Vue Router and Nuxt.

In the end, Nuxt is not about the routing itself — it's about all the other things that it brings. Vue Router is just the baseline, the official router that works well and is battle-tested. It's light, it's fast, and it can be used by any library.

In fact, for example, TanStack could have used Vue Router if they wanted. I think that would have been better for them, but then they wouldn't be able to do a Vue Router for Solid and a Router for React, right? Because I don't really care — I don't want to spend more time thinking about all their abstractions. It's already complicated enough, and I prefer to focus on one framework that I like and do it well.

Yeah, I completely agree. Otherwise, you would have to create "UnRouter," which is like a universal router for any kind of web framework. But I suppose the amount of edge cases would be...

Yeah, it's more about the rendering — the way a framework renders. I think you could create a router that works well and reuse the codebase. In fact, even with Vue Router, you could reuse the router for Solid and Svelte probably, but maybe not React because it renders differently — it renders too many times. So you would have things that do not work well. Even Solid, I don't know. I think that for frameworks that are closer to signal-based reactivity, it would just work.

In the end, the real abstraction is the RouterView and RouterLink, and then the Composition API parts — useRoute, useRouter — these are the parts that are specific to Vue. Everything else is just agnostic.

Pinia and Vue Router in Vue's long-term vision

I see. So now if we can move a bit into the future of Vue, of Pinia, of Vue Router, how do you see Pinia and Vue Router fit in the Vue long-term vision? Do you see it already, or have you talked about it with Evan? Like, where do those two tools fit into the long-term vision?

So we have talked about things, I think maybe a year ago or a bit more. The idea is: Vue is pretty much stable. If the browser doesn't release any groundbreaking feature, Vue is fast, efficient, and well-used. There is no reason to break things in Vue. This is why the focus has shifted to the compiler part — which is a very good topic of its own — but when you have this compiler abstraction, you can also afford to have changes that are invisible to the end user. Because you have your abstraction layer where the breaking changes happen, but because that abstraction layer is meant to be used by a tool, not a human, then it's not a breaking change anymore — those were internal APIs.

So this is where the innovation happened: more in the performance and development experience — the language server and such. And the same happens for Vue Router. I'm moving things to the compiler basically. What can I do at build time that I can strip off from the runtime?

Pinia doesn't have too much left to strip. It's already small enough. I think there are ideas of how to improve some of the APIs to be performance-first. For example, when you have a store, it's a reactive object, and I think this is very convenient. But some people might want something more like a composable, where if you return a ref or a computed, it stays as a computed and you don't have to unwrap the store.

One of the problems with this approach is that the plugins wouldn't work. The plugin system is something that most people overlook in Pinia, but it's what makes Pinia Colada powerful — the plugins, for example — and it has been there since the very beginning. They improved thanks to Pinia Colada, but the main idea was there.

So I don't think Pinia itself is going to change too much. The goal is: it's stable, it's simple. You don't even need to learn it, honestly. The docs aren't even necessary unless you want to do plugin things. Only if you want to check more advanced stuff. This is why I created the Mastering Pinia course — it has more interesting content, also how it is built inside, for people who like to learn how things are built internally and want to build their own.

The router, on the other hand, is moving more to file-based routing and to approaches that are fully type-safe. So this is an interesting topic because it's about how we code and how it's going to...

How is code and development going to change with AI?

...change with AI. I think a lot of the way we interact with code is going to change — not only code but also the files. The file system is also an API in a way. This is why file-based routing is interesting: you can describe things in the file structure without even needing to read a file, which is very cheap both for a plugin that builds (for Vite, for example) but also for an LLM. It's cheaper than reading the file and recognizing patterns inside of it. Also for a developer — and this is something I've been saying for a long time — the idea of having file-based routing is that because it just sits there, it's very easy to learn. It's right next to you every day, you see it. So if you want to create a file that has a parameter in it — meaning a URL that has a dynamic part — you can recognize it based on other examples. It's very easy.

Nowadays you just ask the LLM and it does it for you. But I think that moving towards a more type-safe and lighter version to consume, that is fast, is the way to go. You want a framework that works well with LLMs and is performant by default, with good practices by default.

I think Vue is the framework that handles this the best. It's not the most popular in LLM generation — that's going to be React and Next.js — but React is nowhere near Vue in terms of performance. It just has a lot more plugins, and that exploded even more with AI. But if you know Vue well, you can create more performant applications without even having to worry about it. And you don't need to tell the LLM about all these possible mistakes and stuff.

So I think that's the way to go: type-safe code that can be read by LLMs, and file-based things that are handled at the build, so you still have this deterministic output and artifacts.

Staying motivated and engaged in open-source

Sounds amazing. So about your work as a maintainer and contributor, what keeps you motivated to do that, year after year, day after day? What keeps you engaged and motivated to do these things every day?

I think it's hard to stay engaged in some of the projects. Normally what keeps you engaged is community — it's more about interacting with people, seeing collaboration with other people. So it's the human contact, the social aspect of it.

Pinia and Vue Router are pretty much one-person projects. It's just me most of the time. And because they are stable, they don't change much. I'm not really needed that much — people don't need to learn much about new things because there aren't that many new things. Now there are a few new things coming up, and those are when I'm needed, but that's it.

So it's difficult when you find yourself in that situation. I think it's important to find other projects that have more collaboration, that you build for others — for friends, for family, for yourself — but that you're able to use every day. I think this is the main important aspect: you want to build something that makes you feel connected to others. Otherwise, you're going to disconnect from the project in the long term.

It happened to me — I think I've disconnected a few times, but it was very short. Conferences helped a lot to keep the connection, the social interaction.

And yeah, I just have other projects sometimes that I build. Nowadays with LLMs, I can also explore other projects, even other languages if I want, in my free time. It's very different. Even small ideas that I usually would not implement because they could take me a full day or a full afternoon — because I still need to learn a few things — I could just ask, research, learn at the same time, review the code, and do the work that usually takes an afternoon in one hour, or sometimes even less, sometimes just half an hour. And then you just push the boundaries of that work. So what you would effectively accomplish in three days, you accomplish in two hours.

So yeah, it's important — especially because of that — to keep that connection, that social aspect. You build some projects for yourself, and some of them you build to share. When I build open source, I build it because I want to use it myself. I want to improve my life, and I think I could improve other people's lives. If I share something, it's usually because I think I built something that can be useful. I want to share it because I can see how it helped me, and I feel happy using it. So I want to share that with others. If it's not used, it's not an issue, because it already helped me.

Message from Eduardo to the Vue community

I also wanted to ask if there is anything you would like to share with the Vue community before we wrap up. Maybe a new package, a new project, a new feature, or something that you would like the community to remember from this video specifically.

I would say Pinia Colada. It's really pretty much stable. I'm honestly going to release v1 pretty soon. The plugin system is very strong. The dev tools are great. The API is stable. I'm able to add features that people might want or are used to but are still niche — or are coming from TanStack Query, for example. People are used to some features on TanStack Query, and I don't need to bloat the main library. I can just add a plugin that adds a compatibility layer, for example. So that's really cool.

Honestly, it's worth a try. It's very light, closer to Pinia, way closer to the Vue way. It's type-safe, fully type-safe, and it can be combined with the data loaders in Vue Router. So you have a lot of very cool features to use. The dev tools are really cool to use. I know that it depends on the projects, but if you use AI, you're not going to use the dev tools that much. But when you need to debug something, you're going to use the dev tools.

And also, the custom resolver. So this is the beta of Vue Router 5. It allows you to move the compilation of the routes to the build time, so that instead of writing your own routes, you let this plugin write them for you, and it generates all the code for every single route you have in your project. Because of this new version and this new way of doing things, we can also match query params and fully transform params, so that they become something other than a string. You still have a string in the URL, but in route.params you have a number, you can have a date, a class if you want — fully type-safe. And it's file-based. It's pretty cool.

I'm looking for feedback as well, because it doesn't have full feature parity with the existing default resolver yet. For example, you don't have dynamic routing, some things like redirects or aliases are not implemented yet. So yeah, some features are missing, but I still think that the main core — the 80%, so to say the Pareto rule — is there. So give it a try!

Where to follow Eduardo's work and stay up to date

Where can listeners follow your work and stay up to date with your projects?

Yeah, most of the time it's my projects on GitHub. And then otherwise, I always post on X and on Bluesky as well — I cross-post.

And what's the handle?

The handle is Posva — P-O-S-V-A. And on Bluesky, it's esm.dev — like ECMAScript Modules, the same: esm.dev.

Okay! So thanks very much, Eduardo, for joining this episode. It was really amazing to learn all those things about routing, about state management — both how they were created, how you're maintaining them today, and what are the plans for the future. They sound amazing. So for our viewers, our listeners, make sure to check out both Pinia Colada and the new version of the router. That will be it from our side. Thanks for being here, and see you and hear you next time.

Thanks for having me.

Jakub Andrzejewski
Jakub Andrzejewski
Senior Frontend Developer at Monterail
Jakub Andrzejewski is a skilled Vue and Node.js developer with a strong focus on Web Performance optimization. As an active contributor to the Vue and Nuxt communities, Jakub creates Open-Source Software, shares insights through technical articles, and delivers engaging talks at technology conferences around the globe.