Tenets
#10085
Discussion
This is an attempt to articulate the Svelte philosophy — our bedrock principles, that guide our design decisions.
Edit: for visitors from Hacker News, and anyone else who is curious, that this list came out of
The web matters #
We work on Svelte because we believe that the web is a critically important technology, and that its continued survival is not guaranteed.
Optimise for vibes #
People use Svelte because they like Svelte. They like it because it aligns with their aesthetic sensibilities.
Instead of striving to be the fastest or smallest or whateverest, we explicitly aim to be the framework with the best vibes.
Don't optimise for adoption #
We're not trying to be the most popular framework, we're trying to be the best framework. Sometimes that means making choices that we believe in but that go against the grain of web development trends.
HTML, The Mother Language #
HTML is a really good language for describing UI. Svelte augments HTML in a way that makes it a really good language for describing interactive UI.
Most frameworks are JS-centric, because JS is the most powerful language. But then they find themselves jumping through hoops to make it feel like you're writing HTML. We think both options are valid, but the HTML-first approach ends up feeling more natural.
Embrace progress #
There is a tendency in the web developer community towards a harmful form of pessimistic nostalgia — the idea that things were better in the prelapsarian age before bundlers, TypeScript, client-side routing and other trappings of modernity.
This is nonsense. As a community our default position is one of optimism about technology — the platform is getting better, our tools are getting better, our devices are getting better, and if we embrace that fact we can make better stuff.
And when other frameworks introduce new ideas like signals or server components, we look at them with interest and jealousy, and try to work out how we can incorporate good ideas, instead of resting on our laurels. There is always room for improvement.
Numbers lie #
Lighthouse has broken the brains of a generation of web developers. We have replaced good judgment with subservience to metrics that were only ever intended to be used as a diagnostic tool.
Goodhart's Law states that
When a measure becomes a target, it ceases to be a good measure
and this is very true in web development. Numerical rigour is good, and we pay attention to the various numbers, but when designing Svelte we think qualitatively, not quantitatively.
Magical, not magic #
There's a subtle line between something feeling magical, and something feeling like magic. We want Svelte to feel magical — we want you to feel like a wizard when you're writing Svelte code. Historically I think Svelte went too far into magic territory, where it's not 100% clear why things work a certain way, and that's something that we're rectifying with Svelte 5.
Dream big #
'Choose the right tool for the job' is sensible but boring advice.
It makes us small in our ambitions. I want us to dream bigger. I don't want to feel like my tools can't handle evolving requirements, or that if I want to dabble in a new field I need to learn an entirely new way of working first.
Even if it turns out to be unachievable, I find it valuable to ask the question 'what would it take for SvelteKit to be the best framework for any app?', whether it's purely static content, or a realtime multiplayer app, or an offline-first productivity app, or even something built for an augmented reality headset.
No-one cares #
Most people do not care about frameworks. They just want to build something cool, and Svelte is for those people too.
So when we design things we need to think about the people who haven't read the docs in a while, if at all, and don't care about things like fine-grained rendering or configuring their build tool. This means that things need to be intuitive, that we shouldn't need to worry about manual optimisations like memoisation, that we should have as few APIs as possible, and that things need to be discoverable — for example you should be able to hover over a rune and get a link to comprehensive documentation.
This also informs our approach to documentation and tutorials — it should be possible to build what you want by just learning the concepts that you need, and worrying about the other stuff for another day.
Design by consensus #
Svelte is a community-driven and consensus-led project. It's important that the community — that's you — has a stake in the project's future. Many of Svelte's best ideas originated outside the core team.
When we introduce new plans, we want to communicate them openly and provide everyone with good opportunities to offer their feedback.
Those of us who work on the project every day have a vision for what kind of thing we want it to be, but we don't want to foist that vision on people against their will. And so while we can't get unanimous agreement on every change, we can at least say that dissenting voices have been heard and considered.
Info
@Rich-Harris How do you imagen sveltekit will embrace the no-one cares tenet? I dream of a world where we don't have to think of package managers as much.
Check out Nix 🤠
Oh, you moved from 'optimise for vibes' when you decided to deprecate export let in future version
it made more easy for developer rather than writing 10 export let...just use simple one line ...that's it embrace change my friend
I disagree, the prop rune opens so much
- It helps with stuff such as exporting reserved key word easier
- Also events as props is absolutely amazing
- And as stated it is a lot more terse
I'd sacrifice some code cleanliness for some code legibility & maintainability any day of the week.
I'm a hardcore Svelte user and I always find it strange when some people stick to the export let, the props rune was the one I accepted the fastest by far
It's all a matter of what code we write.
In the first place, Svelte was advertised as "just write plain HTML, CSS and JS!". This was the best feeling. Adding Typescript and CSS preprocessors was good because it allowed "better" flexibility and other syntaxes but still writing "non-svelte" code in svelte components.
Runes are to me the same thing as compilation flags, Rust attributes or features, or C preprocessor directives.
It goes beyond JS, just like a new flavour or syntax, by bringing something that is not accessible through normal import statements.
About runes, I would have been perfectly okay if we had to do import { $state } from 'svelte';. After all, that's what all other frameworks do.
The "it removes one line of code" argument to me is completely useless.
Why remove one line of code if it makes things harder to debug, forces us to remember everything in our already busy brains, while we could just import types based on self-documenting code? There isn't even any auto-completion because it's "svelte-specific", and all IDEs have to adapt. While using import statements would probably don't change many things because in the end you preprocess the JS. But at least this would be true JS code, the very first thing Svelte was here for: simplify things by writing as less "framework-dependent" code.
More code doesn't mean "more complex code".
A bit more lines of code won't complexify things if they make everything clear, easier to debug, easier to test, and self-explanatory with no redundancy. That kind of redundancy about props that we can find in React or Vue for instance, that Svelte doesn't have with export let because it's self-explanatory: it exports a variable to the outside world of this component, I don't see how it could be clearer.
I mean, there are a few svelte-specific things to learn on . One could learn Svelte in an hour, because there is just the "templating syntax" in the HTML part, the export let (which, again, is perfectly valid JS code), and the functions one can import from Svelte (like onMount) which is easy to discover without even reading the docs.
By adding runes, you add more cognitive load to what is "svelte-specific" and that will not be cross-compatible with any framework.
As a full-stack developer with 10+ years of experience, I've seen projects stuck on "framework-specific" code more than once, just to ship code quickly to prod, and then requiring days (if not weeks) of debugging one or two years later because nobody thought about architecture and decoupling.
Now, by architecturing an app according to its needs, and by decoupling as many things from the framework as possible (not everything can be, but we can do it as much as we can), we ensure code reusability, standalone components, functions, classes, etc., ensuring debugging and testing is better.
Now add runes all over the place and your code is now incompatible with any other non-svelte code. What if I'm developing a TS lib in a Svelte app, and turns out another team from the company needs the code but they are using Vue and there are preprocessed Svelte runes everywhere? Not possible anymore without huge refactorings.
Unless the Svelte library can provide a harmless preprocessor to add to any bundler that will resolve runes somehow, but I think this would be a bad idea because it would add a huge burden to the maintenance team for an overly complex solution, while simpler ones could have been chosen.
I could talk hours about what I've seen and experienced in the past decade and more that made me fall in love with Svelte by its simplicity, and the "potential mistakes" I see coming with Runes or other potential ideas that the community may bring. I'd be glad to have a long conversation with the Svelte core team about this, I think it would definitely enlighten me, or maybe convince me, but so far, I'm not convinced about the real reasons for Svelte Runes, or deprecating "export let".
By adding runes, you add more cognitive load to what is "svelte-specific" and that will not be cross-compatible with any framework.
export let is Svelte-specific. It may use JS syntax, but it doesn't translate over to any other framework. Overall, runes reduce the number of Svelte-specific things. There's a list . $props is probably my favorite rune since it makes it easier to reuse types for props, including making generic components a lot easier to work with, and it means we don't have to use the old $$props and $$restProps anymore. On top of that, it's probably easier for newcomers to understand, since props are a common concept between component frameworks. On the other hand, newcomers might see export let and it won't be immediately obvious that it has special meaning to Svelte, and it may even get confused with export const, which means something completely different.
Maybe I'll just get used to it, hopefully. It's already quite annoying to have the +page.svelte system that replaced the old SvelteKit routing system 😅 I know the reasons for these changes, I've seen at least two videos of Rich talking about it, and seen a few posts, and the Svelte blog.
We'll see about the adoption and next updates 🤞
No, you just experience that "harmful form of pessimistic nostalgia" after using $props. export let always was weird - the export keyword directs data flow outside (of a module) while in Svelte it is used for, in general, incoming data flow.
And yeah, $props can be cumbersome in some cases, but Svelte 5 hasn't reached its final form yet.
"This isn't even my final form" - Svelte 5
(Hoping for #9241 to happen.)
$propsis probably my favorite rune since it makes it easier to reuse types for props, including making generic components a lot easier to work with
@eddiemcconkie, can you explain this further (with special emphasis on the "makes it easier to reuse types for props" part)? Working on a design system where we want every component to accept a baseline of props. Will the $props rune make that possible? Any examples?
@AlanBreck sure! Here's a REPL with a couple examples.
If you want every component to accept a baseline of props, you can define an interface with TypeScript, and then extend that interface within each component. In the example, the circle and rectangle components both have color and stroke props, but the circle also has a radius and the rectangle also has width and height.
A really handy use case, though, is if you want to extend the functionality of an existing HTML element, like a button, you can extend the HTMLButtonAttributes type provided by Svelte. This is much easier to do in Svelte 5, compared to Svelte 4.
Thank you! What about from a runtime perspective? Will the $props rune help determine what props are available for a component during runtime, though?
Not totally sure on that one! Someone from the core team could probably give a good answer, but I'm guessing the compiled code gets optimized based on which props you destructure from $props()
I think that's it @eddiemcconkie, that's the argument that can convince me 👌 As a typescript fan, I can definitely see the advantage of being able to just define the types myself, it's probably even easier to generally document 👍
Addition to my big comment above: I'm still not a hype fan of Runes, but now I just don't like them when outside Svelte files. If everything stays in the Svelte file, all is good 👌 And Runes are actually interesting. I'm almost convinced. It just took time. I'm still into this "separation of concerns" thing: Svelte code in Svelte files, JS/TS code in JS/TS files. I would still dislike very much the obligation to compile JS/TS code with Svelte outside of Svelte components, because IMO that's completely different. I really like Svelte also because it's more okay to use it as a frontend templating engine, or as plug-and-play JS components (just like Web components).
(sorry for all the fuss)
the first time I use Svelte & Kit I feel the same joy as I feel when the first time learning web development in 2015
I don't know how I can be thankful enough
I also started in the web track back in 2016 and I wasn't fond of frontend, but came back to it in 2020 because I heard the word svelte on reddit and watched a crash course from traversy media, and quickly fall in love with svelte & frontend.
I love the "Vibe Based Optimization" philosophy
cosign, i'm here for the aesthetic ;)
no-one cares, that's the best vibe 🎉
RICH FOR PRESIDENT
Harris for president :)
With enthusiasm and community like ours, I feel like SvelteKit in five years from now will able to do this:
- +page.server.go (adapter/go)
- +page.server.py (adapter/python)
- +page.server.rs (adapter/rust)
- +page.server.rb (adapter/ruby)
- +page.server.ex (adapter/elixir)
- +page.server.php (adapter/php)
Enjoyed The Tenets
it would be crazy if would be able to add python to it...and integrate with ai models in seconds......or simple python integration in seconds
My guess is with Bun this will be possible since they make it easy to import files if they have a good C FFI. We've already seen Rust and C++ being imported easily into Bun. The only thing I'm not sure about is svelte/kit's tight coupling to vite since I assume Bun would need to do all the bundling and etc
That's actually a great idea.
Yes please
I gave up on learning webdev some time ago. Svelte brought me back last year! I wish there was a bit more in the philosophy of going from 0 - 1 given a lot of docs and resources cater for other web framework converts.
Great tenets and can't wait whats ahead!
Beautifully said for the most part!
HTML, The Mother Language !
I've just realized that with Tailwind you put css in html, and with htmx you put js in html. It is wild how powerful just html can be. I've personally been fully converted to the church of html first 😅 I reeeally like how Svelte is html first, but then also gives you all of css and js right there in <style> and <script> tags if you need them.
But then they find themselves jumping through hoops to make it feel like you're writing HTML. We think both options are valid, but the HTML-first approach ends up feeling more natural.
This is the biggest reason for me to use Svelte.
it should be possible to build what you want by just learning the concepts that you need, and worrying about the other stuff for another day.
As a backend dev trying to do frontend stuff sometimes for side projects this statement is the best thing i ever read.
I love svelte and kit. Even I am just a regular developer but I really enjoy what svelte has reached so far and use svelte and kit as my main tool. I used to learn React, I do not like it because the virtual DOM and advertising that virtual DOM beat DOM, I learn Angular, I feel it too heavy and uncessary thing to configure and pain in ass like layout and router. I wish Svelte still enjoyable to make web because right now there is no a single framework can do it like Svelte and I love the no one cares and numbers lie philosophy because I am tired of those, just look at React has to change to compiler, it's funny 😂
No mention of cybernetics?
My hate for JSX alone would push me toward Svelte :) I mean, returning a tag?! Accepted by the same people shitting on PHP for mangling code with templating.
Regarding "Don't optimise for adoption", if the other tenets are done well adoption rates will increase. So perhaps adoption rates can be a measure of how well other things are being done. I actually think adoption rates are important because when choosing a development environment one of the considerations is how many people can be employed with the necessary experience.
I've written this out elsewhere, but thought I'd repost it - and significantly elaborate on it - here, because it feels relevant, specifically to the "No one cares" point:
I'm really not a fan of how much "background knowledge" is now necessary in many Svelte 5 workflows in general. The introduction of proxied state may have opened up new possibilities and quality of life, but it's also brought many a potential pitfall and footgun with it, and it seems like there are too many stopgap measures and bandaid fixes to issues it's brought up that essentially boil down to "this thing that was previously possible and intuitive with little headache now requires this very specific workflow that you'll always have to keep in mind if you don't want to run into issues".
In short, when previously, you could write code that looks like it should work, and it worked as you expected - I'd reckon this aspect of Svelte was the main reason for why it was the king of DX - now, you constantly need to worry about how Svelte achieves what it achieves in the background.
For instance, you need to remember to $state.snapshot when you send state to an outside consumer because the state is proxied - but you have to know that state is proxied in order to know do this, and if you don't, stuff might break in unexpected and obscure ways.
Or, you need to use $state.is to compare a value to reactive state, which means there is now a distinction between the two where there didn't use to be - and if you don't know that, then you're going to wonder why your comparisons seem so wonky.
Or, you now need to use specific Svelte-only Maps and Sets and Dates and somesuch if you want them to be reactive, which reduces framework agnosticity of all affected code - and you need to know about their existence in order to not be confused when, suddenly, you can no longer use the "vanilla" versions of them in your code and have them be reactive.
Or - as an extension of this - you have to know that state is proxied and that proxying any arbitrary object is a bad idea in order to understand why non-POJOs will just blanket refuse to become reactive in Svelte 5 now, requiring you to either write cumbersome boilerplate to make it work or tie all of your application's code to Svelte inextricably by adding runes all over it.
Every one of these examples is going to need a mention somewhere in the docs, adding sizeable API surface, and will add something you will need to mentally make a note of and keep in the back of your mind whenever you write Svelte code. It feels very un-Svelte-like, and I wouldn't be surprised to see many issues related to all of the above pop up once Svelte 5 is out and about.
To circle back to the tenets: I agree that "no one cares", and previously, no one had to care. You wrote code that looked like it should work, and it worked. Therein lay the magic of Svelte. Now, you do have to care in what feels like far too many cases, and if you don't, then the code you wrote, the code that looks like it should work... just won't work. And you'll have no idea why, because broadly, this stuff just isn't intuitive to anyone who doesn't know about how Svelte works behind the curtains.
I agree that Svelte 5 has some issues (and unfortunately there probably will never be a perfect solution to all this), but I disagree with some of these points.
you now need to use specific Svelte-only Maps and Sets and Dates [...] you can no longer use the "vanilla" versions of them in your code and have them be reactive
The orignal data structures were not reactive in Svelte 3/4, the only way to force reactivity on them was with reassignments or dummy assignments. You can also still use these in Svelte 5, if you replace the instance which is very common for Date. The native API on that class to mutate the object are not that great, so I don't see myself using the Svelte version of this anyway.
You wrote code that looked like it should work, and it worked.
Not necessarily. You might think that objects passed to functions and modified there would update the page, they did not. Reactivity outside of Svelte files was not possible without learning the cumbersome stores API. You might try to use an array of stores, only to find out that you cannot use $-syntax in an #each loop. You try to .push to an array, nothing happens.
There are many such cases that people run into sooner or later. Poxies, getters/setters, effects and other things will also cause some confusion, but it is yet to be seen whether it is actually worse than the status quo.
The orignal data structures were not reactive in Svelte 3/4, the only way to force reactivity on them was with reassignments or dummy assignments. You can also still use these in Svelte 5, if you replace the instance which is very common for Date. The native API on that class to mutate the object are not that great, so I don't see myself using the Svelte version of this anyway.
You're correct - you indeed had to reassign them using the old foo = foo trick. I still think that's better than having to use the Svelte versions of them now, since said trick no longer works due to the new fine-grained reactivity - but I'm not going to argue against fine-grained reactivity, because the positives vastly outshine everything else here, so I've struck that part through in the original comment.
Not necessarily. You might think that objects passed to functions and modified there would update the page, they did not. Reactivity outside of Svelte files was not possible without learning the cumbersome stores API. You might try to use an array of stores, only to find out that you cannot use $-syntax in an #each loop. You try to .push to an array, nothing happens.
Those are fair points, and longstanding odd quirks of Svelte 3/4, but I'd argue they had a much smaller impact on DX than the potential pitfalls with proxies might have, because most of them rely on a simple rule that lay core to the framework's function: reactivity is triggered by assignment. It's true that you have to switch around your methodology somewhat when writing code for Svelte 3/4, but at most, you have to remember to update arrays using spread notation and reassign reactive variables if you update them indirectly somewhere - if something didn't work quite as expected, adding foo = foo somewhere would probably solve your problem. Is it pretty? Of course not. It's API surface and weird one at that. But at least it's simple.
In Svelte 5, there are many different kinds of state and "states of state" to keep track of: your foo could be a simple $state. But it could also be a $state.frozen. Can you tell just by looking at the place where it's being used? What about frozen state that contains reactive state? Or vice-versa? Say you're writing a function and passing your state into it - well, later, you're a refactor or two in, and you'll have to scour your code to see whether it was originally passed in using $state.snapshot or not in order to figure out which kind of comparisons to use and whether you should still snapshot it if you pass it on somewhere. Or you could say you'll just always use $state.is for comparisons where proxies might be involved and $state.snapshot whenever you pass anything anywhere; but now you're potentially sprinkling pointless runes all over your code, even where proxies might be nowhere near, which might confuse future readers (including future you) even more. Or let's assume we're a couple of services deep into the callstack, and somewhere way further up the call chain someone changes a line of code to pass the state itself instead of a snapshot of it - and suddenly you have to potentially rewrite code across several files to deal with it, lest it cause unexpected behavior somewhere completely different and seemingly unrelated!
Of course, above examples are from a lawless horror world in which basically every coding convention is being broken, objects are being mutated hours from home without concern for innocent lives, and there are no rules for anything - I'm not saying any of these things are going to happen on the daily. But in Svelte 3/4, you had to worry about zilch of any of that, because things were only reactive within your component and you knew that things would only update if some sort of assignment was involved. And if you wanted reactivity beyond your component, you'd use stores - which were explicit. You knew by looking at a piece of code whether that store was being accessed, updated, set, subscribed, or unsubscribed to, and you generally knew that stores existed for the explicit purpose of allowing for reactivity across multiple locations - so you'd only use them where that purpose needed fulfilled and you knew, wherever they were used, and whenever you did access them, to potentially expect side-effects somewhere else. In Svelte 5, when you're far away from home, refactoring a function that accepts any sort of object, you have no idea whether you're potentially dealing with a proxy or not - and that potentially includes code within files that aren't even .svelte.js.
I don't think objects passed to functions and modified there should be reactive by default, is essentially what I'm saying. Whenever you use reactive state outside of where it's eventually consumed - which is going to be some sort of UI element in a component in 99% of cases - I think you should have to be very explicit about wanting to update it elsewhere as a result of your actions. Objects passed to functions should be "unstated" by default unless you explicitly say they shouldn't. The same goes for comparisons between potentially proxied values (I don't see any scenario in which you wouldn't want this anyway - there's never a situation where I would want foo.bar === bar to be false, ). We are using a compiler; we can do these things by default. I fear the focus on "less magic, more magical" is leading to situations where things that only would make sense to preprocess aren't being preprocessed because we're too afraid that someone might think the compiler is doing too many things without telling.
I think the runes themselves are a huge step in the right direction, but throwing proxies into the mix and trying to make them "transparent", but then also allowing users to pass them around, potentially even without knowing, and making users keep track of which state is proxied now and which isn't, and having them make sure you never pass a proxy where it shouldn't go, does the exact opposite of making them "transparent". Like, it's cool that we can arr.push() now and it'll be reactive, but... at what cost... at what coooost?
Those are fair points, and longstanding odd quirks of Svelte 3/4, but I'd argue they had a much smaller impact on DX than the potential pitfalls with proxies might have
You literally say, "I learned the Svelte 3/4 quirks the hard way (the only way to learn it is to step on and debug for hours only to find out that it is Svelte's unfixable bug) and got used to them", which, in fact, isn't good DX at all.
I believe you think about states too much. Unless a function stores somewhere the passed arguments, it's ok to pass in a proxied state.
You literally say, "I learned the Svelte 3/4 quirks the hard way (the only way to learn it is to step on and debug for hours only to find out that it is Svelte's unfixable bug) and got used to them", which, in fact, isn't good DX at all.
When do I literally say that? I don't remember saying anything of the sort. The Svelte 4 docs, as well as the tutorial, outline that reactivity is triggered by assignment to the reactive variable, and Svelte 4's behavior largely follows this rule. I doubt many people lost hours in the debugger for this issue that's very prominently pointed out pretty much anywhere that the docs teach you how reactivity works in the first place.
Unless a function stores somewhere the passed arguments, it's ok to pass in a proxied state.
Right, but the issue is that it's impossible to tell at a glance whether the argument you're receiving (or passing, for that matter) is proxied state, particularly when you're dealing with code that lives somewhere other than where said state is declared. Even if you meticulously keep mental track of where exactly every argument you're receiving comes from while you write it, good luck remembering that a few months down the line when you have to touch that code again while refactoring some other feature.
I probably misunderstood your words about Svelte quirks, sorry.
Svlete 3/4 has many undocumented quirks of the reactivity: (I have found 54 issues about reactivity, though some repeats). Roughly half of them are caused by the reactivity implementation, and the other half - by the reactivity design (syntax + rules).
Almost all of them are undocumented, and you encounter many of them when writing more or less complex apps. It's awful to spend hours debugging the app only to find out that it is Svelte's unfixable bug.
I hope Svelte 5 will properly document the edge cases of the runes so we can write apps without unexpected surprises.
the issue is that it's impossible to tell at a glance whether the argument you're receiving (or passing, for that matter) is proxied state
I haven't written big apps with Svelte 5, but I don't notice complaints about it from people who have. So, I believe that either you overestimate the problem, or your personal code style doesn't go well with runes (or kinda both).
Regarding adding reactivity to "Array.push()" and other stuff, I personally wouldn't have minded a few Svelte-specific data structures. I mean, doing something like const myData = new ReactiveArray(); in order for myData.push(someData) to call reactivity, that would have been great, because it's only a data structure, and the implementation behind is clear: when internal array is modified, reactivity is triggered.
For the rest, I still think having a mix of too complex&generic structure (like proxies) is both nice and bad. It's generic enough so it's good for many purposes, but it comes with other quirks (and we already have enough quirks everywhere). To me, the issues @7nik pointed that Svelte has in v3 and v4 are maybe fixed, but when I look at how it works, it's more like "Fixed with another hack, but instead of a syntax hack, it's now a generic-data-structure-based hack".
I hope I will be convinced once I use Svelte 5 every day 😕
"Fixed with another hack, but instead of a syntax hack, it's now a generic-data-structure-based hack"
I felt that. Some degree of "generic-data-structure-based hack" is acceptable but right now it just doesn't feel right. Way overcomplicated for what it's worth. Not going to replace stores as it is currently, not with this many gotchas and conditions.
EDIT: It's actually fine.
I've gotta say, runes ruin the vibes
I will just say, that's how I felt initially, when it was announced. I always thought of Svelte as the one where you didn't have to think of this - where reactivity "just happened" and "just worked". In hind sight, this feels reactive. Having seen Rich talk about runes more recently, and then deciding to try it, I gotta say, I get it now. It's still declarative, but the runes are not just annoying boilerplate, they're useful to the reader because you don't have to figure out what's reactive or not. I changed my mind. Maybe you can too? 🙃
Please revert the changes made in Svelte 5
😂😂😂
Pro tip: You can prefix GitHub URLs of issues, PRs or discussions with svcl.dev/ to view them on this page! Also try it on a GitHub release ;)