feat: 完成 A 群組 — 專案骨架與可重啟的服務

- packages/shared:TypeScript 專案參考建置鏈路、統一日誌模組(Asia/Taipei 格式)
- apps/api:最小 NestJS 服務,GET /health
- apps/web:最小 Next.js(App Router + Tailwind v4)首頁,套用品牌色票與亮暗模式
- scripts/dev-restart.mjs:讀 .dev-pids 以 process group 訊號安全停止舊行程、背景啟動 api/web 並輪詢健康檢查
- scripts/smoke:npm run smoke -- <群組代號> 冒煙測試框架,A 群組測試涵蓋 /health 與首頁內容
- 本機 port 3000 被既有服務佔用,web 開發埠改為 3100(已記錄於 todo.md)

npm run restart && npm run smoke -- A 皆通過(A-V)。
This commit is contained in:
Jeffery
2026-08-13 09:18:40 +08:00
parent 80b1383406
commit ae9c44dde7
29 changed files with 8991 additions and 8 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

+30
View File
@@ -0,0 +1,30 @@
@import "tailwindcss";
:root {
--color-heartbeat-pink: #ff7e9d;
--color-dusk-purple: #8c7ae6;
--background: #fff8fa;
--foreground: #3a3242;
}
@theme inline {
--color-heartbeat-pink: var(--color-heartbeat-pink);
--color-dusk-purple: var(--color-dusk-purple);
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #1a1430;
--foreground: #fff8fa;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: var(--font-sans), Arial, Helvetica, sans-serif;
}
+29
View File
@@ -0,0 +1,29 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "心音 Kokorone",
description: "心音(Kokorone)— 戀愛陪伴系統",
};
export default function RootLayout({ children }: LayoutProps<"/">) {
return (
<html
lang="zh-Hant"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">{children}</body>
</html>
);
}
+24
View File
@@ -0,0 +1,24 @@
export default function Home() {
return (
<main className="flex flex-1 flex-col items-center justify-center gap-8 p-8">
<h1 className="text-4xl font-bold tracking-wide">
心音 <span className="text-[var(--color-heartbeat-pink)]">Kokorone</span>
</h1>
<svg
viewBox="0 0 400 100"
className="w-full max-w-md text-[var(--color-heartbeat-pink)]"
role="img"
aria-label="心跳波形"
>
<polyline
points="0,50 60,50 80,50 95,15 110,85 125,50 160,50 180,50 195,25 210,75 225,50 400,50"
fill="none"
stroke="currentColor"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</main>
);
}