<?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: kvetoslavnovak</title>
    <description>The latest articles on DEV Community by kvetoslavnovak (@kvetoslavnovak).</description>
    <link>https://dev.to/kvetoslavnovak</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%2F544080%2Fdced91ad-b5ad-422f-80c2-86461766f76a.jpg</url>
      <title>DEV Community: kvetoslavnovak</title>
      <link>https://dev.to/kvetoslavnovak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kvetoslavnovak"/>
    <language>en</language>
    <item>
      <title>Self-hosting SvelteKit app - the easy way</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Sat, 03 Jan 2026 13:55:59 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/self-hosting-sveltekit-app-the-easy-way-2g1d</link>
      <guid>https://dev.to/kvetoslavnovak/self-hosting-sveltekit-app-the-easy-way-2g1d</guid>
      <description>&lt;p&gt;This is a follow-up to my post &lt;a href="https://dev.to/kvetoslavnovak/why-we-left-vercel-and-switched-to-self-hosting-1k65"&gt;Why We Left Vercel and Switched to Self-Hosting&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Self-hosting?
&lt;/h2&gt;

&lt;p&gt;SvelteKit is great. Almost every tutorial advises you to use Vercel to deploy and host your app. Vercel is the most convenient way for SvelteKit app, but this also comes with some cons. The main issue is that the pricing scheme may be unpredictable and with growing traffic, your expenses will go up as well.&lt;/p&gt;

&lt;p&gt;The solution may be to "rent" a server (or rather a virtual server, aka a VPS - Virtual Private Server). In this case, you pay just a fixed payment. VPSs are actually super cheap and you can get a decent server for less than $5 monthly.&lt;/p&gt;

&lt;p&gt;But it's up to you to set up the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing your VPS
&lt;/h2&gt;

&lt;p&gt;There are thousands of providers offering affordable VPS - local ones as well as global ones. The biggest ones are Hetzner, Hostinger, DigitalOcean, Vultr, or OVHcloud. It is up to you which one to choose.&lt;/p&gt;

&lt;p&gt;VPS providers usually have nice, user-friendly interfaces where you can choose the location of the server and the operating system. I recommend a Linux operating system such as Ubuntu. During this process, it is better not to choose SSH key access, but rather access via username and password. After renting a VPS, you will be provided with an IP address and a password to be able to connect to your VPS. Generally, VPS providers won't give you a username; in that case, the username is "root" for a VPS with a Linux operating system or "Administrator" for a VPS with a Windows operating system.&lt;/p&gt;

&lt;p&gt;On your computer, just open the terminal. In the terminal, type &lt;code&gt;ssh your_username@your_vps_ip_address&lt;/code&gt; and press Enter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;ssh root@123.45.67.89
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be prompted to enter the password you were given by the VPS provider. Type your VPS password (it won't show as you type) and press Enter.&lt;/p&gt;

&lt;p&gt;You will be prompted about an unknown key and asked to accept it. Type &lt;code&gt;yes&lt;/code&gt; and press Enter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;The authenticity of host '123.45.67.89 (123.45.67.89)' can't be established.
ED25519 key fingerprint is SHA256:NTw36MQjDxsHlxC/Xso5yKMlKJu93uYknRx2LEaqk7I.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will store the fingerprint of the VPS on your computer so that the next time you connect, it is going to validate that fingerprint and you should not see this prompt ever again.&lt;/p&gt;

&lt;p&gt;And now you should be connected to your VPS. This means that in your terminal, you are actually logged in and using the VPS itself. &lt;/p&gt;

&lt;h2&gt;
  
  
  Dokploy
&lt;/h2&gt;

&lt;p&gt;There are several tools that will help you to run applications on your VPS. The most popular ones are Coolify, Dokploy and Caprover. I recommend &lt;a href="https://dokploy.com/" rel="noopener noreferrer"&gt;Dokploy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The installation is super simple. When logged in to your VPS, type this and hit Enter in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;curl -sSL https://dokploy.com/install.sh | sh
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything went okay, you will be given a link where the Dokploy app is available on your VPS. Ctrl-click the link and you will be redirected to the Dokploy registration page. In the browser address bar, you will see that you are on your own server and that you are using the HTTP protocol.&lt;/p&gt;

&lt;p&gt;Provide the email and password you wish to use and hit Register.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmqeduvg03on5u9h9swv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmqeduvg03on5u9h9swv.png" alt=" " width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup HTTPS Domain for Dokploy
&lt;/h2&gt;

&lt;p&gt;I guess you would like to share your app with a proper domain name instead of an IP address. So, I assume you have bought a nice domain name. Go to the website of your domain provider and edit the DNS records like this:&lt;br&gt;
Type: A&lt;br&gt;
Host: dokployadmin&lt;br&gt;
Value: [your VPS IP address]&lt;/p&gt;

&lt;p&gt;You will have to wait a couple of minutes until the DNS record changes propagate.&lt;/p&gt;

&lt;p&gt;Go back to your Dokploy user interface, go to Settings &amp;gt; Web Server &amp;gt; Server Domain and enter:&lt;/p&gt;

&lt;p&gt;Domain: dokployadmin.[YOURDOMAINNAME e.g. superapp.com]&lt;br&gt;
Let's Encrypt Email: [YOUR EMAIL]&lt;br&gt;
Enable HTTPS: [Checked]&lt;br&gt;
Certificate Provider: Let's Encrypt&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foya48xmxx8tpb4tyb61e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foya48xmxx8tpb4tyb61e.png" alt=" " width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are providing your email here to be notified via email when your SSL certificate is about to expire.&lt;/p&gt;

&lt;p&gt;Now, after a minute or so, if you go to the link &lt;code&gt;https://dokployadmin.YOURDOMAINNAME&lt;/code&gt; (e.g., &lt;code&gt;https://dokployadmin.superapp.com&lt;/code&gt;), you should see the Dokploy sign-in page running on HTTPS.&lt;/p&gt;

&lt;p&gt;I would advise changing your Dokploy password now in the Account &amp;gt; Profile section. Before HTTPS was set up, there was a chance that someone listened in on your communication over HTTP.&lt;/p&gt;

&lt;p&gt;Now we can also safely deploy our SvelteKit app and add environment variables (secerts) if these are needed.&lt;/p&gt;
&lt;h2&gt;
  
  
  SvelteKit app changes
&lt;/h2&gt;

&lt;p&gt;Dokploy offers several build types to serve applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;li&gt;Railpack&lt;/li&gt;
&lt;li&gt;Nixpacks&lt;/li&gt;
&lt;li&gt;Heroku Buildpacks&lt;/li&gt;
&lt;li&gt;Paketo Buildpacks&lt;/li&gt;
&lt;li&gt;Static&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will use Dockerfile.&lt;/p&gt;

&lt;p&gt;There are just a couple of preparation steps for your SvelteKit app.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;Dockerfile&lt;/code&gt; and &lt;code&gt;.dockerignore&lt;/code&gt; files in the root of your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz06ft3fawgukl33fz0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz06ft3fawgukl33fz0q.png" alt=" " width="661" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;Dockerfile&lt;/code&gt; should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ---------- Build stage ----------
FROM node:22-alpine AS build

WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build

# ---------- Run stage ----------
FROM node:22-alpine AS run

WORKDIR /app

ENV NODE_ENV=production
ENV PORT=3000

COPY --from=build /app/package.json ./
COPY --from=build /app/build ./build
COPY --from=build /app/node_modules ./node_modules

EXPOSE 3000

CMD ["node", "build"]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your &lt;code&gt;.dockerignore&lt;/code&gt; should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Git files
.git
.gitignore
.gitattributes

# Documentation
README.md

# IDE / editor files
.vscode
.editorconfig

# SvelteKit build/cache
.svelte-kit

# Node modules (we install them in Docker)
node_modules

# Local build output (Docker builds from source)
build

# Config files not needed in container
.prettierrc
.eslintrc.cjs
.graphqlrc
.npmrc

# Environment files (secrets)
**/.env

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install adapter-node&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; npm install @sveltejs/adapter-node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your &lt;code&gt;svelte.config.js&lt;/code&gt; file:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sveltejs/adapter-node&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;vitePreprocess&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@sveltejs/vite-plugin-svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;preprocess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vitePreprocess&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;kit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;adapter&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your &lt;code&gt;.env&lt;/code&gt; file for all environment variables that &lt;strong&gt;ARE NOT&lt;/strong&gt; prefixed with &lt;code&gt;PUBLIC_&lt;/code&gt;&lt;br&gt;
Go through all files of your SvelteKit app and update these variable imports and their usage, we won't import them directly but using env object.&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="c1"&gt;// import { PRIVATE_PASSWORD, ..., ... } from '$env/dynamic/private';&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$env/dynamic/private&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="c1"&gt;// usingsecret(PRIVATE_PASSWORD)&lt;/span&gt;
&lt;span class="nf"&gt;usingsecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit these changes to your Github repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  SvelteKit running in Dockploy
&lt;/h2&gt;

&lt;p&gt;In Dokploy, go to Home &amp;gt; Projects &amp;gt; +Create Project. Choose a name and description. Now we need to use + Create Service &amp;gt; Application. Provide your application name, app name and description. You should see that your empty application was created. Click on it.&lt;/p&gt;

&lt;p&gt;As a provider, use GitHub; go through the intuitive process to connect this provider. You should see your GitHub account added. Click the install icon and select the repository you need to deploy to Dokploy.&lt;/p&gt;

&lt;p&gt;In the Service section, you should now see that you can select your GitHub account, the repository and the branch. You can also enable the Trigger (automatic redeployment) on pushing changes to your branch (if you want to be super sure, you can also use the Webhook URL from the Dokploy Deployments section and paste it into the GitHub repository Settings &amp;gt; Webhooks).&lt;/p&gt;

&lt;p&gt;Hit Save.&lt;/p&gt;

&lt;p&gt;Lower down in the Build Type section, choose Dockerfile. In the Dockerfile input, type &lt;code&gt;./Dockerfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hit Save.&lt;/p&gt;

&lt;p&gt;In Domains in the top navigation, click Add Domain and fill in:&lt;/p&gt;

&lt;p&gt;Host: &lt;a href="http://www.[YOURDOMAINNAME" rel="noopener noreferrer"&gt;www.[YOURDOMAINNAME&lt;/a&gt; e.g. superapp.com]&lt;br&gt;
Path: /&lt;br&gt;
Internal Path: /&lt;br&gt;
Container Port: 3000&lt;br&gt;
Enable HTTPS with Let's Encrypt: [Checked]&lt;/p&gt;

&lt;p&gt;The last thing we have to do is to go to the Environment section in the top navigation. In Environment Settings as well as Build-time Secrets, add all environment variables that your SvelteKit app uses (which you have in &lt;code&gt;.env&lt;/code&gt; file) like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUBLIC_URL = https://........com
PRIVATE_PASSWORD = FDR885dafdafdsafda..........
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can go back to the General section of the navigation and click the Deploy button.&lt;/p&gt;

&lt;p&gt;And your app should be live!&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed Dockploy tutorials
&lt;/h2&gt;

&lt;p&gt;The Dokploy homepage lists several detailed &lt;a href="https://docs.dokploy.com/docs/core/videos" rel="noopener noreferrer"&gt;video tutorials&lt;/a&gt;, although these are not SvelteKit specific. I especially recommend this one: &lt;a href="https://www.youtube.com/watch?v=ELkPcuO5ebo&amp;amp;list=LL&amp;amp;index=4" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=ELkPcuO5ebo&amp;amp;list=LL&amp;amp;index=4&lt;/a&gt;, which goes really deep.&lt;/p&gt;

&lt;p&gt;Dokploy is a great tool. For example, you can install PostgreSQL, MySQL, MariaDB, MongoDB, or Redis there. Or you can choose from more than 70 pre-configured templates like Supabase, n8n, Java Runtime, PocketBase and many others.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>svelte</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Why We Left Vercel and Switched to Self-Hosting</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Wed, 24 Dec 2025 13:29:33 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/why-we-left-vercel-and-switched-to-self-hosting-1k65</link>
      <guid>https://dev.to/kvetoslavnovak/why-we-left-vercel-and-switched-to-self-hosting-1k65</guid>
      <description>&lt;p&gt;There is a follow-up post &lt;a href="https://dev.to/kvetoslavnovak/self-hosting-sveltekit-app-the-easy-way-2g1d"&gt;Self-hosting SvelteKit app - the easy way&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Humble Beginnings
&lt;/h2&gt;

&lt;p&gt;At the beginning of 2025 we launched &lt;a href="https://www.eurlexa.com/" rel="noopener noreferrer"&gt;Eurlexa&lt;/a&gt;, a user-friendly way to access EU regulations.&lt;/p&gt;

&lt;p&gt;Eurlexa is built with &lt;strong&gt;SvelteKit&lt;/strong&gt;. The developer experience was and is great. Vercel seemed like the obvious choice where to deploy Eurlexa.&lt;/p&gt;

&lt;p&gt;Until it wasn't.&lt;/p&gt;

&lt;p&gt;We started on the Hobby Plan. As traffic grew we upgraded to the Pro Plan. However during the start of this summer we noticed an extreme increase in bots crawling Eurlexa. At first we thought this was great. The application uses SSR (Server-Side Rendering) and every page is prerendered, so we assumed our SEO was finally working. But then the bots went into overdrive. The ones to blame are especially AI bots.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Bots Unleashed
&lt;/h2&gt;

&lt;p&gt;By the end of summer and during the autumn the bot traffic went crazy. We realized that Eurlexa is perfect "food" for AI scrapers. To give you the full picture: on Eurlexa, you can find more than &lt;strong&gt;150,000 EU directives and regulations in all 24 official languages&lt;/strong&gt;. Approximately an EU law has roughly five different versions thanks to amendments. Eurlexa also enables users to generate "track changes" server-side. Consequently the number of accessible pages is massive.&lt;/p&gt;

&lt;p&gt;The default &lt;strong&gt;$20 for the Vercel Pro Plan&lt;/strong&gt; was no longer enough. Because we wanted to keep Eurlexa free for our users we absorbed the extra traffic costs ourselves.&lt;/p&gt;

&lt;p&gt;To be fair Vercel did add tools to fight this. During the summer of 2025, they introduced and consistently improved their &lt;strong&gt;Bot Management tools&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  December Ends the Year (and our Vercel journey)
&lt;/h2&gt;

&lt;p&gt;December brought extreme traffic reaching 100,000 mainly bots visits a day. But what hit us hardest was Vercel’s pricing model. The new Fluid Compute model combined with the traffic surge stressing servers side functions duration led to an extreme increase in costs.&lt;/p&gt;

&lt;p&gt;On the other hand I am incredibly thankful that Vercel also introduced the &lt;strong&gt;Spend Management tool&lt;/strong&gt;. This tool allows developers to set a hard cost cap. If the cap was reached Eurlexa was paused.&lt;/p&gt;

&lt;p&gt;The Spend Management tool literally saved us. We had fortunately set a limit of $40 in advance. When the bots went crazy we began increasing the spend cap by $10 increments. These caps weren't being hit over days, but in a matter of hours.&lt;/p&gt;

&lt;p&gt;When our costs crossed &lt;strong&gt;$100&lt;/strong&gt; in a couple of days we decided it was time for a change. I am terrified to imagine what would have happened without that Spend Management tool; by Christmas a Vercel invoice would have been a very unwelcome gift.&lt;/p&gt;

&lt;h2&gt;
  
  
  VPS to the Rescue
&lt;/h2&gt;

&lt;p&gt;We decided to buy a VPS. They are remarkably affordable. After checking out tools like Dokploy, Coolify, and Caprover. We chose Dokploy. The VPS setup was surprisingly easy.&lt;/p&gt;

&lt;p&gt;Migrating the SvelteKit app was a bit more challenging. Ironically AI helped us write the Dockerfile and solve some issues (I guess IA scraped the solution somewhere). The most complicated part was figuring out how environment variables worked and changing how they are called within SvelteKit on VPS. But within just two days Eurlexa was running on our own VPS.&lt;/p&gt;

&lt;p&gt;We’ve already learned that managing a VPS is a task in itself. The bots are still coming and we’ve already had to restart the app several times.&lt;/p&gt;

&lt;p&gt;However we can sleep much better now. The worst-case scenario now is that our server goes down—but our costs remain fixed. &lt;br&gt;
Not being vendor locked is a plus too.&lt;/p&gt;

&lt;p&gt;Merry Christmas to everyone!&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>svelte</category>
      <category>vercel</category>
    </item>
    <item>
      <title>EU Forces Search Engines Like Google to Share Data</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Fri, 10 Oct 2025 09:02:57 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/eu-forces-search-engines-like-google-to-share-data-2lgn</link>
      <guid>https://dev.to/kvetoslavnovak/eu-forces-search-engines-like-google-to-share-data-2lgn</guid>
      <description>&lt;p&gt;🧠💾 Big news for data geeks, AI engineers, and online data analytics — the EU just opened the door to real search engine data access.&lt;/p&gt;

&lt;p&gt;On October 9, 2025, the EU published Regulation (EU) 2025/2050, a new law that implements the Digital Services Act (DSA) and defines how very large online platforms and search engines (like Google, Bing, etc.) must share data with researchers.&lt;/p&gt;

&lt;p&gt;📘 Read the full regulation: &lt;a href="https://www.eurlexa.com/act/en/32025R2050/present/text" rel="noopener noreferrer"&gt;https://www.eurlexa.com/act/en/32025R2050/present/text&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the first time data analysts and researchers — and potentially startups collaborating with them — can legally access search and platform-level data under EU oversight.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Why it matters
&lt;/h2&gt;

&lt;p&gt;Until now, large-scale search data has been locked behind corporate APIs and NDAs. With this regulation, vetted access could enable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI model training on real-world user behavior (ethically and legally)&lt;/li&gt;
&lt;li&gt;Search transparency tools — analyzing bias, misinformation, or ranking algorithms&lt;/li&gt;
&lt;li&gt;Market insights for digital competition and innovation&lt;/li&gt;
&lt;li&gt;Privacy-preserving data engineering solutions and new compliance tech&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 Opportunities ahead
&lt;/h2&gt;

&lt;p&gt;This could be a massive opportunity for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data platform startups offering DSA-compliant research interfaces&lt;/li&gt;
&lt;li&gt;Privacy &amp;amp; security tools enabling safe data sharing&lt;/li&gt;
&lt;li&gt;Analytics frameworks for handling this scale of regulated access&lt;/li&gt;
&lt;li&gt;Academic–industry collaborations that were previously impossible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Europe is effectively opening a new data economy layer — one focused on transparency, research, and accountability.&lt;/p&gt;

</description>
      <category>news</category>
      <category>analytics</category>
      <category>datascience</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Lies about the European Accessibility Act</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Sun, 15 Jun 2025 08:46:52 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/lies-about-the-european-accessibility-act-3p1p</link>
      <guid>https://dev.to/kvetoslavnovak/lies-about-the-european-accessibility-act-3p1p</guid>
      <description>&lt;p&gt;You might be scared of some recent articles and posts stating that on June 28, 2025 the European Accessibility Act aka EAA shall be applicable to all websites and software.&lt;/p&gt;

&lt;p&gt;This is simply not true.&lt;/p&gt;

&lt;p&gt;Read the article in matter for yourself &lt;a href="https://www.eurlexa.com/act/en/32019L0882/present/text#Article-2-Scope" rel="noopener noreferrer"&gt;Article 2 Scope&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The true scope of the EAA&lt;/strong&gt;&lt;br&gt;
The EAA has very broad scope. From approaches to buildings, use of toilets and sanitary facilities to manufacturing and the EU declaration of conformity.&lt;/p&gt;

&lt;p&gt;The EAA is a directive. This means there are no direct effects on EU citizens and businesses. EU member states adopt and publish the laws, regulations and administrative provisions necessary to comply with this Directive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How EAA affects IT&lt;/strong&gt;&lt;br&gt;
The EAA applies to the following products placed on the market after 28 June 2025:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a) consumer general purpose computer hardware systems and operating systems for those hardware systems;&lt;/li&gt;
&lt;li&gt;b) the following self-service terminals:

&lt;ul&gt;
&lt;li&gt;i) payment terminals;&lt;/li&gt;
&lt;li&gt;ii) the following self-service terminals dedicated to the provision of services covered by this Directive:

&lt;ul&gt;
&lt;li&gt;automated teller machines;&lt;/li&gt;
&lt;li&gt;ticketing machines;&lt;/li&gt;
&lt;li&gt;check-in machines;&lt;/li&gt;
&lt;li&gt;interactive self-service terminals providing information, excluding terminals installed as integrated parts of vehicles, aircrafts, ships or rolling stock;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;c) consumer terminal equipment with interactive computing capability, used for electronic communications services;&lt;/li&gt;

&lt;li&gt;d) consumer terminal equipment with interactive computing capability, used for accessing audiovisual media services; and&lt;/li&gt;

&lt;li&gt;e) e-readers.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Without prejudice to Article 32, the EAA  applies to the following services provided to consumers after 28 June 2025:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a) electronic communications services with the exception of transmission services used for the provision of machine-to-machine services;&lt;/li&gt;
&lt;li&gt;b) services providing access to audiovisual media services;&lt;/li&gt;
&lt;li&gt;c) the following elements of &lt;strong&gt;air, bus, rail and waterborne passenger transport services, except for urban, suburban and regional transport services for which only the elements under point v) apply&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;i) websites;&lt;/li&gt;
&lt;li&gt;ii) mobile device-based services including mobile applications;&lt;/li&gt;
&lt;li&gt;iii) electronic tickets and electronic ticketing services;&lt;/li&gt;
&lt;li&gt;iv) delivery of transport service information, including real-time travel information; this shall, with regard to information screens, be limited to interactive screens located within the territory of the Union; and&lt;/li&gt;
&lt;li&gt;v) interactive self-service terminals located within the territory of the Union, except those installed as integrated parts of vehicles, aircrafts, ships and rolling stock used in the provision of any part of such passenger transport services;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;d) consumer banking services;&lt;/li&gt;

&lt;li&gt;e) e-books and dedicated software; and&lt;/li&gt;

&lt;li&gt;f) &lt;strong&gt;e-commerce services&lt;/strong&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The EAA applies to answering emergency communications to the single European emergency number "112".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Are you air, bus, rail and waterborne passenger transport services provider? &lt;/p&gt;

&lt;p&gt;Are you selling e-books and e-books dedicated software?&lt;/p&gt;

&lt;p&gt;Are you a provider of e-commerce services? Do you maintain any paid subscription website or e-shop?&lt;/p&gt;

&lt;p&gt;If so, this one piece of software, and only this one, is subject to the EAA. Note that the e-commerce services apply to the online sale. &lt;/p&gt;

&lt;p&gt;In all other cases EAA does not apply to IT.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>EU Fines Apple and Meta €700 Million for Breaching the DMA Regulation, Protects Developers' Right to Link Outside the App Store</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Thu, 24 Apr 2025 15:52:11 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/eu-fines-apple-and-meta-eu700-million-in-breach-of-the-digital-markets-act-12p4</link>
      <guid>https://dev.to/kvetoslavnovak/eu-fines-apple-and-meta-eu700-million-in-breach-of-the-digital-markets-act-12p4</guid>
      <description>&lt;p&gt;On Apr 23, 2025 the European Commission found that Apple breached its anti-steering obligation under &lt;a href="https://www.eurlexa.com/act/en/32022R1925/present/text" rel="noopener noreferrer"&gt;the Digital Markets Act&lt;/a&gt; (DMA), and that Meta breached the DMA obligation to give consumers the choice of a service that uses less of their personal data. &lt;/p&gt;

&lt;p&gt;Therefore, the Commission has fined Apple and Meta with €500 million and €200 million respectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Non-compliance decision on Apple's steering terms
&lt;/h2&gt;

&lt;p&gt;Under the DMA, &lt;strong&gt;app developers distributing their apps via Apple's App Store should be able to inform customers, free of charge, of alternative offers outside the App Store&lt;/strong&gt;, steer them to those offers and allow them to make purchases.&lt;/p&gt;

&lt;p&gt;This duty of the gatekeeper to allow developers to link users to alternative purchase options outside the gatekeeper's platform is set out in Article 5(4) of the DMA &lt;a href="https://www.eurlexa.com/act/en/32022R1925/present/text#Article-5-Obligations-for-gatekeepers" rel="noopener noreferrer"&gt;https://www.eurlexa.com/act/en/32022R1925/present/text#Article-5-Obligations-for-gatekeepers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Commission found that Apple fails to comply with this obligation. Due to a number of restrictions imposed by Apple, &lt;strong&gt;app developers cannot fully benefit from the advantages of alternative distribution channels&lt;/strong&gt; outside the App Store. &lt;/p&gt;

&lt;p&gt;Similarly, consumers cannot fully benefit from alternative and cheaper offers as Apple prevents app developers from directly informing consumers of such offers. &lt;/p&gt;

&lt;h2&gt;
  
  
  Non-compliance decision on Meta's “consent or pay” model
&lt;/h2&gt;

&lt;p&gt;Under the DMA, gatekeepers must seek users' consent for combining their personal data between services. Those users who do not consent must have access to a less personalised but equivalent alternative.&lt;/p&gt;

&lt;p&gt;In November 2023, Meta introduced a binary &lt;em&gt;Consent or Pay&lt;/em&gt; advertising model. Under this model, EU users of Facebook and Instagram had a choice between consenting to personal data combination for personalised advertising or &lt;strong&gt;paying a monthly subscription for an ad-free service&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Commission found that this model is not compliant with the DMA, as it did not give users the required specific choice to opt for a service that uses less of their personal data but is otherwise equivalent to the ‘personalised ads' service. &lt;strong&gt;Meta's model also did not allow users to exercise their right to freely consent to the combination of their personal data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The duty of the gatekeeper to provide users with a less personalized but equivalent alternative if they refuse data processing consent is set out in Article 5(2) of the DMA &lt;a href="https://www.eurlexa.com/act/en/32022R1925/present/text#Article-5-Obligations-for-gatekeepers" rel="noopener noreferrer"&gt;https://www.eurlexa.com/act/en/32022R1925/present/text#Article-5-Obligations-for-gatekeepers&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>EU Crypto Implementing Regulations Package Released</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Fri, 14 Feb 2025 07:58:04 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/eu-crypto-implementing-regulations-package-released-2ebf</link>
      <guid>https://dev.to/kvetoslavnovak/eu-crypto-implementing-regulations-package-released-2ebf</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Important Update for Crypto Businesses in the EU 🇪🇺
&lt;/h1&gt;

&lt;p&gt;If you're involved in crypto and your activities or business relate to the EU, you may find this useful:&lt;br&gt;&lt;br&gt;
The &lt;strong&gt;European Union&lt;/strong&gt; has just published a significant package of &lt;strong&gt;implementing regulations&lt;/strong&gt;. These cover key aspects of &lt;strong&gt;crypto-asset services, complaint handling, and regulatory procedures&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Here’s a breakdown of the newly released &lt;strong&gt;Commission Delegated Regulations&lt;/strong&gt; under the &lt;strong&gt;Markets in Crypto-Assets Regulation (MiCA):&lt;/strong&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Handling of complaints related to asset-referenced tokens
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.eurlexa.com/act/en/32025R0293/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2025/293&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Handling of complaints by crypto-asset service providers
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.eurlexa.com/act/en/32025R0294/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2025/294&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Procedure for the approval of a crypto-asset white paper
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.eurlexa.com/act/en/32025R0296/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2025/296&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Conditions for the establishment and functioning of consultative supervisory colleges
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.eurlexa.com/act/en/32025R0297/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2025/297&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Methodology for estimating the number and value of transactions using asset-referenced and e-money tokens
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.eurlexa.com/act/en/32025R0298/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2025/298&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔹 Continuity and regularity in the performance of crypto-asset services
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.eurlexa.com/act/en/32025R0299/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2025/299&lt;/a&gt;  &lt;/p&gt;




&lt;p&gt;📌 If you're operating in the &lt;strong&gt;crypto space in the EU&lt;/strong&gt;, it’s worth reviewing these regulations to stay compliant. 🚨&lt;br&gt;&lt;br&gt;
I guess the most significant one is the &lt;strong&gt;regulation on the approval of a crypto-asset white paper&lt;/strong&gt;, as it directly impacts new token issuances and market transparency.  &lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;What are your thoughts on these updates?&lt;/strong&gt; Let’s discuss in the comments! 👇  &lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>tokens</category>
      <category>bitcoin</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>ICT Security in EU - DORA Delegated Regulation on Oversight Was Published</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Fri, 14 Feb 2025 07:33:52 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/ict-security-in-eu-dora-delegated-regulation-on-oversight-was-published-31je</link>
      <guid>https://dev.to/kvetoslavnovak/ict-security-in-eu-dora-delegated-regulation-on-oversight-was-published-31je</guid>
      <description>&lt;p&gt;Anyone into information and communication technology (ICT) security be aware that #DORA delegated Regulation 2025/295 on harmonisation of conditions enabling the conduct of the oversight activities was officialy published in EU on February 13, 2025. &lt;/p&gt;

&lt;p&gt;The Regulation can be found here &lt;a href="https://www.eurlexa.com/act/en/32025R0295/present/text" rel="noopener noreferrer"&gt;https://www.eurlexa.com/act/en/32025R0295/present/text&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ict</category>
      <category>security</category>
    </item>
    <item>
      <title>EU Drops the Hammer: MiCA Crypto Regulations Now in Full Force in 2025</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Fri, 10 Jan 2025 09:43:12 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/eu-drops-the-hammer-mica-crypto-regulations-now-in-full-force-in-2025-4e5d</link>
      <guid>https://dev.to/kvetoslavnovak/eu-drops-the-hammer-mica-crypto-regulations-now-in-full-force-in-2025-4e5d</guid>
      <description>&lt;p&gt;Do you have or use crypto? Are you providing crypto services? If so, in 2025, you need to be very careful, especially if you or your clients or investors are from the European Union.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;As of January 2025, all crypto-asset service providers will need to begin applying for licenses to operate under MiCA in EU.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MiCA Latest Version
&lt;/h2&gt;

&lt;p&gt;On December 30, 2024, the EU Crypto Regulation known as MiCA came into full effect. The full text of the latest version of MiCA can be found here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32023R1114/present/text" rel="noopener noreferrer"&gt;https://www.eurlexa.com/act/en/32023R1114/present/text&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recent Changes
&lt;/h2&gt;

&lt;p&gt;Interestingly, this is already the second version of MiCA. The initial text can be found &lt;a href="https://www.eurlexa.com/act/en/32023R1114/32023R1114/text" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The main changes are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The EU Commission has been given the power to supplement MiCA by adopting regulatory technical standards in certain areas.&lt;/li&gt;
&lt;li&gt;Issuers, offerors, or persons seeking admission to trading are required to submit inside information to the European Single Access Point (expected to operate from 2030).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can view the specific updates in detail with track changes mode &lt;a href="https://www.eurlexa.com/act/en/32023R1114/02023R1114-20240109/text/diff/32023R1114" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objectives of MiCA
&lt;/h2&gt;

&lt;p&gt;MiCA is a comprehensive framework designed to regulate crypto assets across the EU.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified Regulatory Framework&lt;/strong&gt;: MiCA establishes a single set of rules applicable to all 27 EU member states, replacing the fragmented regulatory landscape that previously existed. 
So far, so good — you won’t need to study crypto rules for each individual EU member state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumer Protection&lt;/strong&gt;: MiCA introduces consumer protection measures, including transparency requirements for issuers of crypto-assets, and obligations for crypto-asset service providers (CASPs) to clearly communicate the risks associated with crypto investments. Given the many unfortunate stories from crypto customers, these protective measures are a much-needed step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market Integrity&lt;/strong&gt;: MiCA aims to strengthen confidence in crypto markets by prohibiting market manipulation and insider trading. This is a fair addition, similar to regulations in traditional capital markets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Provisions
&lt;/h2&gt;

&lt;p&gt;Now comes the tricky part for crypto in the EU.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Licensing Requirements&lt;/strong&gt;: All CASPs must obtain authorization from national competent authorities to operate within the EU. This includes having at least one director based in the EU and maintaining a registered office there. Competent authorities are typically financial market regulators, not IT experts, making it difficult to predict how stringent the rulings will be. It’s also possible that we may see "licence shopping" — CASPs choosing the most favorable EU regulator. More details on application to provide crypto-asset services are here &lt;a href="https://www.eurlexa.com/act/en/32023R1114/present/text#Article-62-Application-for-authorisation-as-a-crypto-asset-service-provider" rel="noopener noreferrer"&gt;https://www.eurlexa.com/act/en/32023R1114/present/text#Article-62-Application-for-authorisation-as-a-crypto-asset-service-provider&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regulatory Oversight&lt;/strong&gt;: The European Securities and Markets Authority (ESMA) will oversee significant CASPs — those with more than 15 million active users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issuers' Obligations&lt;/strong&gt;: Issuers of asset-referenced tokens (ARTs) and electronic money tokens (EMTs) must prepare detailed whitepapers outlining their offerings, including risks and terms of investment. More details describing content and form of the crypto-asset white paper are here &lt;a href="https://www.eurlexa.com/act/en/32023R1114/present/text#Article-6-Content-and-form-of-the-crypto-asset-white-paper" rel="noopener noreferrer"&gt;https://www.eurlexa.com/act/en/32023R1114/present/text#Article-6-Content-and-form-of-the-crypto-asset-white-paper&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-Money Laundering (AML)&lt;/strong&gt;: All CASPs are required to implement strong AML policies to ensure compliance with EU financial service standards. This was, of course, expected, especially in light of sanctions imposed on Russia.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Licensing and Transitional Period
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;As of January 1, 2025, all CASPs will need to begin applying for licenses to operate under MiCA in EU.&lt;/strong&gt; Here are the key details regarding the transitional provisions and licensing process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transitional Period&lt;/strong&gt;: Existing virtual asset service providers (VASPs) — the more commonly used term outside the EU for crypto providers — can continue to operate under their current national licenses until December 31, 2025. In some countries, this transitional period may be extended until July 1, 2026. This allows VASPs time to apply for a MiCA CASP license while still providing services legally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License Application Submission&lt;/strong&gt;: From January 1, 2025, companies must submit their applications for a MiCA CASP license. However, they could have begun preparing and submitting applications as early as April 22, 2024, for pre-examination by local authorities, although formal authorization cannot be granted until MiCA comes into effect on December 30, 2024.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Process&lt;/strong&gt;: Submitting a license application is necessary but not sufficient on its own. The application must be complete and meet all regulatory requirements. The review process typically takes around 40 working days, but it can take longer if additional information is requested or if the application is complex.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continued Operation During Application&lt;/strong&gt;: While existing VASPs can operate under their current licenses during the transition period, they must ensure that they submit their CASP license applications before the end of this period to avoid interruptions in service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, existing providers have until the end of 2025 to transition to a MiCA CASP license while continuing their operations, provided they apply for the new license in a timely manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Regulations
&lt;/h2&gt;

&lt;p&gt;Welcome to the EU bureaucracy! Below is a comprehensive list of all EU regulations that supplement or implement MiCA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R1503/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2024/1503 of 22 February 2024 supplementing Regulation (EU) 2023/1114 of the European Parliament and of the Council by specifying the fees charged by the European Banking Authority to issuers of significant asset-referenced tokens and issuers of significant e-money tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R1504/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2024/1504 of 22 February 2024 supplementing Regulation (EU) 2023/1114 of the European Parliament and of the Council by specifying the procedural rules for the exercise of the power to impose fines or periodic penalty payments by the European Banking Authority on issuers of significant asset-referenced tokens and issuers of significant e-money tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.eurlexa.com/act/en/32024R1506/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2024/1506 of 22 February 2024 supplementing Regulation (EU) 2023/1114 of the European Parliament and of the Council by specifying certain criteria for classifying asset-referenced tokens and e-money tokens as significant&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R1507/present/text" rel="noopener noreferrer"&gt;Commission Delegated Regulation (EU) 2024/1507 of 22 February 2024 supplementing Regulation (EU) 2023/1114 of the European Parliament and of the Council by specifying the criteria and factors to be taken into account by the European Securities Markets Authority, the European Banking Authority and competent authorities in relation to their intervention powers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R2494/present/text" rel="noopener noreferrer"&gt;Commission Implementing Regulation (EU) 2024/2494 of 24 September 2024 laying down implementing technical standards for the application of Regulation (EU) 2023/1114 of the European Parliament and of the Council with regard to standard forms, templates and procedures for the cooperation and exchange of information between competent authorities and EBA and ESMA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R2545/present/text" rel="noopener noreferrer"&gt;Commission Implementing Regulation (EU) 2024/2545 of 24 September 2024 laying down implementing technical standards for the application of Regulation (EU) 2023/1114 of the European Parliament and of the Council with regard to standard forms, templates and procedures for the cooperation and exchange of information between competent authorities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R2861/present/text" rel="noopener noreferrer"&gt;Commission Implementing Regulation (EU) 2024/2861 of 12 November 2024 laying down implementing technical standards for the application of Regulation (EU) 2023/1114 of the European Parliament and of the Council with regard to the technical means for the appropriate public disclosure of inside information and for delaying the public disclosure of that information&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R2902/present/text" rel="noopener noreferrer"&gt;Commission Implementing Regulation (EU) 2024/2902 of 20 November 2024 laying down implementing technical standards for the application of Regulation (EU) 2023/1114 of the European Parliament and of the Council with regard to reporting related to asset-referenced tokens and to e-money tokens denominated in a currency that is not an official currency of a Member State&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eurlexa.com/act/en/32024R2984/present/text" rel="noopener noreferrer"&gt;Commission Implementing Regulation (EU) 2024/2984 of 29 November 2024 laying down implementing technical standards for the application of Regulation (EU) 2023/1114 of the European Parliament and of the Council with regard to forms, formats and templates for the crypto-asset white papers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, MiCA aims to create one transparent environment for crypto assets within the EU. As the regulation comes into full effect in 2025, it will significantly shape how crypto-asset service providers operate in Europe, hopefully fostering innovation while ensuring accountability within the market.&lt;/p&gt;

&lt;p&gt;Disclosure: I am a member of &lt;a href="https://www.eurlexa.com/" rel="noopener noreferrer"&gt;eurlexa&lt;/a&gt; team. On Eurlexa you can access and search EU regulations and directives with ease. Eurlexa is a mobile-optimized, user-friendly alternative to EU offical and rather cumbersome EUR-Lex.&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>bitcoin</category>
      <category>law</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>🇪🇺 8 EU Regulations Every Developer Must Know ⚖️💻</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Thu, 12 Dec 2024 15:09:21 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/key-eu-directives-and-regulations-in-it-web-developmentm-ai-and-data-protection-4pn5</link>
      <guid>https://dev.to/kvetoslavnovak/key-eu-directives-and-regulations-in-it-web-developmentm-ai-and-data-protection-4pn5</guid>
      <description>&lt;p&gt;Recently, I was involved in coverage of specific rules and regulations that web pages or applications in the EU must adhere to. I thought it might be interesting for others as well to know the most important EU legal rules for IT and web developers.&lt;/p&gt;

&lt;p&gt;Sometimes these Directives and Regulations sets only the basic framework and have many implementing technical regulations as you can learn bellow.&lt;/p&gt;

&lt;p&gt;The most important EU regulations and directives that may affect development are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Directive on Privacy and Electronic Communications &lt;/li&gt;
&lt;li&gt;General Data Protection Regulation&lt;/li&gt;
&lt;li&gt;Artificial Intelligence Act&lt;/li&gt;
&lt;li&gt;Digital Services Act&lt;/li&gt;
&lt;li&gt;Digital Markets Act&lt;/li&gt;
&lt;li&gt;Cyber Resilience Act&lt;/li&gt;
&lt;li&gt;Directive on Measures for a High Common Level of Cybersecurity&lt;/li&gt;
&lt;li&gt;Regulation on Digital Operational Resilience&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Directive on Privacy and Electronic Communications
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32002L0058/present/text" rel="noopener noreferrer"&gt;Cookie Directive&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32002L0058/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32002L0058/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32002L0058/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Directive 2002/58/EC of the European Parliament and of the Council of 12 July 2002 concerning the processing of personal data and the protection of privacy in the electronic communications sector (Directive on privacy and electronic communications)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;Cookie Directive&lt;/em&gt;, &lt;em&gt;ePrivacy Directive&lt;/em&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any service that uses cookies (other than strictly necessary cookies) or similar tracking technologies, and companies providing electronic communications services&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cookies other than strictly necessary ones stored on a user’s device require the user's consent&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  General Data Protection Regulation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32016R0679/present/text" rel="noopener noreferrer"&gt;GDPR&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32016R0679/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32016R0679/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32016R0679/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016 on the protection of natural persons with regard to the processing of personal data and on the free movement of such data, and repealing Directive 95/46/EC (General Data Protection Regulation)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;GDPR&lt;/em&gt;, &lt;em&gt;Data Protection Regulation&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anyone who collects or processes personal data, regardless of their form, size, or sector&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cases when you send personal data outside the EU (this may include the full user IP address to Google, Vercel, etc.)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Artificial Intelligence Act
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32024R1689/present/text" rel="noopener noreferrer"&gt;AI Act&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32024R1689/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32024R1689/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32024R1689/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Regulation (EU) 2024/1689 of the European Parliament and of the Council of 13 June 2024 laying down harmonised rules on artificial intelligence and amending Regulations (EC) No 300/2008, (EU) No 167/2013, (EU) No 168/2013, (EU) 2018/858, (EU) 2018/1139 and (EU) 2019/2144 and Directives 2014/90/EU, (EU) 2016/797 and (EU) 2020/1828 (Artificial Intelligence Act)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;AI Act&lt;/em&gt;, &lt;em&gt;Artificial Intelligence Act&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers or providers of AI systems, especially those classified as high-risk or unacceptable risk&lt;/li&gt;
&lt;li&gt;Companies across various sectors that utilize AI technologies for decision-making, customer interaction, or operational efficiency &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Severe penalties for non-compliance, including fines up to €35 million or 7% of global annual turnover&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Digital Services Act
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32022R2065/present/text" rel="noopener noreferrer"&gt;DSA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32022R2065/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32022R2065/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32022R2065/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Regulation (EU) 2022/2065 of the European Parliament and of the Council of 19 October 2022 on a Single Market For Digital Services and amending Directive 2000/31/EC (Digital Services Act)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;DSA&lt;/em&gt;, &lt;em&gt;DSA Regulation&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Online platforms and very large online platforms (VLOPs)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FAANG (Facebook, Amazon, Apple, Netflix, Google) or MAMAA (Meta, Apple, Microsoft, Amazon, Alphabet)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Digital Markets Act
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32022R1925/present/text" rel="noopener noreferrer"&gt;DMA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32022R1925/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32022R1925/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32022R1925/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Regulation (EU) 2022/1925 of the European Parliament and of the Council of 14 September 2022 on contestable and fair markets in the digital sector and amending Directives (EU) 2019/1937 and (EU) 2020/1828 (Digital Markets Act)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;DMA&lt;/em&gt;, &lt;em&gt;DMA Regulation&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gatekeeper platforms&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alphabet (Google), Amazon, Apple, ByteDance (TikTok), Meta (Facebook) and Microsoft&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cyber Resilience Act
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32024R2847/present/text" rel="noopener noreferrer"&gt;CRA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32024R2847/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32024R2847/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32024R2847/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Regulation (EU) 2024/2847 of the European Parliament and of the Council of 23 October 2024 on horizontal cybersecurity requirements for products with digital elements and amending Regulations (EU) No 168/2013 and (EU) 2019/1020 and Directive (EU) 2020/1828 (Cyber Resilience Act)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;CRA&lt;/em&gt;, &lt;em&gt;CRA Directive&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;manufacturers, importers and distributors of products with digital elements having data connection to a device or network&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Organizations involved in developing open-source software intended for commercial use must implement cybersecurity policies and procedures as well&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Directive on Measures for a High Common Level of Cybersecurity
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32022L2555/present/text" rel="noopener noreferrer"&gt;NIS 2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32022L2555/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32022L2555/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32022L2555/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Directive (EU) 2022/2555 of the European Parliament and of the Council of 14 December 2022 on measures for a high common level of cybersecurity across the Union, amending Regulation (EU) No 910/2014 and Directive (EU) 2018/1972, and repealing Directive (EU) 2016/1148 (NIS 2 Directive)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;NIS 2&lt;/em&gt;, &lt;em&gt;NIS 2 Directive&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Companies in essential sectors such as energy, transport, healthcare, cloud computing services, internet service providers (ISPs), financial services, food production and distribution, chemicals production&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Organizations must report significant incidents not only to national authorities but also to affected service recipients without undue delay&lt;/li&gt;
&lt;li&gt;entities are required to assess the cybersecurity posture of their suppliers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Regulation on Digital Operational Resilience
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Current consolidated version: &lt;a href="https://www.eurlexa.com/act/en/32022R2554/present/text" rel="noopener noreferrer"&gt;DORA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Implementing regulations: &lt;a href="https://www.eurlexa.com/act/en/32022R2554/present/info#all-based-on" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Judicial precedents: &lt;a href="https://www.eurlexa.com/act/en/32022R2554/present/info#affected-by-case" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amendments and corrections: &lt;a href="https://www.eurlexa.com/act/en/32022R2554/present/timeline" rel="noopener noreferrer"&gt;link&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full title: &lt;em&gt;Regulation (EU) 2022/2554 of the European Parliament and of the Council of 14 December 2022 on digital operational resilience for the financial sector and amending Regulations (EC) No 1060/2009, (EU) No 648/2012, (EU) No 600/2014, (EU) No 909/2014 and (EU) 2016/1011&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also known as: &lt;em&gt;DORA&lt;/em&gt;, &lt;em&gt;DORA Regulation&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Who should be concerned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Financial Institutions and their IT services providers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Financial institutions must establish rigorous oversight mechanisms and ensure that their vendors comply with DORA&lt;/li&gt;
&lt;li&gt;Financial institutions have to report their key IT vendros to regulators&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;So, if you are asked to deliver IT services to a financial institution in the EU, and the project includes AI models for customers' payment terminals data, including an accompanying web app and phone app, as well as servers and database hosted outside of the EU, God bless you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>PostgreSQL Full Text Search Rank by Position</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Sat, 30 Nov 2024 10:17:07 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/postgresql-full-text-search-rank-by-position-3ioj</link>
      <guid>https://dev.to/kvetoslavnovak/postgresql-full-text-search-rank-by-position-3ioj</guid>
      <description>&lt;p&gt;Recently, I encountered a problem with full-text search. I am using this feature in my search input, where the backend sends hints of possible matches as you type. The backend database is PostgreSQL. I needed the hints to be ranked by the position of the searched term in the text.&lt;/p&gt;

&lt;p&gt;So if you search for "Star Wars" title you will get "Star Wars" post first instead of "How Star Wars 7- 9 changed the world of Star Wars (a fun made documentary about Star Wars)" which may have higher ranking as the term is there 3 times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full Text Search in PostgreSQL
&lt;/h2&gt;

&lt;p&gt;Full-text search in PostgreSQL can be achieved quite easily. There are two main tools to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tsvector - represents a searchable document.&lt;/li&gt;
&lt;li&gt;tsquery - represents the search query to perform against a document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s say we want to search the titles of our blog posts. To make them searchable, we can use the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; 
&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="n"&gt;title&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt; &lt;span class="n"&gt;to_tsvector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we are converting the post titles to a tsvector dynamically with every search. However, this transformation takes some time. A better approach is to perform this transformation in advance in the database and also store it as an indexes for the titles for faster search.&lt;/p&gt;

&lt;p&gt;Lets create a new collumn of vectors of titles and also index this new column:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;search_vector&lt;/span&gt; &lt;span class="n"&gt;tsvector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;search_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_tsvector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;titles_fts_idx&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;gin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_vector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try to search the term "JavaScript"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; 
&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="n"&gt;title&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt; &lt;span class="n"&gt;search_vector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may also make indexes from ts vectors directly on titles column  like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;titles_fts_idx&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to_tsvector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and use the search like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; 
&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="n"&gt;title&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the full-text search will be blazingly fast, completing in milliseconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ranking the Results
&lt;/h2&gt;

&lt;p&gt;PostgreSQL provides the ts_rank feature, which allows you to score search results and order them based on their ranking. PostgreSQL supports the following ranking options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0 (the default) ignores the document length&lt;/li&gt;
&lt;li&gt;1 divides the rank by 1 + the logarithm of the document length&lt;/li&gt;
&lt;li&gt;2 divides the rank by the document length&lt;/li&gt;
&lt;li&gt;4 divides the rank by the mean harmonic distance between extents (this is implemented only by ts_rank_cd)&lt;/li&gt;
&lt;li&gt;8 divides the rank by the number of unique words in document&lt;/li&gt;
&lt;li&gt;16 divides the rank by 1 + the logarithm of the number of unique words in document&lt;/li&gt;
&lt;li&gt;32 divides the rank by itself + 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use the ts_rank like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;ts_rank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;rank_title&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;rank_title&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="n"&gt;NULLS&lt;/span&gt; &lt;span class="k"&gt;LAST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, there is no built-in ranking option based on the position of the search term within the string (i.e. title column).&lt;/p&gt;

&lt;h2&gt;
  
  
  POSITION to the rescue
&lt;/h2&gt;

&lt;p&gt;Fortunatelly there is POSITION function in PostgreSQL. The PostgreSQL POSITION function is used to find the location of a substring within a given string. In our case we can use it like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;ts_rank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="k"&gt;NULLIF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;POSITION&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;rank_title&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="n"&gt;NULLS&lt;/span&gt; &lt;span class="k"&gt;LAST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ts_rank uses normalization integer 2 because 2 divides the rank by the document length &lt;br&gt;
Magic number + 0.0001 is to avoid dividing by the 0 because POSTION function counts from 1 not 0 and returns 0 if the string is not found.&lt;/p&gt;

&lt;p&gt;Final code may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; 
&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;ts_rank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;rank_title&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;blogposts&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'JavaScript'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt; &lt;span class="n"&gt;search_vector&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;rank_title&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="n"&gt;NULLS&lt;/span&gt; &lt;span class="k"&gt;LAST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Searching for more terms
&lt;/h2&gt;

&lt;p&gt;One caveat has to be mentioned if you search for more terms at once (like &lt;em&gt;JavaScript&lt;/em&gt; and &lt;em&gt;TypeScript&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;The arguments for the to_tsquery function may be used with a big fleibility, including logical operators etc. POSITION function on the other hand is "just" a substring in string. &lt;/p&gt;

&lt;h2&gt;
  
  
  Real World Example
&lt;/h2&gt;

&lt;p&gt;Here is my example from real world endpoint in SvelteKit web application which uses postgres (sql) npm library:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../utils/sql.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&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;POST&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;queryTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`'&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &amp;amp; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchingLang&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`fts_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; 
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fts_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt; &lt;span class="s2"&gt;`SELECT 
    id, 
    COALESCE(title-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, title-&amp;gt;&amp;gt;'en') as title,
    ts_rank(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fts&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;queryTerm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, 2) + (1.0 / NULLIF(POSITION(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; IN COALESCE(title-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, title-&amp;gt;&amp;gt;'en')), 0) + 0.0001)  as rank
    FROM notices 
    WHERE &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; @@ to_tsquery('simple', &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;queryTerm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)
    ORDER BY rank DESC NULLS LAST
    LIMIT &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;`&lt;/span&gt;

 &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fts_response&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the links to the documentatio in matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES&lt;/a&gt;
&lt;a href="https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-DOCUMENTS" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-DOCUMENTS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-RANKING&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/9.1/functions-string.html" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/9.1/functions-string.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>postgressql</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>sveltekit</category>
    </item>
    <item>
      <title>"Helper" Varaibles in Svelte 5</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Fri, 08 Nov 2024 15:03:18 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/helper-varaibles-in-svelte-5-5cni</link>
      <guid>https://dev.to/kvetoslavnovak/helper-varaibles-in-svelte-5-5cni</guid>
      <description>&lt;h2&gt;
  
  
  Bye Bye Magical Svelte 4 &lt;code&gt;$:&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Following my recent post &lt;a href="https://dev.to/kvetoslavnovak/experiences-and-caveats-of-svelte-5-migration-27cp"&gt;Experiences and Caveats of Svelte 5 Migration&lt;/a&gt; I would like to highlight some techniques and change of mindset when going from Svelte 4 to Svelte 5.&lt;/p&gt;

&lt;p&gt;Svelte 4 uses "magical" &lt;code&gt;$:&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt; and does all the heavy lifting to make code reactive. We also embraced varaibles reassignment like&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

&lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of methods updating/mutating varaibles like &lt;code&gt;push&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;I was quite suprprised to re-learn good old JS patterns using Svelte 5.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Need to Be Reactive All the Time
&lt;/h2&gt;

&lt;p&gt;And I was also probably quite spoiled by &lt;code&gt;let&lt;/code&gt; in Svelte 4 , no reasoning about reactivity, it was included if needed.  But not all varaibles have to be reactive. Also non reactive variables may be updated in reactive or even "traditional mutating code". The real need for reactive variable is when we use it in UI (when this varaible is rendered in html/page and we need it to update later). &lt;/p&gt;

&lt;p&gt;You may encounter erros in Svelte 5 like &lt;code&gt;Cannot assign to derived state&lt;/code&gt;,  &lt;code&gt;State referenced in its own scope will never update. Did you mean to reference it inside a closure?&lt;/code&gt; or &lt;code&gt;derived_references_self\nA derived value cannot reference itself recursively&lt;/code&gt; if using Svelte 4 coding style.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of Helper Variables
&lt;/h2&gt;

&lt;p&gt;Take a look at this example of Svelte 4 style of code:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;derivedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="nx"&gt;$&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;derivedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;derivedArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&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;on:click=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Generate Random Value&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;value: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;derivedArr: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;derivedArr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://svelte.dev/playground/2c64d0ac90a04aa1bef37322367b2f70?version=5.1.12" rel="noopener noreferrer"&gt;DEMO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The random function works as some kind of simulation of server response sending as a result of a search query, on the client we are accumulating the results, so it work like a "Load more" button. Hereby random function should not be changed. We have two reactive variables and Svelte 4 solves the updates automatically. We only needed to remember that the right way is by reassigning the variable. &lt;/p&gt;

&lt;p&gt;In Svelte 5 we should think a little how to achieve the same result. The two variables we are using are not enough, we need one more, the helper one. &lt;/p&gt;

&lt;p&gt;One way is to use a &lt;code&gt;$derived&lt;/code&gt; rune.&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


                  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;helperArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;   
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;derivedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                     &lt;span class="nx"&gt;helperArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;helperArr&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Generate Random Value&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;value: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;derivedArr: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;derivedArr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://svelte.dev/playground/c61883cad4254f518df1b8dd3104a642?version=5.1.12" rel="noopener noreferrer"&gt;DEMO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am trying visually emphasize which parts of the code are relevant and somehow "wrapped" from Svelte 4 into Svelte 5 mental model. &lt;code&gt;helperArr&lt;/code&gt; is declared outside of a&lt;code&gt;$derived.by()&lt;/code&gt; function scope not to be reseted every time &lt;code&gt;$derived.by()&lt;/code&gt; reruns (which is when reactive variables inside $derived updates). If you know easier way to do this let me know.&lt;/p&gt;

&lt;p&gt;There is also an &lt;code&gt;$effect()&lt;/code&gt; rune way to achieve the same with &lt;code&gt;untrack&lt;/code&gt; trick. It might look even simplier but we should avoid effects if possible (mainly Svetlet 5 effects do not run on the server/SSR).&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;untrack&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;derivedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

    &lt;span class="nx"&gt;$effect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pre&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;untrack&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;derivedArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;random&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Generate Random Value&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;value: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;derivedArr: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;derivedArr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://svelte.dev/playground/90c91a96604f48089aa81dcc2bf8e5fb?version=5.1.13" rel="noopener noreferrer"&gt;DEMO&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Life Example
&lt;/h2&gt;

&lt;p&gt;This is the example how I tried to migrate quite stright forward Svelte 4 page to Svelte 5. It took me a while to rethink the code. This page works as a posts search with a "Load More" functionality (adding results or pagging if a user does not have JS):&lt;/p&gt;

&lt;p&gt;Svelte 4&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="nx"&gt;Icon&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Icon.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;enhance&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$app/forms&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;tick&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;searchingLang&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;previousSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;$&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="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thereIsMore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nl"&gt;$&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="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;)&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;previousSearch&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thereWasMore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="nx"&gt;previousSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&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;intoView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&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;tick&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;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeValue&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrollIntoView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;smooth&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="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ol&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#each&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;use:intoView&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; aria-posinset=&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&amp;gt;
                &lt;span class="c"&gt;&amp;lt;!-- users without javascript have calculated order of results within paggination and css disables standard ol ul numbering --&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- users with javascript have standard ol ul numbering and loading more feature --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;noscript&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;. &lt;span class="nt"&gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/post/{searchingLang}/{item.id}/content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/each&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;

    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thereIsMore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt;
            &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;
            &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"?/search&amp;amp;skip={skip}&amp;amp;thereWasMore={form?.thereIsMore}"&lt;/span&gt;
            &lt;span class="na"&gt;use:enhance&lt;/span&gt;
            &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- Probably we do not need to bind the value as this is hidden input --&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;input name="searchTerm" type="hidden" bind:value={searchTerm} /&amp;gt; --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"searchTerm"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Button to load more search results"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"outline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;Icon&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"loadMore"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;:else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;noResultsFound&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* users without javascript have calculated order of results within paggination and css disables standard ol ul numbering
users with javascript have standard ol ul numbering and loading more feature */&lt;/span&gt;
        &lt;span class="nt"&gt;ol&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;list-style-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Svelte 5&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="nx"&gt;Icon&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Icon.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;enhance&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$app/forms&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;tick&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchingLang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;previousSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thereIsMore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;20&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;helperResultsArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;)&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;previousSearch&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thereWasMore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;helperResultsArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;helperResultsArr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;helperResultsArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
                &lt;span class="nx"&gt;helperResultsArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;previousSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;helperResultsArr&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;else&lt;/span&gt; &lt;span class="k"&gt;return&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;intoView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&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;tick&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;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeValue&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scrollIntoView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;smooth&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="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ol&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#each&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;use:intoView&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; aria-posinset=&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&amp;gt;
                &lt;span class="c"&gt;&amp;lt;!-- users without javascript have calculated order of results within paggination and css disables standard ol ul numbering --&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- users with javascript have standard ol ul numbering and loading more feature --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;noscript&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;. &lt;span class="nt"&gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/post/{searchingLang}/{item.id}/content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/each&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;

    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;thereIsMore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt;
            &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;
            &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"?/search&amp;amp;skip={skip}&amp;amp;thereWasMore={form?.thereIsMore}"&lt;/span&gt;
            &lt;span class="na"&gt;use:enhance&lt;/span&gt;
            &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"searchTerm"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Button to load more search results"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"outline"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;Icon&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"loadMore"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;:else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;searchResultFromAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;noResultsFound&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;/* users without javascript have calculated order of results within paggination and css disables standard ol ul numbering
users with javascript have standard ol ul numbering and loading more feature */&lt;/span&gt;
        &lt;span class="nt"&gt;ol&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;list-style-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all for now. &lt;/p&gt;

&lt;p&gt;PS: Do not hesitate to let me know if you would do the migration in a different way.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>sveltekit</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Experiences and Caveats of Svelte 5 Migration</title>
      <dc:creator>kvetoslavnovak</dc:creator>
      <pubDate>Sun, 03 Nov 2024 10:39:27 +0000</pubDate>
      <link>https://dev.to/kvetoslavnovak/experiences-and-caveats-of-svelte-5-migration-27cp</link>
      <guid>https://dev.to/kvetoslavnovak/experiences-and-caveats-of-svelte-5-migration-27cp</guid>
      <description>&lt;p&gt;I have recently updated a rather complex web application. The application has features like auth, Stripe, i18n, dark/light mode, PWA, etc. Overall, it has around 30 pages and components, with almost no third-party npm packages.&lt;/p&gt;

&lt;p&gt;I would like to point out what I found quite challenging when migrating the app to Svelte 5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-Migration Script Hammer
&lt;/h2&gt;

&lt;p&gt;The auto-migration script provided by Svelte can do the job for you with this "one-liner" command in the terminal &lt;code&gt;npx sv migrate svelte-5&lt;/code&gt; (after you do all the necessary updates and installs: "@sveltejs/vite-plugin-svelte": "^4.0.0" and "svelte": "^5"). But I do not recommend this "hammer" approach. &lt;/p&gt;

&lt;p&gt;Go file by file, component by component with &lt;strong&gt;Ctrl + Shift + P&lt;/strong&gt; (Windows/Linux) / &lt;strong&gt;Shift + Command + P&lt;/strong&gt; (Mac) and use the &lt;code&gt;Migrate Component to Svelte 5 Syntax&lt;/code&gt; command in the VS Code command palette instead. You will have more control that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deprecated run() Surprise
&lt;/h2&gt;

&lt;p&gt;The script cannot perform miracles. Upgrading reactive variable declarations to &lt;code&gt;$state()&lt;/code&gt; is usually fine. However, the script may struggle to detect whether &lt;code&gt;$:&lt;/code&gt; should be converted to &lt;code&gt;$derived()/$derived.by(() =&amp;gt; {})&lt;/code&gt; or &lt;code&gt;$effect(() =&amp;gt; {})&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, guess what? With the auto-migration script, you might end up with lots of &lt;code&gt;run(() =&amp;gt; {})&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example imagine using something like this (this is a very simplified example from real life code just to highhlight the point):&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="p"&gt;...&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;notext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nl"&gt;$&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completeDoc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NoLangVersion&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="nx"&gt;notext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="nl"&gt;$&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completeDoc&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NoLangVersion&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="nx"&gt;notext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;#if&lt;/span&gt; &lt;span class="nx"&gt;notext&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
   &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userPrefferedLang&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;noTextWarning&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
...
&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;/if&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The auto-migration script will give you this:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svelte/legacy&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;notext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;run&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completeDoc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NoLangVersion&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="nx"&gt;notext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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="nf"&gt;run&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completeDoc&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NoLangVersion&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="nx"&gt;notext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with a nice little warning that &lt;strong&gt;the run function is deprecated&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The better Svelte 5 code would be this I guess:&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="p"&gt;...&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;notext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;by&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completeDoc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NoLangVersion&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="k"&gt;return&lt;/span&gt;  &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completeDoc&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NoLangVersion&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason is that the script cannot transform code to &lt;code&gt;$derived.by(() =&amp;gt; {})&lt;/code&gt; easily, so it would use a more dirty approach with &lt;code&gt;$effect()&lt;/code&gt;. But &lt;code&gt;$effect()&lt;/code&gt; runs only client-side, so the script uses the deprecated &lt;code&gt;run&lt;/code&gt; function instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid $effect If You Can
&lt;/h2&gt;

&lt;p&gt;Now we are getting to the most important takeaway. Which is &lt;code&gt;$effect()&lt;/code&gt; running only client-side. So no &lt;code&gt;$effect()&lt;/code&gt; on the server, for prerendering pages and SSR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;$effect()&lt;/code&gt; DOES NOT RUN ON THE SERVER!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This should be really emphasized in the Svelte 5 documentation.&lt;/p&gt;

&lt;p&gt;Look at this two examples:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  // server responds with c == 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;$effect&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;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  // server responds with c == 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They are not the same. This causes a lot of challenges. The client will need to reevaluate the c variable when mounting the page. The page will look different when sent from the server and when finally DOM-rendered on the client (SSR, SEO, flicker issues, etc.).&lt;/p&gt;

&lt;p&gt;So always try to use &lt;code&gt;$derived()&lt;/code&gt; or &lt;code&gt;$derived.by()&lt;/code&gt; over &lt;code&gt;$effect()&lt;/code&gt;. It will save you lots of trouble.&lt;/p&gt;

&lt;p&gt;It's quite the same story as when we were discouraged from using stores server side in SvelteKit.&lt;/p&gt;

&lt;h2&gt;
  
  
  $effect vs onMount() in SvelteKit
&lt;/h2&gt;

&lt;p&gt;You might be tempted to replace your &lt;code&gt;onMount()&lt;/code&gt; with &lt;code&gt;$effect()&lt;/code&gt; thanks to the examples that were given during the arrival of Svelte 5. For the reasons already mentioned, I would discourage this for the time being. onMount is still a core Svelte lifecycle hook.  &lt;/p&gt;

&lt;h2&gt;
  
  
  $bindable $props Surprise
&lt;/h2&gt;

&lt;p&gt;The other nice surprise is that Svelte 5 takes care to have consistent variable values. If you pass a variable as a prop to a component and change this variable in the component later on, the script will try to solve this inconsistency using &lt;code&gt;$bindable $prop&lt;/code&gt;. The parent should be notified about this change, so your app state is consistent.&lt;/p&gt;

&lt;p&gt;Look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;// parent svelte file
&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="nx"&gt;ComponentBinded&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ComponentBinded.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ComponentWithDerived&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ComponentWithDerived.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Wick&lt;/span&gt;&lt;span class="dl"&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;p&amp;gt;&lt;/span&gt;Name value in parent: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;ComponentBinded&lt;/span&gt; &lt;span class="na"&gt;bind:name=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;ComponentWithDerived&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The auto-migration script will want you to use a component with binded value to ensure the parent may get the updated value back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;// ComponentBinded.svelte
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$bindable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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;p&amp;gt;&lt;/span&gt;
Name value in component with binded value: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are mutating the &lt;code&gt;name&lt;/code&gt; varaible in this child component. So we are notifing the parent so. The parent will use this mutated value as well.&lt;/p&gt;

&lt;p&gt;If you do not need the parent to reflect the mutated &lt;code&gt;name&lt;/code&gt; value we can use quite simpler way as well, you guessed it, with &lt;code&gt;$derived()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;// ComponentWithDerived.svelte
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;upperCaseName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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;p&amp;gt;&lt;/span&gt;
Name value in component with derived value: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;upperCaseName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But in this later case we are not mutating &lt;code&gt;name&lt;/code&gt; variable in the component.  &lt;/p&gt;

&lt;h2&gt;
  
  
  :global { } Block
&lt;/h2&gt;

&lt;p&gt;A very nice feature that I found during migration was that we can use CSS &lt;code&gt;:global&lt;/code&gt; with block now. Styling with &lt;code&gt;:global&lt;/code&gt; is quite necessary if you want to style the HTML elements in &lt;code&gt;@html&lt;/code&gt;, for example.&lt;/p&gt;

&lt;p&gt;So instead of this:&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;style&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;#blog&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;#blog&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;#blog&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bolder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;medium&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&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;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can use this:&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;style&amp;gt;&lt;/span&gt;
   &lt;span class="nf"&gt;#blog&lt;/span&gt; &lt;span class="nd"&gt;:global&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;table&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bolder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;medium&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Style as a Prop in Components
&lt;/h2&gt;

&lt;p&gt;In Svelte 4, if you wanted to provide a CSS class as a prop to a component, you would use &lt;code&gt;{$$props.class}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;// Icons Component
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5em&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5em&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;focusable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;path fill="none" d="M0 0h24v24H0V0z"/&amp;gt;&amp;lt;path d="M12 6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2m0 10c2.7 0 5.8 1.29 6 2H6c.23-.72 3.31-2 6-2m0-12C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;user_logged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;path fill="none" d="M0 0h24v24H0z"/&amp;gt;&amp;lt;path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&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;svg&lt;/span&gt;
    &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;$$props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
    &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;focusable&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&amp;gt;
   &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;@html&lt;/span&gt; &lt;span class="nx"&gt;displayIcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Svelte 5 you may use &lt;code&gt;class={className}&lt;/code&gt;:&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="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5em&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.5em&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;focusable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$props&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;path fill="none" d="M0 0h24v24H0V0z"/&amp;gt;&amp;lt;path d="M12 6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2m0 10c2.7 0 5.8 1.29 6 2H6c.23-.72 3.31-2 6-2m0-12C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;user_logged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;path fill="none" d="M0 0h24v24H0z"/&amp;gt;&amp;lt;path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/&amp;gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&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;svg&lt;/span&gt;
    &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;
    &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt;
    &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;focusable&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&amp;gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;@html&lt;/span&gt; &lt;span class="nx"&gt;displayIcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Possible Lighthouse Perfomance Drop
&lt;/h2&gt;

&lt;p&gt;When I used the auto-merging script, I was shocked at how my app's performance dropped. With Svelte 4, I had nearly all 100%s. It was only after I manually migrated and carefully considered "how to" (mainly how to avoid &lt;code&gt;$effect()&lt;/code&gt; if possible) when my Lighthouse scores were back in the green again. &lt;del&gt;And to be honest even after extensive tests the Lighthouse score for the mobile is still worse compared to Svelte 4 version of the app.&lt;/del&gt;  &lt;/p&gt;

&lt;p&gt;EDIT: Svelte 5 seem to have great performace now too. I have updated to the  Svelte 5 latest version and it is now even a little bit faster than Svelte 4. &lt;/p&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;It took longer to migrate to Svelte 5 than I had expected. I still have not pushed this new version to production, though. The updates to Svelte 5 are still coming in with &lt;a href="https://github.com/sveltejs/svelte/releases" rel="noopener noreferrer"&gt;quite high frequency&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope my experience may be useful to others.&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>sveltekit</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
