Updates

These posts are aggregated from Svelte GitHub Repository.

  • Svelte Philosophy

    This is an attempt to articulate the Svelte philosophy β€” our bedrock principles, that guide our design decisions.
  • I scored this repo for AI-Readiness and it got 38%,

    Inspired by @MathiasWP's story πŸ‘, decided to share this here.

    I scored this repo for AI-Readiness and it got 38%, so I built a tool to improve the score, and now it gets 100%. The two files are below β€” now AI knows what I'm working on and is optimized for my exact project.

    Before (38%)

    # sveltejs/svelte
    project:
      name: svelte-monorepo
      goal: monorepo for svelte and friends
      main_language: TypeScript
      type: frontend
      frontend: SvelteKit
    

    After (100%)

    # sveltejs/svelte
    project:
      name: svelte
      goal: Cybernetically enhanced web apps
      main_language: TypeScript
      type: framework
      framework: svelte
    stack:
      frontend: SvelteKit
      state_management: Runes
      backend: SvelteKit
      api_type: Server Routes
      runtime: Node.js
      build: Vite
      cicd: GitHub Actions
    human_context:
      who: Svelte core team and open-source contributors
      what: Compiler-first web framework β€” components compile to vanilla JS with no runtime overhead
      why: Web development should be simple, fast, and accessible to everyone
      where: npm (svelte, @sveltejs/kit), used in production worldwide
      when: Created 2016 by Rich Harris, Svelte 5 (Runes) released 2024
      how: Open-source, MIT licensed, community-driven with full-time maintainers
    
  • $state the new store ?

    I was under the impression that $state are meant to replace stores. Yet, if they can't be used in normal js/ts files (e.g. to run unit tests), their usability seems quite limited. I think a comparison table would be helpful when to use a store vs state. Also, will stores also gain deep fine-grained reactivity in svelte 5 ?

    I guess $state is a compiler level feature, but I'm wondering if it would be truly impossible to make it importable so it can be used in any js files, rendering stores obsolete while allowing for straightforward use with TDD.

  • Scoped Custom Element Registries

    Hey, I'm a huge fan of the Custom Elements capabilities of Svelte. In our company, we're building more and more custom elements with Svelte.

    The biggest pain point of Custom Elements in general is the page-wide, shared Custom Element Registry. We have a component library (built with Lit, don't ask why) that is used across many teams (number constantly growing). When we need to render multiple Custom Elements (for example, created with Svelte), we run into the issue that multiple custom elements try to register the same component library components (e.g., button, checkbox, textfield, etc.). To work around this, we currently have a small "hack" on every page where we override the global window.customElements.define function to prevent runtime exceptions.

    Fortunately, there is a very new feature in the HTML Living Standard that addresses this issue: the "Scoped Custom Element Registry". With this feature, each custom element can create its own encapsulated Custom Element Registry. This completely solves this duplication problem and also addresses version conflicts when two different versions of the same custom elements need to be used at the same time. Even though Firefox doesn't have support for this at the moment, this should only be a matter of time, since it is already part of the HTML Living Standard.

    How can Svelte help here? I see two areas where Svelte could step in.

    1. Svelte already provides the helper function $host() to get a reference to the custom element instance. It would be great if Svelte could offer a similar helper function for getting a scoped custom element registry (like $registry()). The creation of a scoped custom element registry could be controlled in the <svelte:options customElement={...}> object.
    2. Currently, when importing a Svelte component that is compiled as a custom element, that component automatically registers itself in the global Custom Element Registry. It would be great if there were a way to prevent this and instead allow the Svelte component to be registered manually in a scoped Custom Element Registry.
  • How can a beginner start building real-world frontend projects?

    Hi everyone,

    I am currently learning frontend development (HTML, CSS, JavaScript) and want to start building real-world projects.

    What are the best beginner-friendly projects and how can I improve my problem-solving skills while learning?

    Any guidance would be appreciated.

    Prinjal Kumari, Frontend Beginner, iCreativez

  • Derived stateful classes

    Is there an idiomatic way to do this? basically i have state, then I have some derived state but it's not pure - it's stateful too. here's a basic example

    
    class Counter {
        counter = $state(0);
    }
    
    class CounterWithAdded {
        counter = $state(0);
    
        sum;
        constructor(props: { add: number }) {
            this.sum = $derived(this.counter + props.add);
        }
    }
    
    const a = new Counter();
    
    // no, this will reset internal counter every time
    const c1 = $derived(new CounterWithAdded({ add: a.counter }));
    
    // recommended approach but wieldy when you have several options like that
    const c2 = new CounterWithAdded({
        get add() {
            return a.counter;
        },
    });
    
    // works and less verbose when a lot of properties probably but feels icky
    class AddProps {
        add = $derived(a.counter);
    }
    const c3 = new CounterWithAdded(new AddProps());
    

    as for the real use case - we're a bank and we have a lot of functions built around svelte 4 stores where a function sets up a bunch of state, and then reused by other functions which derive from its state but declare its own state too and so on. when migrating this to runes - it's not very clear whats a nice, clean solution

    it may look like this

    function userCardsStore() {
        const cards = writable([]);
    
        return { cards };
    }
    
    function userCreditCardsStore() {
        const creditStatus = writable('new');
    
        const cards = userCardsStore();
        const creditCards = derived(cards.cards, ($cards) => $cards.filter(isCredit));
    
        function updateCreditStatus() {
            if (get(creditCards).length === 0) {
                creditStatus.set('empty');
            } else {
                creditStatus.set('with-cards');
            }
        }
    
        return {
            creditCards,
            creditStatus,
            updateCreditStatus,
        };
    }
    

    assume creditStatus cannot just be a derived and since it needs creditCards, we can't just split these stores - it kinda has to be a stateful derived. And it's a big app so we can't be changing the logic much here so of course ideally there should be a straightfoward way to move store code to rune code.

    I guess the 4th option is to introduce some Rune type { current: T} - akin to what fromStore returns and use that instead of Readable/Writable everywhere

    This probably has been asked before but kinda hard to search for

    This is a duplicate question from Discord: https://discord.com/channels/457912077277855764/1489264519468552294

  • ProjectBook β€” Design Thinking Workspace built with SvelteKit

    Hey everyone,

    I’ve been building ProjectBook β€” a Design Thinking–first workspace that connects user research, problem definition, ideation, execution, and feedback into a single system.

    Unlike traditional tools, it focuses on preserving context and linking artifacts across the entire lifecycle.

    Built with:

    • SvelteKit + Svelte 5 runes
    • Remote function architecture (no direct API calls from UI)
    • Tailwind + shadcn-svelte
    • Go backend with RBAC + hybrid DB (Postgres + Mongo)

    Would love feedback from the community πŸ™Œ

    Demo: https://demo.projectbook.dev
    Live working prototype: https://projectbook.dev Repo: https://github.com/MrEthical07/projectbook


    Tech Stack

    Frontend

    • Svelte 5 (Runes)
    • SvelteKit 2
    • Tailwind CSS v4
    • shadcn-svelte + bits-ui
    • Zod + sveltekit-superforms

    Backend

    • Go (modular architecture: handler β†’ service β†’ repository β†’ store)
    • Policy-driven request pipeline (auth β†’ scope β†’ RBAC β†’ rate-limit)

    Database

    • PostgreSQL β†’ relational data (users, projects, permissions)
    • MongoDB β†’ flexible document data (pages, artifacts)

    Caching & Infra

    • Redis β†’ caching + rate limiting
    • Remote function architecture for client-server communication

    Auth

    • Cookie-based auth with automatic token refresh
    • Server-side session + permission hydration

    Email

    • Resend integration
  • Make await works in <script> with <svelte:boundary>

    Testing the new await and <svelte:boundary> features, I came to the conclusion that using await within the <script> tag should have the same effect as when used within <svelte:boundary>.

    <script>
        //
    </script>
    <svelte:boundary>
        {@const result = await promise}
        {#snippet pending()
            Pending
        {/snippet}
    </svelte:boundary>
    

    If I run the code above, the pending component is rendered normally.

    <script>
        const result = await promise;
    </script>
    <svelte:boundary>
        {#snippet pending()
            Pending
        {/snippet}
    </svelte:boundary>
    

    If I run the code above, the pending component is not rendered. Why this is a problem: if I need to use the result value inside the <script> tag, initially, I can't in the first example. In the second one, I can manage it, but I lose the "effect" of the pending snippet. One solution would be to use {result = await promise} inside <svelte:boundary>, but that would generate "dirt markup" within the HTML.

  • Automated accessibility testing for SvelteKit apps

    Quick accessibility testing for SvelteKit projects

    Sharing a tool I built for automated WCAG 2.1 testing that works well with SvelteKit apps.

    Terminal scan (no install)

    npx accessscore https://your-sveltekit-app.com
    

    Runs 16 WCAG 2.1 Level A/AA checks and outputs your score, grade, and issues.

    Results for framework sites

    Site Score Grade Issues
    svelte.dev 87 B 10
    nextjs.org 100 A 1
    react.dev 82 B 14
    tailwindcss.com 73 C 48

    svelte.dev scores 87/B β€” solid but there's room for improvement (missing skip nav, heading hierarchy, some link text issues).

    Common SvelteKit a11y fixes

    Document language (in app.html):

    <html lang="en">
    

    Skip navigation (in +layout.svelte):

    <a href="#main" class="sr-only focus:not-sr-only">Skip to content</a>
    <nav>...</nav>
    <main id="main"><slot /></main>
    

    Image alt text:

    <img src={product.image} alt={product.name} />
    

    Form labels:

    <label for="email">Email</label>
    <input id="email" type="email" bind:value={email} />
    

    Svelte already has built-in a11y warnings in the compiler (which is great!), but automated runtime scanning catches issues that static analysis misses β€” like missing alt text in dynamically rendered content.

    Full tool: accessscore.autonomous-claude.com

  • Why bind to index instead of value in a component with $bindable?

    Hello everyone,

    I am learning Svelte at the moment and have come across this behavior and cannot find an explanation to why the compiler wants me to write the code like this:

    I have a component TodoList.svelte that uses another component TodoItem.svelte.

    TodoList.svelte

    <script>
        import TodoItem from "./TodoItem.svelte";
    
        let { todos = $bindable(), removeTodo } = $props()
    </script>
    
    <ul>
        {#each todos as todo, i}
            <TodoItem bind:todo={todos[i]} {removeTodo}/>
        {/each}
    </ul>
    

    TodoItem.svelte

    <script>
        import { slide } from "svelte/transition";
        
        let { todo = $bindable(), removeTodo } = $props()
    </script>
    
    <li transition:slide>
        <input type="checkbox" bind:checked={todo.completed}>
        <input type="text" bind:value={todo.text}>
        <button onclick="{() => removeTodo(todo)}">x</button>
    </li>
    

    In TodoItem.svelte, I am binding to todo as I want to mutate it by activating/deactivating the checkbox and so mutate todo.completed.

    In TodoList.svelte I need to use bind:todo={todo[i]} or I will get a warning about the mutability of todo and that I should use bind.

    Why do I need to pass the reference to the right todo object in the each loop by its index instead of directly using the value, like:

    {#each todos as todo, i}
        <TodoItem bind:todo={todo} {removeTodo}/>
    {/each}
    

    Thanks in advance! I am still learning and this somehow stopped me as I want to understand but couldn't find an entry to the right topic in the documentation.

Loading Svelte Themes