CINXE.COM
Captain Codeman Blog
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1" /> <link href="./_app/immutable/assets/0.DbjY0eM-.css" rel="stylesheet"><!--[--><link rel="icon" href="https://image.blogserve.co/captaincodeman/icon.ico"> <link rel="icon" href="https://image.blogserve.co/captaincodeman/icon-192x192.png" type="image/png" sizes="192x192"> <link rel="apple-touch-icon" href="https://image.blogserve.co/captaincodeman/icon-192x192.png"> <!--[--><script defer="" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5049499290128209" crossorigin="anonymous"></script><!----><!--]--> <!--[--><script defer="" src="https://www.googletagmanager.com/gtag/js?id=UA-226828-9"></script> <!----><script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-226828-9'); </script><!----><!--]--><!--]--><!--[--><!--[!--><!--]--><!--]--><!--[--><link rel="canonical" href="https://www.captaincodeman.com/undefined"> <meta name="twitter:card" content="summary_large_image"> <!--[--><meta name="twitter:creator" content="CaptainCodeman"><!--]--> <!--[!--><meta property="og:url" content="https://www.captaincodeman.com/undefined"> <meta property="og:type" content="website"> <meta property="og:title" content="Captain Codeman"> <meta property="og:description" name="description" content="My random assortment of coding articles on all manner of technologies."> <meta property="og:image" content="https://image.blogserve.co/captaincodeman/computer-1209641_1280_960.jpeg?v=1"> <meta property="og:image:secure_url" content="https://image.blogserve.co/captaincodeman/computer-1209641_1280_960.jpeg?v=1"> <meta property="og:image:width" content="960"> <meta property="og:image:height" content="640"><!----><!--]--><!--]--><title>Captain Codeman Blog</title> </head> <body> <!--[--><!--[--><!----><!--[--><!----><script type="application/ld+json">{"@context":"https://schema.org","@type":"Blog","url":"https://www.captaincodeman.com","name":"Captain Codeman","alternativeHeadline":"Web Development and Cloud Computing","description":"My random assortment of coding articles on all manner of technologies.","potentialAction":{"@type":"SearchAction","target":"https://www.captaincodeman.com/search?q={query}","query":"required"},"sameAs":["https://www.twitter.com/CaptainCodeman","https://www.github.com/CaptainCodeman"]}</script><!----><!--]--><!----> <div class="min-h-screen bg-white"><div class="flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start md:space-x-10"><div><a href="/" class="flex items-center"><img class="mr-3 h-8 w-auto sm:h-10" src="https://image.blogserve.co/captaincodeman/icon-192x192.png" alt="Captain Codeman" width="192" height="192"> <span class="text-xl font-bold tracking-tighter text-gray-600">Captain Codeman</span></a></div> <div class="-my-2 -mr-2 md:hidden"><button id="menuopen" type="button" class="inline-flex items-center justify-center rounded-md bg-white p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" aria-expanded="false"><span class="sr-only">Open menu</span> <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg></button></div> <div class="hidden md:flex md:flex-1 md:items-center md:justify-between"><nav class="flex space-x-10"><!--[--><a href="/category/web-development" class="text-base font-medium text-gray-500 hover:text-gray-900">Web-Development</a><a href="/category/server-side" class="text-base font-medium text-gray-500 hover:text-gray-900">Server-Side</a><a href="/category/cloud" class="text-base font-medium text-gray-500 hover:text-gray-900">Cloud</a><a href="/category/tools" class="text-base font-medium text-gray-500 hover:text-gray-900">Tools</a><a href="/about" class="text-base font-medium text-gray-500 hover:text-gray-900">About</a><!--]--></nav></div></div> <!----><div class="px-4 pt-4"><div class="mx-auto max-w-7xl text-center"><h1 class="text-4xl font-extrabold tracking-tighter text-gray-700">Captain Codeman</h1> <p class="mt-4 text-gray-800"><!---->Web Development and Cloud Computing<!----></p></div></div><!----> <!--[!--><!--]--> <div class="px-4 pb-12 pt-4 sm:px-6 lg:px-8 lg:pb-12 lg:pt-8"><div class="mx-auto max-w-7xl"><!--[!--><!--]--> <!--[--><ins class="adsbygoogle mt-4" style="display:block" data-ad-client="ca-pub-5049499290128209" data-ad-slot="3649907970" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> ;(adsbygoogle = window.adsbygoogle || []).push({}) </script><!--]--><!----> <div class="mx-auto mt-12 grid max-w-lg gap-5 md:max-w-none md:grid-cols-2 lg:max-w-none lg:grid-cols-3"><!--[--><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/cross-origin-isolation-with-sveltekit-vite-and-firebase"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/292747e3fb6683c7c18e419310e8610c/vips-coep-fail_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "119 " alt = "Cross-Origin-Isolation with SvelteKit, Vite, and Firebase"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/cross-origin-isolation-with-sveltekit-vite-and-firebase" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Cross-Origin-Isolation with SvelteKit, Vite, and Firebase</h2> <p class="mt-3 text-base text-gray-500">Using SharedArrayBuffer requires Cross Origin Isolation which can be a challenge. Learn how to use it with SvelteKit, Vite, and Firebase.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><a href="/tag/svelte" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">svelte</a><a href="/tag/vite" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">vite</a><a href="/tag/firebase" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">firebase</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/local-first-with-cloud-sync-using-firestore-and-svelte-5-runes"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/6b52e9401883c41d0ecdfb4c596da70d/net-worth_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "270 " alt = "Local First with Cloud Sync using Firestore and Svelte 5 Runes"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/local-first-with-cloud-sync-using-firestore-and-svelte-5-runes" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Local First with Cloud Sync using Firestore and Svelte 5 Runes</h2> <p class="mt-3 text-base text-gray-500">Local-first storage with cloud synchronization or backup doesn't need to be difficult or expensive. Learn how to achieve it with Firestore and Svelte 5 Runes.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/svelte" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">svelte</a><a href="/tag/firestore" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">firestore</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/dealing-with-dialogs-in-svelte"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/3c8a59cc6c3090386b74d575ebe4b395/prompt-accept_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "110 " alt = "Dealing with Dialogs in Svelte"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/dealing-with-dialogs-in-svelte" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Dealing with Dialogs in Svelte</h2> <p class="mt-3 text-base text-gray-500">Approaches to working with Modal Dialogs in Svelte</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><a href="/tag/headlessui" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">headlessui</a><a href="/tag/tailwindcss" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">tailwindcss</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/build-a-docker-container-from-a-pnpm-monorepo"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/6e5cc99ea5f65ea2ace733770fd99acb/dockerfile-vscode_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "215 " alt = "Build a Docker Container from a pnpm monorepo"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/build-a-docker-container-from-a-pnpm-monorepo" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Build a Docker Container from a pnpm monorepo</h2> <p class="mt-3 text-base text-gray-500">Docker is a great way to deploy your SvelteKit app, but how to create an optimized container build from a pnpm mono-repo isn't always obvious. Learn how to configure a small and efficient docker build process.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><a href="/tag/docker" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">docker</a><a href="/tag/pnpm" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">pnpm</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/firebase-signinwithredirect-localhost-and-sveltekit"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/60f7f9a30c33ad3c9cda20f4e90d3f9e/access-blocked_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "140 " alt = "Firebase signInWithRedirect, localhost, and SvelteKit"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/firebase-signinwithredirect-localhost-and-sveltekit" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Firebase signInWithRedirect, localhost, and SvelteKit</h2> <p class="mt-3 text-base text-gray-500">They improved the security of Firebase Auth so much it completely stopped working. Learn how to fix it.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/firebase" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">firebase</a><a href="/tag/auth" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">auth</a><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/securing-your-sveltekit-app"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/334530cb2f34c5d2b92ead0e579cc42c/8qg68e_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "223 " alt = "Securing Your SvelteKit App"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/securing-your-sveltekit-app" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Securing Your SvelteKit App</h2> <p class="mt-3 text-base text-gray-500">Naive use of +layout load functions could put your SvelteKit app at risk of security leaks. This details one approach to applying security in an unobtrusive manner.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><a href="/tag/security" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">security</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/prevent-waterfalls-from-multiple-sveltekit-server-hooks-in-sequence"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "213 " alt = "Prevent Waterfalls from Multiple SvelteKit Server Hooks in sequence"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/prevent-waterfalls-from-multiple-sveltekit-server-hooks-in-sequence" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Prevent Waterfalls from Multiple SvelteKit Server Hooks in sequence</h2> <p class="mt-3 text-base text-gray-500">Sequential async hooks.server handle functions can introduce waterfalls which can be a performance killer. Avoid slowdowns by running independent handle functions in parallel.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/deploy-a-sveltekit-app-to-github-pages"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/7795559bd2a39a20b19e83d7d66002c6/github-pages_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "154 " alt = "Deploy a SvelteKit App to GitHub Pages"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/deploy-a-sveltekit-app-to-github-pages" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Deploy a SvelteKit App to GitHub Pages</h2> <p class="mt-3 text-base text-gray-500">There are already a few guides on how to deploy your SvelteKit application to GitHub Pages but many are more complex than they need to be. This guide shows an easy way to do it with less configuration.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/svelte" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">svelte</a><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><a href="/tag/github" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">github</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/sveltekit-hydration-gotcha"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/09857e308be882242983c4bc13e2f488/sveltekit-payload-size_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "185 " alt = "SvelteKit Hydration Gotcha"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/sveltekit-hydration-gotcha" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">SvelteKit Hydration Gotcha</h2> <p class="mt-3 text-base text-gray-500">SvelteKit makes web development easy. So easy, you may not notice that you accidentally added some inefficiency. Learn what to look for and how to easily avoid it.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/svelte" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">svelte</a><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/schema-versioning-with-google-firestore"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/53d7f6c3c20b90bb54339b9368ad6af3/firestore-schema-loading-test-data_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "210 " alt = "Schema Versioning with Google Firestore"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/schema-versioning-with-google-firestore" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Schema Versioning with Google Firestore</h2> <p class="mt-3 text-base text-gray-500">NoSQL doesn't mean no-schema, it means each entity has it's own schema so you may end up with more than one. Learn how Schema Versioning helps bring order to chaos and how to use it with Google Firestore</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><a href="/category/cloud" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">cloud</a><!--]--> <!--[--><a href="/tag/firebase" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">firebase</a><a href="/tag/firestore" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">firestore</a><a href="/tag/nosql" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">nosql</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/internationalization-formatting-with-intl-ssr-sveltekit"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/e0a574b98549df02b8ee847e1ceb7ec1/browser-preferred-languages_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "175 " alt = "Internationalization Formatting with Intl + SSR + SvelteKit"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/internationalization-formatting-with-intl-ssr-sveltekit" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">Internationalization Formatting with Intl + SSR + SvelteKit</h2> <p class="mt-3 text-base text-gray-500">Using Intl to format dates and numbers on a purely client-side app is easy, but adding SSR can result in a flash of wrongly-styled content. Learn how to perfectly format SSR content to match the users locale</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/i18n" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">i18n</a><a href="/tag/internationalization" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">internationalization</a><a href="/tag/svelte" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">svelte</a><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><a href="/tag/ssr" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">ssr</a><a href="/tag/csr" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">csr</a><a href="/tag/spa" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">spa</a><!--]--></div></div></div><div class="flex flex-col overflow-hidden rounded-lg shadow-lg"><a class="flex-shrink-0" href="/how-to-await-firebase-auth-with-sveltekit"><!----><picture><source type="image/avif" srcset="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.avif?v=1 240w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_640.avif?v=1 640w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_320.avif?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><source type="image/webp" srcset="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.webp?v=1 240w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_640.webp?v=1 640w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_320.webp?v=1 320w" sizes="(min-width: 768px) 768px, 100vw"><img class="h-48 w-full object-cover" src="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.jpeg?v=1" srcset="https://image.blogserve.co/captaincodeman/computer-1209641_1280_thumb.jpeg?v=1 240w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_640.jpeg?v=1 640w,https://image.blogserve.co/captaincodeman/computer-1209641_1280_320.jpeg?v=1 320w" sizes="(min - width: 768px) 768px, 100vw" loading=lazy decoding="async" width = "320 " height = "213 " alt = "How to await Firebase Auth with SvelteKit"></picture><!----></a> <div class="flex flex-1 flex-col justify-between bg-white p-6"><div class="flex-1"><a href="/how-to-await-firebase-auth-with-sveltekit" class="mt-2 block"><h2 class="text-xl font-semibold text-gray-900">How to await Firebase Auth with SvelteKit</h2> <p class="mt-3 text-base text-gray-500">Support for async await is baked into Svelte templates but when you're using SvelteKit, you may need to wait for auth to settle in a load function which can lead to subtle gotchas.</p></a></div> <div class="mt-6"><!--[--><!--]--> <!--[--><a href="/category/web-development" class="m-1 inline-flex items-center rounded-full bg-green-100 px-3 py-0.5 text-sm font-medium text-green-800 no-underline">web-development</a><!--]--> <!--[--><a href="/tag/firebase" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">firebase</a><a href="/tag/auth" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">auth</a><a href="/tag/sveltekit" class="m-1 inline-flex items-center rounded-full bg-blue-100 px-3 py-0.5 text-sm font-medium text-blue-800 no-underline">sveltekit</a><!--]--></div></div></div><!--]--></div> <!--[--><div class="mt-8 flex justify-end"><a href="/2" class="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100">Read More …</a></div><!--]--> <!--[--><ins class="adsbygoogle mt-4" style="display:block" data-ad-client="ca-pub-5049499290128209" data-ad-slot="3649907970" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> ;(adsbygoogle = window.adsbygoogle || []).push({}) </script><!--]--><!----></div></div><!----><!----><!----> <footer class="bg-white"><div class="mx-auto max-w-7xl px-4 py-12 sm:px-6 md:flex md:items-center md:justify-between lg:px-8"><div class="flex justify-center space-x-6 md:order-2"><!--[!--><!--]--> <!--[!--><!--]--> <!--[--><a href="https://www.twitter.com/CaptainCodeman" class="text-gray-400 hover:text-gray-500"><span class="sr-only">Twitter</span> <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84"></path></svg></a><!--]--> <!--[!--><!--]--> <!--[!--><!--]--> <!--[--><a href="https://www.github.com/CaptainCodeman" class="text-gray-400 hover:text-gray-500"><span class="sr-only">GitHub</span> <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"></path></svg></a><!--]--></div> <div class="mt-8 md:order-1 md:mt-0"><p class="text-center text-base text-gray-400">© 2017 Captain Codeman, Inc. All rights reserved.</p></div></div></footer> <x-transition id="menu" enter="duration-200 ease-out" enter-from="opacity-0 scale-95" enter-to="opacity-100 scale-100" leave="transition ease-in" leave-from="opacity-100 scale-100" leave-to="opacity-0 scale-95" class="svelte-18nsacp"><div class="absolute inset-x-0 top-0 origin-top-right transform p-2 transition md:hidden"><div class="divide-y-2 divide-gray-50 rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5"><div class="px-5 pb-6 pt-5"><div class="flex items-center justify-between"><div><img class="h-8 w-auto" src="https://image.blogserve.co/captaincodeman/icon-192x192.png" alt="Captain Codeman"></div> <div class="-mr-2"><button id="menuclose" type="button" class="inline-flex items-center justify-center rounded-md bg-white p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"><span class="sr-only">Close menu</span> <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg></button></div></div></div> <div class="px-5 py-6"><div class="grid grid-cols-1 gap-4"><!--[--><a href="/category/web-development" class="text-base font-medium text-gray-900 hover:text-gray-700">Web-Development</a><a href="/category/server-side" class="text-base font-medium text-gray-900 hover:text-gray-700">Server-Side</a><a href="/category/cloud" class="text-base font-medium text-gray-900 hover:text-gray-700">Cloud</a><a href="/category/tools" class="text-base font-medium text-gray-900 hover:text-gray-700">Tools</a><a href="/about" class="text-base font-medium text-gray-900 hover:text-gray-700">About</a><!--]--></div></div></div></div></x-transition></div><!----><!--]--> <!--[!--><!--]--><!--]--> <script src="/transition.js" type="module"></script> <script src="/lite-youtube.js" type="module"></script> <script> menuopen.onclick = () => (menu.open = true) menuclose.onclick = () => (menu.open = false) </script> </body> </html>