<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Angga Islami</title>
    <description>The latest articles on DEV Community by Angga Islami (@anggaais).</description>
    <link>https://dev.to/anggaais</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4237496%2F9d14c030-354d-4889-a597-5f05af259632.jpg</url>
      <title>DEV Community: Angga Islami</title>
      <link>https://dev.to/anggaais</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anggaais"/>
    <language>en</language>
    <item>
      <title>I Built a Simple Top Loading Bar for Svelte 5</title>
      <dc:creator>Angga Islami</dc:creator>
      <pubDate>Wed, 11 Nov 2026 02:13:08 +0000</pubDate>
      <link>https://dev.to/anggaais/i-built-a-simple-top-loading-bar-for-svelte-5-dpj</link>
      <guid>https://dev.to/anggaais/i-built-a-simple-top-loading-bar-for-svelte-5-dpj</guid>
      <description>&lt;p&gt;A small loading indicator can make navigation feel much more responsive. But when I looked for a top loading bar for my Svelte 5 app, I wanted something that was simple to add, worked with regular links, and didn’t make SvelteKit-specific code mandatory.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;svelte-topbar&lt;/strong&gt;: a Svelte component powered by NProgress, with automatic tracking for eligible same-origin links and an optional adapter for SvelteKit navigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add it to a Svelte app
&lt;/h2&gt;

&lt;p&gt;Install it with your package manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm install svelte-topbar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use Bun, pnpm, or Yarn. NProgress is installed automatically as a dependency, so you don’t need to add it separately.&lt;/p&gt;

&lt;p&gt;Then render the component once near the top of your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;TopLoader&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'svelte-topbar'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;TopLoader&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#635bff"&lt;/span&gt; &lt;span class="na"&gt;showSpinner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same-origin links are tracked by default. The color and spinner are configurable, along with other NProgress options. The component is also compatible with SSR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it for async work
&lt;/h2&gt;

&lt;p&gt;Sometimes the loading state isn’t caused by a link. For example, you might want to show progress while a user-triggered operation is running. &lt;code&gt;createTopLoader()&lt;/code&gt; gives you controls for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;createTopLoader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'svelte-topbar'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createTopLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;doWork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;loadData&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Load data&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The returned controller also has methods such as &lt;code&gt;setProgress&lt;/code&gt;, &lt;code&gt;inc&lt;/code&gt;, and &lt;code&gt;remove&lt;/code&gt;. It controls the shared NProgress instance, so render one &lt;code&gt;&amp;lt;TopLoader /&amp;gt;&lt;/code&gt; component to configure that instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  And if you’re using SvelteKit?
&lt;/h2&gt;

&lt;p&gt;SvelteKit has its own navigation lifecycle callbacks, so the package includes an optional adapter for them. In your root &lt;code&gt;+layout.svelte&lt;/code&gt;, set up the adapter and turn off the component’s built-in link tracking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nc"&gt;TopLoader&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'svelte-topbar'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;trackSvelteKitNavigation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'svelte-topbar/sveltekit'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;trackSvelteKitNavigation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;TopLoader&lt;/span&gt; &lt;span class="na"&gt;trackLinks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The adapter uses SvelteKit’s &lt;code&gt;beforeNavigate&lt;/code&gt; and &lt;code&gt;afterNavigate&lt;/code&gt; callbacks. It’s a separate import, which means regular Svelte apps don’t need to depend on or import the SvelteKit adapter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I made it
&lt;/h2&gt;

&lt;p&gt;I wanted the basic case to stay basic: install the package, render one component, and get a useful loading indicator for normal same-origin links. When an app needs more control, there’s an imperative API. And when it’s a SvelteKit app, the navigation integration is available without being required by every other Svelte app.&lt;/p&gt;

&lt;p&gt;The package is new, so I’d appreciate feedback from people who try it—especially if the setup is unclear or you run into an issue in a real app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/svelte-topbar" rel="noopener noreferrer"&gt;Get svelte-topbar on npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnggaaIs/svelte-topbar" rel="noopener noreferrer"&gt;Browse the source and demo projects on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AnggaaIs/svelte-topbar/issues" rel="noopener noreferrer"&gt;Open an issue or share feedback&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
