refactor: convert to bun workspaces monorepo

- Move web app into apps/web/
- Create packages/shared/ with shared types
- Create plugins/decky-vault/ scaffold
- Root package.json manages workspaces only
This commit is contained in:
2026-06-28 05:20:28 +08:00
parent c4bede20d4
commit cd72b7a948
345 changed files with 488 additions and 126 deletions
+58
View File
@@ -0,0 +1,58 @@
import type { Metadata } from "next"
import { notFound } from "next/navigation"
import Link from "next/link"
import { ArrowLeftIcon } from "lucide-react"
import { getAllUpdateSlugs, getUpdateBySlug } from "@/lib/updates"
import { UpdateViewer } from "@/components/updates/update-viewer"
export async function generateStaticParams() {
const slugs = getAllUpdateSlugs()
return slugs.map((slug) => ({ slug }))
}
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>
}): Promise<Metadata> {
const { slug } = await params
let update
try {
update = await getUpdateBySlug(slug)
} catch {
return { title: "Update Not Found" }
}
return {
title: `${update.meta.title} | DeckyVault`,
description: update.meta.summary,
}
}
export default async function UpdatePage({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
let update
try {
update = await getUpdateBySlug(slug)
} catch {
notFound()
}
return (
<main className="w-full">
<div className="w-full max-w-7xl mx-auto px-4 pt-4">
<Link
href="/updates"
className="inline-flex items-center gap-1 text-sm text-text/60 hover:text-primary transition-colors"
>
<ArrowLeftIcon className="w-3 h-3" />
Back to updates
</Link>
</div>
<UpdateViewer update={update} />
</main>
)
}
+46
View File
@@ -0,0 +1,46 @@
import type { Metadata } from "next"
import Link from "next/link"
import { getAllUpdates } from "@/lib/updates"
import { UpdateCard } from "@/components/updates/update-card"
import { ArrowLeftIcon } from "lucide-react"
export const metadata: Metadata = {
title: "Updates",
description:
"See what's new in DeckyVault — version release notes, features, and improvements.",
}
export default function UpdatesPage() {
const updates = getAllUpdates()
return (
<main className='w-full max-w-7xl mx-auto px-4 py-8'>
<div className='flex flex-row items-center gap-2 mb-6'>
<Link
href='/'
className='text-text/60 hover:text-primary transition-colors'
>
<ArrowLeftIcon className='w-4 h-4' />
</Link>
<h1 className='text-2xl font-bold'>Updates</h1>
</div>
<p className='text-text/60 mb-8'>
Release notes, changelogs, and the like for DeckyVault.
</p>
{updates.length === 0 ? (
<p className='text-text/40 text-center py-16'>
No updates yet.
</p>
) : (
<div className='flex flex-col gap-3'>
{updates.map((update) => (
<UpdateCard
key={update.slug}
update={update}
/>
))}
</div>
)}
</main>
)
}