<?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: Peter Hallander</title>
    <description>The latest articles on DEV Community by Peter Hallander (@stackedboost).</description>
    <link>https://dev.to/stackedboost</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3843719%2F0ea5966b-9e47-4633-b38c-5ca07e7f14b5.JPG</url>
      <title>DEV Community: Peter Hallander</title>
      <link>https://dev.to/stackedboost</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stackedboost"/>
    <language>en</language>
    <item>
      <title>How Polish Accounting Firms Are Managing KSeF Tokens for 50+ Clients at Once</title>
      <dc:creator>Peter Hallander</dc:creator>
      <pubDate>Mon, 27 Apr 2026 10:29:17 +0000</pubDate>
      <link>https://dev.to/stackedboost/how-polish-accounting-firms-are-managing-ksef-tokens-for-50-clients-at-once-p34</link>
      <guid>https://dev.to/stackedboost/how-polish-accounting-firms-are-managing-ksef-tokens-for-50-clients-at-once-p34</guid>
      <description>&lt;p&gt;If you run an accounting firm in Poland, the past year has meant one thing above everything else: KSeF. The National e-Invoice System (Krajowy System e-Faktur) has dominated compliance conversations for months, and for good reason. But most of the public discussion focuses on the invoice format itself. What gets far less attention is the authentication layer, and that is where the real operational headache lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Token Per Client, Multiplied by 50
&lt;/h2&gt;

&lt;p&gt;KSeF uses a token-based authorization model. Each company registered in the system can generate API tokens that allow authorized software to send and receive invoices on its behalf. Simple enough in theory. In practice, when you are a bookkeeper managing the finances of 50, 80, or 150 businesses, you suddenly have 50 to 150 separate tokens to generate, store, rotate, and track.&lt;/p&gt;

&lt;p&gt;Each token is tied to a specific NIP (Polish tax identification number). Each one has its own permissions scope, its own expiration window, and its own generation date. If a token gets revoked, the connected software stops working silently. If you store tokens in a shared spreadsheet and someone leaves the company, that spreadsheet is now a security liability. And if a client asks you to revoke their access immediately, you need to find the right token fast, not scroll through rows in a Google Sheet under pressure.&lt;/p&gt;

&lt;p&gt;This is not a hypothetical. It is the daily reality for hundreds of Polish accounting offices right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What KSeF Actually Requires Under the Hood
&lt;/h2&gt;

&lt;p&gt;KSeF authentication works through the Ministry of Finance API. You can find the full technical terminology explained in the &lt;a href="https://fakturaflow.pl/slownik-ksef" rel="noopener noreferrer"&gt;KSeF glossary&lt;/a&gt;, but the short version is this: to interact with the system on behalf of a taxpayer, your software needs a valid session token. To get a session token, you first need an authorization token that was granted by that taxpayer.&lt;/p&gt;

&lt;p&gt;The authorization token is generated in the KSeF production environment by the company's NIP holder, or someone they explicitly delegate. Once you have it, you use it to open sessions and send or receive invoices. The token does not expire on a fixed schedule, but it can be revoked by the client at any time, and it is specific to the NIP it was issued for.&lt;/p&gt;

&lt;p&gt;The technical flow is straightforward for a single client. Multiply it across dozens of clients, with different delegation setups, different software configurations, and different client expectations for how often credentials should rotate, and the complexity becomes real.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Firms Are Actually Handling This
&lt;/h2&gt;

&lt;p&gt;From conversations with accountants working in this space, there are roughly three approaches in active use right now.&lt;/p&gt;

&lt;p&gt;The first is a spreadsheet or text document. It works, technically. Firms list client NIP, token value, date of generation, who generated it, and maybe a rotation reminder. This approach is fine for five clients. At thirty it becomes fragile. At eighty it is a genuine liability, both operationally and from a data security standpoint.&lt;/p&gt;

&lt;p&gt;The second approach involves password managers like 1Password or Bitwarden. Better than a spreadsheet for security, but these tools were not designed for structured credential management across dozens of businesses with context-specific fields. You end up with messy folder structures and no way to see at a glance which tokens are stale, which clients have not yet delegated access, or whether a token belongs to the production environment versus test.&lt;/p&gt;

&lt;p&gt;The third approach, where firms with larger client books are moving, is dedicated tooling. The idea is simple: a system that stores KSeF tokens alongside client NIP data, tracks their status, and integrates directly with the invoicing workflow. No copy-pasting between a credential vault and an invoicing app. No switching tabs to check whether a token is still valid before sending a batch of invoices.&lt;/p&gt;

&lt;p&gt;This operational challenge is exactly what shaped the design of &lt;a href="https://fakturaflow.pl" rel="noopener noreferrer"&gt;FakturaFlow&lt;/a&gt;. The platform was built from the start for accounting firms handling KSeF access for multiple clients, with token management treated as a core part of the data model rather than bolted on afterward. When you are sending invoices for forty clients in a single morning, the token is not a side detail, it is part of the critical path.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern That Keeps Emerging
&lt;/h2&gt;

&lt;p&gt;The firms that struggle most with KSeF are not struggling with the invoice format. The XML schema, the mandatory fields, the FA namespace, those are learnable problems. The struggle is operational: credentials, delegation chains, permissions, client communication about access, and what happens when a token breaks something at 4pm on a Friday.&lt;/p&gt;

&lt;p&gt;The firms handling it smoothly have made a deliberate choice about where token data lives and how that storage connects to their daily invoicing work. That choice is worth making explicitly, before something breaks at an inconvenient moment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you are managing KSeF access for a larger client book, how are you currently handling token storage and rotation? Spreadsheet, password manager, custom solution, or something else entirely?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>compliance</category>
      <category>saas</category>
      <category>poland</category>
    </item>
    <item>
      <title>I built a Shopify app that makes stores feel instant using link prefetching</title>
      <dc:creator>Peter Hallander</dc:creator>
      <pubDate>Wed, 22 Apr 2026 08:43:30 +0000</pubDate>
      <link>https://dev.to/stackedboost/i-built-a-shopify-app-that-makes-stores-feel-instant-using-link-prefetching-56af</link>
      <guid>https://dev.to/stackedboost/i-built-a-shopify-app-that-makes-stores-feel-instant-using-link-prefetching-56af</guid>
      <description>&lt;p&gt;I've been building small Shopify apps as side projects for a while, and one thing that's always bugged me about Shopify stores is the noticeable page load delay when navigating between products and pages.&lt;/p&gt;

&lt;p&gt;You click a link, and there's a brief but annoying pause before anything happens. It's not catastrophic, but that friction adds up — especially on mobile connections. I decided to fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea: prefetch on hover
&lt;/h2&gt;

&lt;p&gt;The fix is conceptually simple. When a user hovers over a link, there's roughly a 200–400ms window before they actually click. That's enough time to start loading the destination page in the background, so by the time they click, the page is already partially (or fully) loaded.&lt;/p&gt;

&lt;p&gt;This technique is called &lt;strong&gt;link prefetching&lt;/strong&gt;, and libraries like &lt;a href="https://instant.page" rel="noopener noreferrer"&gt;instant.page&lt;/a&gt; and &lt;a href="https://github.com/GoogleChromeLabs/quicklink" rel="noopener noreferrer"&gt;quicklink&lt;/a&gt; have been doing it on general websites for years. But for Shopify specifically, there was no dead-simple plug-and-play solution that works within the app ecosystem constraints. So I built one: &lt;a href="https://apps.shopify.com/prefetch" rel="noopener noreferrer"&gt;Prefetch for Shopify&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works technically
&lt;/h2&gt;

&lt;p&gt;Prefetch injects a small script (~2KB gzipped) into your storefront that listens for hover events and fires prefetch requests using &lt;code&gt;&amp;lt;link rel="prefetch"&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A few nuances worth sharing:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Debouncing hover intent
&lt;/h3&gt;

&lt;p&gt;We don't prefetch on every fleeting mouseover — that would waste bandwidth and fire constantly as users scan a page. Instead, we use a ~65ms delay to detect genuine hover intent. Fast accidental mouse movements don't count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouseover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;hoverTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;prefetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouseout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hoverTimer&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Network-aware prefetching
&lt;/h3&gt;

&lt;p&gt;On slow connections (2G/slow-3G), prefetching is a net negative — it would consume the limited bandwidth users need for the actual page they're on. The script checks &lt;code&gt;navigator.connection.effectiveType&lt;/code&gt; and disables itself on slow connections automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saveData&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="sr"&gt;/2g/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;effectiveType&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Only prefetch what matters
&lt;/h3&gt;

&lt;p&gt;We limit prefetching to internal store links (same origin only), skip already-cached URLs, skip checkout/cart links, and skip static resource files. Only navigational page links get prefetched — which is what actually benefits the user.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Mobile: touchstart instead of mouseover
&lt;/h3&gt;

&lt;p&gt;On mobile there's no hover, so we listen for &lt;code&gt;touchstart&lt;/code&gt; instead. The moment a finger touches a link, we fire the prefetch. Given that touch-to-tap typically takes 80–150ms, this gives us a meaningful head start.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;p&gt;In testing across several stores, this shaves 200–400ms off perceived navigation time. Google's research puts 100ms as the threshold humans perceive as "instant" — we're not magic, but closing the gap noticeably improves how snappy a store feels.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shopify constraint challenge
&lt;/h2&gt;

&lt;p&gt;Building for Shopify is interesting because you can't modify the theme directly from an app — everything has to be injected via script tags through the App Bridge / ScriptTag API. That forced me to keep the implementation entirely self-contained with zero dependencies, no global namespace pollution, and graceful degradation if the browser doesn't support the Prefetch API.&lt;/p&gt;

&lt;p&gt;The hardest design decision was figuring out &lt;em&gt;when not to prefetch&lt;/em&gt;. Being too aggressive causes a spike in server requests and bandwidth consumption that can hurt slow-connection users. The threshold tuning (65ms delay, connection checks, same-origin filtering) took the most iteration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you run a Shopify store and care about performance, the app is free to install: &lt;a href="https://apps.shopify.com/prefetch" rel="noopener noreferrer"&gt;Prefetch on the Shopify App Store&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer any technical questions in the comments — particularly around the Shopify scripting constraints or the prefetch threshold tuning.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
