# Implementation: Homarr + Portfolio via Terraform ## Phase 1: Portfolio Site (Local Dev) ### 1.1 Initialize Next.js project ```bash cd ~/workplace/riotpiao npm init -y npm install next@15 react@19 react-dom@19 typescript tailwindcss postcss autoprefixer npx tailwindcss init -p npx tsc --init ``` **`tsconfig.json`:** ```json { "compilerOptions": { "target": "ES2020", "lib": ["ES2020", "DOM", "DOM.Iterable"], "jsx": "react-jsx", "module": "ESNext", "moduleResolution": "bundler", "resolveJsonModule": true, "strict": true, "skipLibCheck": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, "baseUrl": ".", "paths": { "@/*": ["./*"] } }, "include": ["**/*.ts", "**/*.tsx"], "exclude": ["node_modules", ".next"] } ``` **`next.config.js`:** ```javascript /** @type {import('next').NextConfig} */ const nextConfig = { output: 'standalone', reactStrictMode: true, }; module.exports = nextConfig; ``` **`package.json` (key fields):** ```json { "name": "riotpiao-portfolio", "version": "1.0.0", "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "eslint ." } } ``` ### 1.2 App Router structure **`app/layout.tsx`:** ```typescript import "@/styles/globals.css"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; export const metadata = { title: "Rock Liang — Portfolio & Demos", description: "Software engineer showcasing live demos and open-source projects.", openGraph: { title: "Rock Liang", description: "Portfolio and interactive demo platform", url: "https://portfolio.riotpiao.homelab.com", images: [ { url: "https://portfolio.riotpiao.homelab.com/og-image.png", width: 1200, height: 630, }, ], }, }; export default function RootLayout({ children }: { children: React.ReactNode }) { return (
{children}