【IT】「忘れ物ゼロ」へ。かわいいToDoで毎日をちょっと良くする話
— 無料版から“使い心地”を一段上げる → 本編で一気に完成へ
この記事は、無料パート(保存つき最小ToDo)を触った人が、
“使い心地の良さ”と“アプリとしての仕上げ”に踏み出すためのガイドです。
最後に、本編(有料)で得られる“完成体験”をまとめたので、気になったら覗いてみてください。
本編:かわいいToDoアプリをゼロから完成まで(PWA/公開/はまり対処)
✅ 限定公開URLと推奨環境
前回、有料パートで作成したToDoアプリの完成版を限定公開します。
限定公開URL:https://tabi-cat-todo-555.pages.dev/
※予告なく、公開を終了したり、クラウドホスティングサービスを変更することがございます。あらかじめご了承ください。推奨環境:
Android / PC:Chrome, Edge, Firefox, Safari(最新)
iPhone / iPad(iOS Safari):ホーム画面追加は可能。ただし 圏外では起動しません。
事前にオンラインで開いておけば、一部画面や静的資産がキャッシュで表示される場合がありますが、動作は保証できません。
まず「ここが変わる」を3行で
スマホで触りやすい:下固定の入力バー+安全なボタン配置
達成感が続く:未完了/完了/すべて切替+進捗バー、100%で紙吹雪
毎日使える:PWA対応でホーム追加&オフラインでも起動
ポイント:無料版でもリロードで保持されています。ここからは“使うたび小さな喜びがある”設計を足していきます。
5分で試せる「快適化」ミニ改良(無料のまま)
無料パートのコードに最小の追記で、体験がガラッと良くなるところだけ先出しします。
1) 三分割フィルタと進捗(導出は `$derived`)
<script lang="ts">
import { todos, type Todo } from '$lib/stores/todos';
type Filter = 'all' | 'todo' | 'done';
let filter = $state<Filter>('all');
let list = $state<Todo[]>([]);
$effect(() => todos.subscribe(v => list = v));
function applyFilter(a: Todo[], f: Filter){
if (f === 'todo') return a.filter(t => !t.done);
if (f === 'done') return a.filter(t => t.done);
return a;
}
const filtered = $derived(applyFilter(list, filter));
const stats = $derived({
total: list.length,
done: list.filter(t => t.done).length,
rate: list.length ? Math.round(list.filter(t=>t.done).length / list.length * 100) : 0
});
</script>
<div class="segbar card">
<button class="segbtn" class:active={filter==='todo'} onclick={() => filter='todo'}>
未完了 <span class="pill">{stats.total - stats.done}</span>
</button>
<button class="segbtn" class:active={filter==='done'} onclick={() => filter='done'}>
完了 <span class="pill">{stats.done}</span>
</button>
<button class="segbtn" class:active={filter==='all'} onclick={() => filter='all'}>
すべて <span class="pill">{stats.total}</span>
</button>
</div>コツ:Svelte v5/Runesでは、`bind:value` の相手は `$state`。導出は `$derived` を“式”で書くと素直に動きます。
2) 100%達成で“ちょい紙吹雪”
<script lang="ts">
let last = $state(0);
$effect(() => {
if (stats.rate === 100 && Date.now() - last > 1500) { boom(); last = Date.now(); }
});
function boom(){
const root = document.querySelector('.confetti')!;
root.innerHTML = '';
const colors=['#FF8FB1','#A7E8F8','#FDE68A','#55C3A6'];
for(let i=0;i<60;i++){
const s=document.createElement('span');
s.style.left=Math.random()*100+'vw';
s.style.top='-5vh';
s.style.animationDuration=(1.6+Math.random()*1.2)+'s';
s.style.animationDelay=(Math.random()*0.6)+'s';
s.style.background=colors[i%colors.length];
root.appendChild(s);
}
setTimeout(()=>root.innerHTML='',3200);
}
</script>
<div class="confetti" aria-hidden="true"></div>心理効果:軽い演出でも「終わらせたい気持ち」が続きます。
デザインは“透け”で整える(無料のまま)
背景イラストをWebP優先+PNGフォールバック。カードは白の半透明で可読性を確保。
/* src/app.css(抜粋) */
html, body { height: 100%; }
body{
min-height: 100dvh;
background:
image-set(
url('/bg-cat.webp') type('image/webp') 1x,
url('/bg-cat.png') type('image/png') 1x
) center / cover no-repeat;
}
.card{ background: rgba(255,255,255,.74); border-radius: 18px; box-shadow: 0 8px 28px rgba(0,0,0,.08); }「ここから先」を本編で得られること(要点だけ先出し)
✅ PWA:ホーム追加&オフライン(iOS/Androidの違いも“迷わない”)
manifest の正解:`id/start_url/scope` を '/'で統一(警告回避)
iOSの真実:インストールバナーは出ません → 共有から「ホーム画面に追加」
アイコン生成の沼回避(`192x188`にならない ImageMagick の式)
magick ./WORK/tabi-cat.jpg -resize "192x192^" -gravity center -extent 192x192 -strip ./static/icons/icon-192.png
magick ./WORK/tabi-cat.jpg -resize "512x512^" -gravity center -extent 512x512 -strip ./static/icons/icon-512.png✅ 本当に毎日使えるUI:親指で届く設計
下固定の入力バー(セーフエリア対応)
ボタンは誤タップを防ぐ角丸+十分なタップ領域
✅ 本番運用の壁をショートカット
Workbox 2MB問題(大きい背景は precache されない)→ 実害の線引きと対処
each_key_duplicate(キー重複)→ `(t.id)`必須+古いデータのid補完
Vercelで反映されない → Service Worker の更新(Unregister/Reload)
こうした「作るより時間を奪う“迷い”」に答えを用意しました。
スクショ/設定例/コピペOKの最小スニペット付きで、迷わず完成させます。
Before / After(たった30分で体験がこう変わる)

まずはここまでできたらOK(無料の最終チェック)
追加・切替・削除ができ、リロード後も保持される
未完了/完了/すべての切替&進捗バーが動く
背景は最初から下まで表示、カードは半透明で可読性高い
ここからPWA対応→配布(Vercel)→“毎日使う”完成まで、
具体例と“はまり対処”をまとめたのが本編です👇
本編のご案内(ここで迷わず一気に完成)
PWAの正解セット(manifest・iOS/Android差分・インストール導線UI)
アイコン/スクショの作り方テンプレ(失敗しないImageMagick式)
Vercelでの公開・更新の勘所(SW更新/キャッシュ癖を含む)
実装のはまりケースを丸ごと時短(`crossorigin`型、`each_key_duplicate`ほか)
本編:かわいいToDoアプリをゼロから完成まで(PWA/公開/はまり対処)
👉 https://note.com/t_ak66/n/n690e65a9a535
追伸
「買い物メモをまた忘れた」「今日やることを見失う」— それ、UIと小さな演出で意外と解決します。
せっかく動くToDoがあるなら、“毎日使いたくなるToDo”に変えましょう。
続きは本編で。
では
また!
