diff --git a/frontend/.dockerignore b/frontend/.dockerignore
new file mode 100644
index 0000000..b9ed5c4
--- /dev/null
+++ b/frontend/.dockerignore
@@ -0,0 +1,136 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+.temp
+.cache
+
+# vitepress build output
+**/.vitepress/dist
+
+# vitepress cache directory
+**/.vitepress/cache
+
+# Docusaurus cache and generated files
+.docusaurus
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# yarn v2
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
\ No newline at end of file
diff --git a/frontend/Dockerfile b/frontend/Dockerfile
new file mode 100644
index 0000000..fb93121
--- /dev/null
+++ b/frontend/Dockerfile
@@ -0,0 +1,15 @@
+FROM node:20-alpine as pnpm
+RUN apk add pnpm
+
+FROM pnpm as build
+WORKDIR /app
+COPY . .
+RUN apk add pnpm && pnpm install && pnpm run build
+
+FROM pnpm as production
+WORKDIR /app
+COPY . .
+COPY --from=build /app/.next .next
+RUN pnpm install --prod
+EXPOSE 3000
+CMD ["pnpm", "run", "start"]
diff --git a/frontend/public/file.svg b/frontend/public/file.svg
deleted file mode 100644
index 004145c..0000000
--- a/frontend/public/file.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/public/globe.svg b/frontend/public/globe.svg
deleted file mode 100644
index 567f17b..0000000
--- a/frontend/public/globe.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/public/icon/logo-dark.svg b/frontend/public/icon/logo-dark.svg
new file mode 100644
index 0000000..d84a437
--- /dev/null
+++ b/frontend/public/icon/logo-dark.svg
@@ -0,0 +1,107 @@
+
+
+
+
diff --git a/frontend/public/icon/logo-light.svg b/frontend/public/icon/logo-light.svg
new file mode 100644
index 0000000..05865cf
--- /dev/null
+++ b/frontend/public/icon/logo-light.svg
@@ -0,0 +1,107 @@
+
+
+
+
diff --git a/frontend/public/next.svg b/frontend/public/next.svg
deleted file mode 100644
index 5174b28..0000000
--- a/frontend/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/public/vercel.svg b/frontend/public/vercel.svg
deleted file mode 100644
index 7705396..0000000
--- a/frontend/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/public/window.svg b/frontend/public/window.svg
deleted file mode 100644
index b2b2a44..0000000
--- a/frontend/public/window.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/src/app/HackNerdMono.woff2 b/frontend/src/app/_font/HackNerdMono.woff2
similarity index 100%
rename from frontend/src/app/HackNerdMono.woff2
rename to frontend/src/app/_font/HackNerdMono.woff2
diff --git a/frontend/src/app/favicon.ico b/frontend/src/app/favicon.ico
deleted file mode 100644
index 718d6fe..0000000
Binary files a/frontend/src/app/favicon.ico and /dev/null differ
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index c63d8d6..6d55e89 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -18,13 +18,27 @@ const notoSansMono = Noto_Sans_Mono({
});
const hackNerdMono = localFont({
- src: "./HackNerdMono.woff2",
+ src: "./_font/HackNerdMono.woff2",
variable: "--font-hack-nerd-mono",
});
export const metadata: Metadata = {
title: "魚之魷魂 SquidSpirit",
description: "程式、科技、教學、分享",
+ icons: {
+ icon: [
+ {
+ media: "(prefers-color-scheme: light)",
+ url: "/icon/logo-light.svg",
+ href: "/icon/logo-light.svg",
+ },
+ {
+ media: "(prefers-color-scheme: dark)",
+ url: "/icon/logo-dark.svg",
+ href: "/icon/logo-dark.svg",
+ },
+ ],
+ },
};
export default function RootLayout({