It's a todo list.
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

update stores with PersistedState, useInterval timers

authored by

Zeu Capua and committed by tangled.org 4fb3ee3c 7faeaa01

+101 -131
+12
bun.lock
··· 7 7 "dependencies": { 8 8 "@tailwindcss/vite": "^4.1.13", 9 9 "oslo": "^1.2.1", 10 + "runed": "^0.37.1", 10 11 "svelte-french-toast": "^1.2.0", 11 12 "tailwindcss": "^4.1.13", 12 13 }, 13 14 "devDependencies": { 15 + "@sveltejs/adapter-netlify": "^6.0.4", 14 16 "@sveltejs/kit": "^2.43.5", 15 17 "@sveltejs/vite-plugin-svelte": "^6.2.1", 16 18 "svelte": "^5.39.6", ··· 77 79 "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="], 78 80 79 81 "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="], 82 + 83 + "@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="], 80 84 81 85 "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], 82 86 ··· 199 203 "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], 200 204 201 205 "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.6", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ=="], 206 + 207 + "@sveltejs/adapter-netlify": ["@sveltejs/adapter-netlify@6.0.4", "", { "dependencies": { "@iarna/toml": "^2.2.5", "esbuild": "^0.25.4" }, "peerDependencies": { "@sveltejs/kit": "^2.31.0" } }, "sha512-Ln/vgZc1v/2JFXhl5QiVKJ61a75jKe2rdxMnDO8PPDpQN8Tq/0w4JnBGAMBqENtD+kDACyY00ZTyzP9uTP77wg=="], 202 208 203 209 "@sveltejs/kit": ["@sveltejs/kit@2.43.5", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-44Mm5csR4mesKx2Eyhtk8UVrLJ4c04BT2wMTfYGKJMOkUqpHP5KLL2DPV0hXUA4t4+T3ZYe0aBygd42lVYv2cA=="], 204 210 ··· 260 266 261 267 "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], 262 268 269 + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], 270 + 263 271 "detect-libc": ["detect-libc@2.1.1", "", {}, "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw=="], 264 272 265 273 "devalue": ["devalue@5.3.2", "", {}, "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw=="], ··· 310 318 311 319 "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], 312 320 321 + "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="], 322 + 313 323 "magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="], 314 324 315 325 "memfs": ["memfs@3.5.3", "", { "dependencies": { "fs-monkey": "^1.0.4" } }, "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw=="], ··· 339 349 "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], 340 350 341 351 "rollup": ["rollup@4.52.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.3", "@rollup/rollup-android-arm64": "4.52.3", "@rollup/rollup-darwin-arm64": "4.52.3", "@rollup/rollup-darwin-x64": "4.52.3", "@rollup/rollup-freebsd-arm64": "4.52.3", "@rollup/rollup-freebsd-x64": "4.52.3", "@rollup/rollup-linux-arm-gnueabihf": "4.52.3", "@rollup/rollup-linux-arm-musleabihf": "4.52.3", "@rollup/rollup-linux-arm64-gnu": "4.52.3", "@rollup/rollup-linux-arm64-musl": "4.52.3", "@rollup/rollup-linux-loong64-gnu": "4.52.3", "@rollup/rollup-linux-ppc64-gnu": "4.52.3", "@rollup/rollup-linux-riscv64-gnu": "4.52.3", "@rollup/rollup-linux-riscv64-musl": "4.52.3", "@rollup/rollup-linux-s390x-gnu": "4.52.3", "@rollup/rollup-linux-x64-gnu": "4.52.3", "@rollup/rollup-linux-x64-musl": "4.52.3", "@rollup/rollup-openharmony-arm64": "4.52.3", "@rollup/rollup-win32-arm64-msvc": "4.52.3", "@rollup/rollup-win32-ia32-msvc": "4.52.3", "@rollup/rollup-win32-x64-gnu": "4.52.3", "@rollup/rollup-win32-x64-msvc": "4.52.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A=="], 352 + 353 + "runed": ["runed@0.37.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0", "zod": "^4.1.0" }, "optionalPeers": ["@sveltejs/kit", "zod"] }, "sha512-MeFY73xBW8IueWBm012nNFIGy19WUGPLtknavyUPMpnyt350M47PhGSGrGoSLbidwn+Zlt/O0cp8/OZE3LASWA=="], 342 354 343 355 "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], 344 356
+2
package.json
··· 10 10 "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch" 11 11 }, 12 12 "devDependencies": { 13 + "@sveltejs/adapter-netlify": "^6.0.4", 13 14 "@sveltejs/kit": "^2.43.5", 14 15 "@sveltejs/vite-plugin-svelte": "^6.2.1", 15 16 "svelte": "^5.39.6", ··· 22 23 "dependencies": { 23 24 "@tailwindcss/vite": "^4.1.13", 24 25 "oslo": "^1.2.1", 26 + "runed": "^0.37.1", 25 27 "svelte-french-toast": "^1.2.0", 26 28 "tailwindcss": "^4.1.13" 27 29 }
+53
src/lib/TaskItem.svelte
··· 1 + <script lang="ts"> 2 + import { useInterval } from "runed"; 3 + import type { Task } from "./stores.svelte"; 4 + import { formatSecondsToDuration } from "./utils"; 5 + 6 + let { task = $bindable(), onDelete }: { task: Task, onDelete: (taskId: string) => void } = $props(); 7 + 8 + const interval = useInterval(1000, { 9 + immediate: false, 10 + callback: () => { 11 + task.duration++; 12 + } 13 + }); 14 + 15 + function toggleInterval() { 16 + if (interval.isActive) { 17 + interval.pause(); 18 + } 19 + else { 20 + interval.resume(); 21 + } 22 + } 23 + </script> 24 + 25 + <li class="group flex justify-between items-center gap-4"> 26 + <div class="flex w-full gap-4 items-center pr-4 py-2"> 27 + <input 28 + type="checkbox" 29 + bind:checked={task.completed} 30 + class="w-6 h-6 bg-transparent" 31 + /> 32 + <input 33 + type="text" 34 + bind:value={task.description} 35 + class={`w-full hover:underline text-ellipsis overflow-hidden bg-transparent ${task.completed && "text-white/50"}`} 36 + /> 37 + </div> 38 + 39 + <div class="flex gap-4 w-fit items-center"> 40 + <button 41 + onclick={toggleInterval} 42 + class="w-fit h-fit tabular-nums text-lg" 43 + > 44 + {formatSecondsToDuration(task.duration!)} 45 + </button> 46 + <button 47 + onclick={() => onDelete(task.id)} 48 + class="px-4 py-2 bg-red-500 rounded-xl text-white" 49 + > 50 + - 51 + </button> 52 + </div> 53 + </li>
+8 -40
src/lib/stores.svelte.ts
··· 1 1 import { generateId } from "./utils"; 2 - 3 - // Browser + Local Storage 4 - const browser_exists = (typeof window !== "undefined") && (typeof (document) !== "undefined"); 5 - const storage = browser_exists ? localStorage : null; 6 - 7 - // Generalized Local Storage 8 - export function persisted<T>(key: string, default_value: T) { 9 - let value : T | undefined = $state(); 10 - 11 - const initial_local = storage?.getItem(key); 12 - if (initial_local) { 13 - value = JSON.parse(initial_local).value as T; 14 - if (!value) { update(); } 15 - } 16 - else { 17 - value = default_value; 18 - update(); 19 - } 20 - 21 - function update() { 22 - if (browser_exists) { 23 - storage?.setItem(key, JSON.stringify({ value: value })); 24 - } 25 - } 26 - 27 - return { 28 - get value() { return value; }, 29 - set value(new_value) { value = new_value; update(); }, 30 - update 31 - } 32 - } 2 + import { PersistedState } from "runed"; 33 3 34 4 export type Task = { 35 5 id: string; 36 6 description: string; 37 - is_completed: boolean; 38 - // optional 39 - duration?: number; 40 - stopwatchInterval?: number; 7 + completed: boolean; 8 + duration: number; 41 9 } 42 10 43 11 export type List = { ··· 46 14 tasks: Task[]; 47 15 } 48 16 49 - export const local_lists = persisted<List[]>("local_lists", [ 17 + export const local_lists = new PersistedState<List[]>("local_lists", [ 50 18 { 51 19 id: generateId(), 52 20 title: "Take a Break", 53 21 tasks: [ 54 - { id: generateId(), description: "Drink water", is_completed: false }, 55 - { id: generateId(), description: "Stand up and stretch", is_completed: false }, 56 - { id: generateId(), description: "Go outside for 10 seconds", is_completed: false }, ] 22 + { id: generateId(), description: "Drink water", completed: false, duration: 0 }, 23 + { id: generateId(), description: "Stand up and stretch", completed: false, duration: 0 }, 24 + { id: generateId(), description: "Go outside for 10 seconds", completed: false, duration: 0 }, ] 57 25 } 58 26 ]); 59 27 60 - export const pinned_list = persisted<string>("pinned_list", local_lists.value![0].id); 28 + export const pinned_list = new PersistedState<string>("pinned_list", local_lists.current[0].id);
+9 -8
src/routes/+layout.svelte
··· 5 5 import { goto } from "$app/navigation"; 6 6 import { fade } from "svelte/transition"; 7 7 import toast, { Toaster } from "svelte-french-toast"; 8 - import { persisted, pinned_list } from "$lib/stores.svelte"; 8 + import { pinned_list } from "$lib/stores.svelte"; 9 + import { PersistedState } from "runed"; 9 10 10 11 interface Props { 11 12 children: Snippet ··· 13 14 14 15 let { children }: Props = $props(); 15 16 16 - let theme = persisted<string>("theme", "dark"); 17 + let theme = new PersistedState<string>("theme", "dark"); 17 18 let is_menu_open = $state(false); 18 - let theme_style = $derived(theme.value === "dark" 19 + let theme_style = $derived(theme.current === "dark" 19 20 ? "text-white absolute top-0 z-[-2] h-screen w-screen bg-[#000000] bg-[radial-gradient(#ffffff33_1px,#00091d_1px)] bg-size-[20px_20px]" 20 21 : "text-black absolute inset-0 -z-10 h-full w-full bg-white bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] bg-size-[16px_16px]" 21 22 ); ··· 26 27 27 28 onMount(() => { 28 29 if (page.url.pathname === "/") { 29 - goto(`/${pinned_list.value}`); 30 + goto(`/${pinned_list.current}`); 30 31 } 31 32 }); 32 33 </script> ··· 41 42 {#if is_menu_open} 42 43 <menu 43 44 transition:fade={{ duration: 150 }} 44 - class={`${theme.value === "light" ? "border-black" : "border-[#00091d]"} w-fit border z-50 flex flex-col items-start gap-2 h-fit p-2 rounded-xl bg-white`} 45 + class={`${theme.current === "light" ? "border-black" : "border-[#00091d]"} w-fit border z-50 flex flex-col items-start gap-2 h-fit p-2 rounded-xl bg-white`} 45 46 > 46 47 <button 47 48 onclick={() => { ··· 66 67 </menu> 67 68 {/if} 68 69 69 - <nav class={`${theme.value === "light" ? "border-black" : "border-[#00091d]"} border z-50 flex self-center items-center gap-4 mx-auto w-fit h-fit p-2 rounded-xl bg-white`}> 70 + <nav class={`${theme.current === "light" ? "border-black" : "border-[#00091d]"} border z-50 flex self-center items-center gap-4 mx-auto w-fit h-fit p-2 rounded-xl bg-white`}> 70 71 <button 71 72 onclick={() => is_menu_open = !is_menu_open} 72 73 class="w-full h-fit hover:bg-slate-500/10 rounded-full" ··· 94 95 95 96 96 97 <button 97 - onclick={() => { theme.value = theme.value === "light" ? "dark" : "light" }} 98 - class={`${theme.value === "light" ? "border-black" : "border-[#00091d]"} border w-fit h-fit p-2 bg-white rounded-xl pointer-events-auto`} 98 + onclick={() => { theme.current = theme.current === "light" ? "dark" : "light" }} 99 + class={`${theme.current === "light" ? "border-black" : "border-[#00091d]"} border w-fit h-fit p-2 bg-white rounded-xl pointer-events-auto`} 99 100 > 100 101 <img 101 102 src="/light-bulb.svg"
+15 -75
src/routes/[id]/+page.svelte
··· 5 5 import toast from "svelte-french-toast"; 6 6 import { formatSecondsToDuration, generateId } from "$lib/utils"; 7 7 import { local_lists, pinned_list, type List, type Task } from "$lib/stores.svelte"; 8 + import TaskItem from "$lib/TaskItem.svelte"; 8 9 9 10 let is_menu_open = $state(false); 10 - let list : List | undefined = $state(local_lists.value!.find((l) => l.id === page.params.id)); 11 + let list : List | undefined = $derived(local_lists.current!.find((l) => l.id === page.params.id)); 11 12 let task_input = $state(""); 12 - let user_lists = $derived(local_lists.value) as List[]; 13 + let user_lists = $derived(local_lists.current) as List[]; 13 14 14 15 // since list points to something inside local_lists, 15 16 // it will run when list state changes 16 - $effect(() => local_lists.update()); 17 17 18 18 function addTask() { 19 19 if (task_input.length === 0) { ··· 24 24 list?.tasks.push({ 25 25 id: generateId(), 26 26 description: task_input, 27 - is_completed: false 27 + completed: false, 28 + duration: 0 28 29 }); 29 30 30 31 task_input = ""; ··· 36 37 } 37 38 } 38 39 39 - function toggleInterval(id: string) { 40 - if (list) { 41 - const task = list.tasks.find((t) => t.id === id) as Task; 42 - if (task.stopwatchInterval) { 43 - clearInterval(task.stopwatchInterval); 44 - task.stopwatchInterval = undefined; 45 - } 46 - else { 47 - const interval = setInterval(() => { 48 - if (!task.duration) { task.duration = 0; } 49 - task.duration += 1; 50 - }, 1000); 51 - task.stopwatchInterval = interval; 52 - } 53 - } 54 - } 55 - 56 40 function createList() { 57 41 const new_list = { 58 42 id: generateId(), ··· 60 44 tasks: [] 61 45 }; 62 46 63 - local_lists.value!.push(new_list); 64 - list = local_lists.value!.find((l) => l.id === new_list.id); 47 + local_lists.current!.push(new_list); 48 + list = local_lists.current!.find((l) => l.id === new_list.id); 65 49 goto(`/${list!.id}`); 66 50 } 67 51 68 52 function switchToList(id: string) { 69 - list = local_lists.value!.find((l) => l.id === id); 53 + list = local_lists.current!.find((l) => l.id === id); 70 54 goto(`/${list!.id}`); 71 55 } 72 56 73 57 function pinList(id: string) { 74 - pinned_list.value = id; 58 + pinned_list.current = id; 75 59 } 76 60 77 61 function deleteList() { 78 - if (pinned_list.value === page.params.id) { 62 + if (pinned_list.current === page.params.id) { 79 63 toast.error("Cannot delete pinned list"); 80 64 return; 81 65 } 82 66 83 - local_lists.value = local_lists.value!.filter((l) => l.id !== page.params.id); 84 - list = local_lists.value.find((l) => l.id === pinned_list.value); 67 + local_lists.current = local_lists.current!.filter((l) => l.id !== page.params.id); 68 + list = local_lists.current.find((l) => l.id === pinned_list.current); 85 69 goto(`/${list!.id}`); 86 70 } 87 - 88 - onMount(() => { 89 - if (list) { 90 - for (const task of list.tasks) { 91 - // if a task's stopwatch is still running 92 - // remove it so the user can start it again in one click 93 - // instead of two cause the first `toggleInterval` would 94 - // just remove the interval 95 - if (task.stopwatchInterval) { 96 - clearInterval(task.stopwatchInterval); 97 - task.stopwatchInterval = undefined; 98 - local_lists.update(); 99 - } 100 - } 101 - } 102 - }); 103 71 </script> 104 72 105 73 <main class="flex flex-col w-full px-2 pt-8 pb-28 lg:px-4 lg:pt-4 gap-8 text-xl lg:text-3xl"> ··· 115 83 </button> 116 84 <button onclick={() => pinList(list!.id)}> 117 85 <img 118 - src={pinned_list.value === list.id ? "/pin.svg" : "/pin-line.svg"} 86 + src={pinned_list.current === list.id ? "/pin.svg" : "/pin-line.svg"} 119 87 alt="Pin list button" 120 88 class="w-12 h-12 hover:bg-slate-500/10 rounded-full" 121 89 /> ··· 166 134 /> 167 135 168 136 <ul class="flex flex-col gap-4"> 169 - {#each list.tasks as task (task.id)} 170 - <li class="group flex justify-between items-center gap-4"> 171 - <div class="flex w-full gap-4 items-center pr-4 py-2"> 172 - <input 173 - type="checkbox" 174 - bind:checked={task.is_completed} 175 - class="w-6 h-6 bg-transparent" 176 - /> 177 - <input 178 - type="text" 179 - bind:value={task.description} 180 - class={`w-full hover:underline text-ellipsis overflow-hidden bg-transparent ${task.is_completed && "text-white/50"}`} 181 - /> 182 - </div> 183 - 184 - <div class="flex gap-4 w-fit items-center"> 185 - <button 186 - onclick={() => toggleInterval(task.id)} 187 - class="w-fit h-fit tabular-nums text-lg" 188 - > 189 - {formatSecondsToDuration(task.duration!)} 190 - </button> 191 - <button 192 - onclick={() => deleteTask(task.id)} 193 - class="px-4 py-2 bg-red-500 rounded-xl text-white" 194 - > 195 - - 196 - </button> 197 - </div> 198 - </li> 137 + {#each list.tasks as task, i (task.id)} 138 + <TaskItem bind:task={list.tasks[i]} onDelete={deleteTask} /> 199 139 {/each} 200 140 <li class="flex gap-4 w-full"> 201 141 <input type="text" bind:value={task_input} class="bg-transparent pr-4 py-2 border-b w-full"/>
+2 -8
svelte.config.js
··· 1 - import adapter from '@deno/svelte-adapter'; 1 + import adapter from '@sveltejs/adapter-netlify'; 2 2 import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 3 3 4 4 /** @type {import('@sveltejs/kit').Config} */ ··· 6 6 // Consult https://kit.svelte.dev/docs/integrations#preprocessors 7 7 // for more information about preprocessors 8 8 preprocess: vitePreprocess(), 9 - 10 - kit: { 11 - // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. 12 - // If your environment is not supported or you settled on a specific environment, switch out the adapter. 13 - // See https://kit.svelte.dev/docs/adapters for more information about adapters. 14 - adapter: adapter() 15 - } 9 + kit: { adapter: adapter() } 16 10 }; 17 11 18 12 export default config;