Skip to content

Commit 640b520

Browse files
aster-voidclaude
andcommitted
treewide: implement TODO items and improvements
- Add development alert banner (controlled by PUBLIC_SHOW_DEV_BANNER) - Make stats section clickable with navigation links - Fix migrate page memory leak with proper $effect/untrack usage - Add URL redirects for old article structure (/articles/YYYY/...) - Add sponsor company logos (GMOメディア, RIZAPテクノロジーズ) - Improve mobile responsiveness across site and admin pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent ea3d258 commit 640b520

36 files changed

+390
-278
lines changed

.env.sample

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ UNSAFE_DISABLE_AUTH=true
1818
# Cloudflare cache purge (leave empty to disable)
1919
CLOUDFLARE_ZONE_ID=""
2020
CLOUDFLARE_API_TOKEN=""
21+
22+
# Show development banner on site layout
23+
PUBLIC_SHOW_DEV_BANNER=true

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"scripts": {
77
"dev": "vite dev",
88
"build": "vite build",
9-
"build:local": "sops exec-env secrets.prod.yaml 'vite build'",
109
"preview": "vite preview",
1110
"prepare": "svelte-kit sync",
1211
"test-check": "bun test",
@@ -20,8 +19,8 @@
2019
"lint-check": "biome lint .",
2120
"lint": "bun lint-check",
2221
"lint-fix": "biome lint --fix .",
23-
"db": "drizzle-kit",
24-
"up": "bun db push --force && devenv processes up -d",
22+
"db": "bun drizzle-kit",
23+
"up": "sops exec-env secrets.dev.yaml 'bun db push --force' && devenv processes up -d",
2524
"down": "devenv processes down",
2625
"reload": "bun down && bun up",
2726
"attach": "devenv processes up",

src/hooks.server.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Handle } from "@sveltejs/kit";
2+
import { redirect } from "@sveltejs/kit";
23
import { sequence } from "@sveltejs/kit/hooks";
34
import { svelteKitHandler } from "better-auth/svelte-kit";
45
import { building } from "$app/environment";
@@ -8,6 +9,20 @@ const handleAuth: Handle = async ({ event, resolve }) => {
89
return await svelteKitHandler({ event, resolve, auth, building });
910
};
1011

12+
const handleRedirect: Handle = async ({ event, resolve }) => {
13+
const path = event.url.pathname;
14+
15+
// Redirect old article URL structure: /articles/YYYY/MM-DD_slug -> /articles/MM-DD_slug
16+
const oldArticlePattern = /^\/articles\/(\d{4})\/(.+)$/;
17+
const match = path.match(oldArticlePattern);
18+
if (match) {
19+
const slug = match[2];
20+
redirect(301, `/articles/${slug}`);
21+
}
22+
23+
return resolve(event);
24+
};
25+
1126
const handleCache: Handle = async ({ event, resolve }) => {
1227
const response = await resolve(event);
1328
const path = event.url.pathname;
@@ -30,4 +45,4 @@ const handleCache: Handle = async ({ event, resolve }) => {
3045
return response;
3146
};
3247

33-
export const handle = sequence(handleAuth, handleCache);
48+
export const handle = sequence(handleRedirect, handleAuth, handleCache);

src/lib/components/MemberForm.svelte

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@
7676
<form onsubmit={handleSubmit} class="flex h-full flex-col">
7777
<!-- Header Bar -->
7878
<header
79-
class="sticky top-0 z-20 flex items-center justify-between border-b border-zinc-200 bg-white px-4 py-3"
79+
class="sticky top-0 z-20 flex flex-wrap items-center justify-between gap-2 border-b border-zinc-200 bg-white px-3 py-2 sm:px-4 sm:py-3"
8080
>
81-
<div class="flex items-center gap-4">
81+
<div class="flex items-center gap-2 sm:gap-4">
8282
<button
8383
type="button"
8484
onclick={() => goto("/admin/members")}
@@ -89,12 +89,12 @@
8989
</button>
9090
</div>
9191

92-
<div class="flex items-center gap-2">
92+
<div class="flex items-center gap-1 sm:gap-2">
9393
<!-- Settings Toggle -->
9494
<button
9595
type="button"
9696
onclick={() => (showSettings = !showSettings)}
97-
class="flex items-center gap-1.5 rounded-lg px-3 py-2 text-sm transition-colors {showSettings
97+
class="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-sm transition-colors sm:px-3 sm:py-2 {showSettings
9898
? 'bg-zinc-900 text-white'
9999
: 'text-zinc-600 hover:bg-zinc-100 hover:text-zinc-900'}"
100100
>
@@ -106,12 +106,13 @@
106106
<button
107107
type="submit"
108108
disabled={isSubmitting}
109-
class="inline-flex items-center gap-2 rounded-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white transition-all hover:bg-zinc-800 active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50"
109+
class="inline-flex items-center gap-1.5 rounded-lg bg-zinc-900 px-3 py-1.5 text-sm font-semibold text-white transition-all hover:bg-zinc-800 active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:gap-2 sm:px-4 sm:py-2"
110110
>
111111
{#if isSubmitting}
112112
<Loader2 class="h-4 w-4 animate-spin" />
113113
{/if}
114-
{submitLabel}
114+
<span class="hidden sm:inline">{submitLabel}</span>
115+
<span class="sm:hidden">Save</span>
115116
</button>
116117
</div>
117118
</header>
@@ -221,9 +222,9 @@
221222

222223
<!-- Settings Sidebar -->
223224
{#if showSettings}
224-
<aside class="w-80 shrink-0 overflow-y-auto border-l border-zinc-200 bg-zinc-50/50 lg:w-96">
225+
<aside class="fixed inset-0 z-30 w-full overflow-y-auto bg-zinc-50 lg:static lg:w-80 lg:shrink-0 lg:border-l lg:border-zinc-200 lg:bg-zinc-50/50 xl:w-96">
225226
<div
226-
class="sticky top-0 flex items-center justify-between border-b border-zinc-200 bg-zinc-50/80 px-4 py-3 backdrop-blur-sm"
227+
class="sticky top-0 flex items-center justify-between border-b border-zinc-200 bg-zinc-50 px-4 py-3 backdrop-blur-sm lg:bg-zinc-50/80"
227228
>
228229
<h2 class="font-semibold text-zinc-900">Settings</h2>
229230
<button

src/lib/components/admin-dashboard/DashboardHeader.svelte

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,51 +10,52 @@
1010
const { publishedArticles, members, projects }: Props = $props();
1111
</script>
1212

13-
<header class="animate-fade-slide-in gradient-dark relative overflow-hidden rounded-2xl p-8">
13+
<header class="animate-fade-slide-in gradient-dark relative overflow-hidden rounded-2xl p-4 sm:p-6 lg:p-8">
1414
<!-- Decorative elements -->
1515
<div class="absolute -top-10 -right-10 h-40 w-40 rounded-full bg-primary/30 blur-3xl"></div>
1616
<div class="absolute -bottom-10 left-1/4 h-32 w-32 rounded-full bg-info/20 blur-3xl"></div>
1717

18-
<div class="relative flex items-start justify-between">
18+
<div class="relative flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
1919
<div>
2020
<div class="mb-2 flex items-center gap-2">
2121
<div
22-
class="gradient-primary glow-primary flex h-10 w-10 items-center justify-center rounded-xl"
22+
class="gradient-primary glow-primary flex h-8 w-8 items-center justify-center rounded-xl sm:h-10 sm:w-10"
2323
>
24-
<LayoutGrid class="h-5 w-5 text-white" />
24+
<LayoutGrid class="h-4 w-4 text-white sm:h-5 sm:w-5" />
2525
</div>
2626
<span class="font-mono text-xs font-semibold tracking-wider text-primary uppercase">
2727
Dashboard
2828
</span>
2929
</div>
30-
<h1 class="text-3xl font-bold text-white">Welcome back</h1>
31-
<p class="mt-1 text-white/60">Here's what's happening with your content</p>
30+
<h1 class="text-xl font-bold text-white sm:text-2xl lg:text-3xl">Welcome back</h1>
31+
<p class="mt-1 text-xs text-white/60 sm:text-sm lg:text-base">Here's what's happening with your content</p>
3232
</div>
3333
<a
3434
href="/"
3535
target="_blank"
36-
class="btn gap-2 border-white/20 bg-white/10 text-white btn-sm hover:bg-white/20"
36+
class="btn gap-2 border-white/20 bg-white/10 text-white btn-sm hover:bg-white/20 sm:btn-md"
3737
>
38-
<ExternalLink class="h-4 w-4" />
39-
View Site
38+
<ExternalLink class="h-3 w-3 sm:h-4 sm:w-4" />
39+
<span class="hidden sm:inline">View Site</span>
40+
<span class="sm:hidden">Site</span>
4041
</a>
4142
</div>
4243

4344
<!-- Quick stats row -->
44-
<div class="relative mt-6 flex items-center gap-6">
45-
<div class="flex items-center gap-2 text-white/80">
46-
<TrendingUp class="h-4 w-4 text-primary" />
47-
<span class="text-sm font-medium">{publishedArticles} published</span>
45+
<div class="relative mt-4 flex flex-wrap items-center gap-2 sm:mt-6 sm:gap-3 lg:gap-6">
46+
<div class="flex items-center gap-1.5 text-white/80 sm:gap-2">
47+
<TrendingUp class="h-3.5 w-3.5 text-primary sm:h-4 sm:w-4" />
48+
<span class="text-xs font-medium sm:text-sm">{publishedArticles} published</span>
4849
</div>
49-
<div class="h-4 w-px bg-white/20"></div>
50-
<div class="flex items-center gap-2 text-white/80">
51-
<Users class="h-4 w-4 text-info" />
52-
<span class="text-sm font-medium">{members} members</span>
50+
<div class="hidden h-4 w-px bg-white/20 sm:block"></div>
51+
<div class="flex items-center gap-1.5 text-white/80 sm:gap-2">
52+
<Users class="h-3.5 w-3.5 text-info sm:h-4 sm:w-4" />
53+
<span class="text-xs font-medium sm:text-sm">{members} members</span>
5354
</div>
54-
<div class="h-4 w-px bg-white/20"></div>
55-
<div class="flex items-center gap-2 text-white/80">
56-
<Folder class="h-4 w-4 text-secondary-content" />
57-
<span class="text-sm font-medium">{projects} projects</span>
55+
<div class="hidden h-4 w-px bg-white/20 sm:block"></div>
56+
<div class="flex items-center gap-1.5 text-white/80 sm:gap-2">
57+
<Folder class="h-3.5 w-3.5 text-secondary-content sm:h-4 sm:w-4" />
58+
<span class="text-xs font-medium sm:text-sm">{projects} projects</span>
5859
</div>
5960
</div>
6061
</header>

src/lib/components/admin-dashboard/NeedsAttention.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
</script>
1717

1818
{#if draftArticles.length > 0}
19-
<section class="animate-fade-slide-in stagger-5 glow-soft rounded-2xl bg-base-100 p-6">
20-
<div class="mb-4 flex items-center gap-3">
21-
<div class="flex h-8 w-8 items-center justify-center rounded-lg bg-warning/10">
19+
<section class="animate-fade-slide-in stagger-5 glow-soft rounded-2xl bg-base-100 p-4 sm:p-6">
20+
<div class="mb-4 flex flex-wrap items-center gap-2 sm:gap-3">
21+
<div class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-warning/10">
2222
<AlertCircle class="h-4 w-4 text-warning" />
2323
</div>
2424
<h2 class="font-semibold text-base-content">Needs Attention</h2>
2525
<span class="ml-auto rounded-full bg-warning/10 px-2 py-0.5 text-xs font-medium text-warning">
26-
{draftArticles.length} drafts
26+
{draftArticles.length} draft{draftArticles.length > 1 ? 's' : ''}
2727
</span>
2828
</div>
2929
<div class="space-y-2">

src/lib/components/admin-dashboard/QuickActions.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,24 @@
99
</div>
1010
<h2 class="font-semibold text-base-content">Quick Actions</h2>
1111
</div>
12-
<div class="flex flex-wrap gap-3">
12+
<div class="grid grid-cols-1 gap-3 sm:grid-cols-3">
1313
<a
1414
href="/admin/members/new"
15-
class="btn gap-2 border-base-300 bg-base-100 font-medium transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary"
15+
class="btn btn-sm gap-2 border-base-300 bg-base-100 font-medium transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary sm:btn-md"
1616
>
1717
<UserPlus class="h-4 w-4" />
1818
Add Member
1919
</a>
2020
<a
2121
href="/admin/articles/new"
22-
class="btn gap-2 border-base-300 bg-base-100 font-medium transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary"
22+
class="btn btn-sm gap-2 border-base-300 bg-base-100 font-medium transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary sm:btn-md"
2323
>
2424
<Pencil class="h-4 w-4" />
2525
New Article
2626
</a>
2727
<a
2828
href="/admin/projects/new"
29-
class="btn gap-2 border-base-300 bg-base-100 font-medium transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary"
29+
class="btn btn-sm gap-2 border-base-300 bg-base-100 font-medium transition-all hover:border-primary/30 hover:bg-primary/5 hover:text-primary sm:btn-md"
3030
>
3131
<Folder class="h-4 w-4" />
3232
New Project

src/lib/components/admin-dashboard/RecentActivity.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
</script>
1919

2020
<section
21-
class="animate-fade-slide-in stagger-5 glow-soft rounded-2xl bg-base-100 p-6 {hasDrafts
21+
class="animate-fade-slide-in stagger-5 glow-soft rounded-2xl bg-base-100 p-4 sm:p-6 {hasDrafts
2222
? ''
2323
: 'lg:col-span-2'}"
2424
>
25-
<div class="mb-4 flex items-center gap-3">
26-
<div class="flex h-8 w-8 items-center justify-center rounded-lg bg-primary/10">
25+
<div class="mb-4 flex flex-wrap items-center gap-2 sm:gap-3">
26+
<div class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary/10">
2727
<Clock class="h-4 w-4 text-primary" />
2828
</div>
2929
<h2 class="font-semibold text-base-content">Recent Activity</h2>

src/lib/components/article-form/ArticleFormHeader.svelte

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
</script>
2727

2828
<header
29-
class="sticky top-0 z-20 flex items-center justify-between border-b border-zinc-200 bg-white px-4 py-3"
29+
class="sticky top-0 z-20 flex flex-wrap items-center justify-between gap-2 border-b border-zinc-200 bg-white px-3 py-2 sm:px-4 sm:py-3"
3030
>
31-
<div class="flex items-center gap-4">
31+
<div class="flex items-center gap-2 sm:gap-4">
3232
<button
3333
type="button"
3434
onclick={() => goto("/admin/articles")}
@@ -41,28 +41,28 @@
4141
<!-- Status Badge -->
4242
{#if published}
4343
<span
44-
class="flex items-center gap-1 rounded-full bg-emerald-50 px-2.5 py-1 text-xs font-medium text-emerald-700"
44+
class="flex items-center gap-1 rounded-full bg-emerald-50 px-2 py-0.5 text-xs font-medium text-emerald-700 sm:px-2.5 sm:py-1"
4545
>
4646
<Eye class="h-3 w-3" />
47-
Public
47+
<span class="hidden sm:inline">Public</span>
4848
</span>
4949
{:else}
5050
<span
51-
class="flex items-center gap-1 rounded-full bg-zinc-100 px-2.5 py-1 text-xs font-medium text-zinc-600"
51+
class="flex items-center gap-1 rounded-full bg-zinc-100 px-2 py-0.5 text-xs font-medium text-zinc-600 sm:px-2.5 sm:py-1"
5252
>
5353
<EyeOff class="h-3 w-3" />
54-
Draft
54+
<span class="hidden sm:inline">Draft</span>
5555
</span>
5656
{/if}
5757
</div>
5858

59-
<div class="flex items-center gap-2">
59+
<div class="flex items-center gap-1 sm:gap-2">
6060
<!-- Preview Button -->
6161
{#if articleId}
6262
<button
6363
type="button"
6464
onclick={openPreviewPage}
65-
class="flex items-center gap-1.5 rounded-lg px-3 py-2 text-sm text-zinc-600 transition-colors hover:bg-zinc-100 hover:text-zinc-900"
65+
class="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-sm text-zinc-600 transition-colors hover:bg-zinc-100 hover:text-zinc-900 sm:px-3 sm:py-2"
6666
>
6767
<ExternalLink class="h-4 w-4" />
6868
<span class="hidden sm:inline">Preview</span>
@@ -73,7 +73,7 @@
7373
<button
7474
type="button"
7575
onclick={() => (showSettings = !showSettings)}
76-
class="flex items-center gap-1.5 rounded-lg px-3 py-2 text-sm transition-colors {showSettings
76+
class="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-sm transition-colors sm:px-3 sm:py-2 {showSettings
7777
? 'bg-zinc-900 text-white'
7878
: 'text-zinc-600 hover:bg-zinc-100 hover:text-zinc-900'}"
7979
>
@@ -85,14 +85,15 @@
8585
<button
8686
type="submit"
8787
disabled={isSubmitting}
88-
class="inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-semibold text-white transition-all active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 {published
88+
class="inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-semibold text-white transition-all active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50 sm:gap-2 sm:px-4 sm:py-2 {published
8989
? 'bg-emerald-600 hover:bg-emerald-700'
9090
: 'bg-zinc-900 hover:bg-zinc-800'}"
9191
>
9292
{#if isSubmitting}
9393
<Loader2 class="h-4 w-4 animate-spin" />
9494
{/if}
95-
{published ? "Publish" : submitLabel}
95+
<span class="hidden sm:inline">{published ? "Publish" : submitLabel}</span>
96+
<span class="sm:hidden">Save</span>
9697
</button>
9798
</div>
9899
</header>

src/lib/components/article-form/ArticleSettings.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
</script>
3333

3434
{#if show}
35-
<aside class="w-80 shrink-0 overflow-y-auto border-l border-zinc-200 bg-zinc-50/50 lg:w-96">
35+
<aside class="fixed inset-0 z-30 overflow-y-auto bg-zinc-50 lg:static lg:w-80 lg:shrink-0 lg:border-l lg:border-zinc-200 lg:bg-zinc-50/50 xl:w-96">
3636
<div
37-
class="sticky top-0 flex items-center justify-between border-b border-zinc-200 bg-zinc-50/80 px-4 py-3 backdrop-blur-sm"
37+
class="sticky top-0 flex items-center justify-between border-b border-zinc-200 bg-zinc-50 px-4 py-3 backdrop-blur-sm lg:bg-zinc-50/80"
3838
>
3939
<h2 class="font-semibold text-zinc-900">Settings</h2>
4040
<button

0 commit comments

Comments
 (0)