diff --git a/README.md b/README.md index 87b4957..e0669bf 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,66 @@ -# 🐱 CatSave - Go + Next.js Monorepo +# 🐱 NekoFlow - Go + Next.js Monorepo -Single binary application with Go backend + Next.js frontend. +[](README.md) +[](README.vi.md) -## 📦 Structure +> **[Đọc bằng tiếng Việt](README.vi.md)** + +Single binary application combining Go backend with Next.js frontend. + +## 📦 Project Structure ``` -catsave/ +nekoflow/ ├── apps/ -│ ├── web/ # Next.js frontend (static export) -│ └── server-go/ # Go backend + static file server +│ ├── web/ # Next.js 14 (Frontend - Static Export) +│ └── server-go/ # Go backend + Static file server ├── scripts/ # Build scripts └── dist/ # Build output ``` -## 🚀 Development +## 🚀 Quick Start + +### Prerequisites +- Node.js 18+ +- Go 1.21+ + +### Installation -### Quick Start ```bash # 1. Install dependencies npm install -# 2. Option A: Dev Next.js only +# 2. Option A: Dev Next.js only (with hot reload) npm run dev:web # http://localhost:3000 -# 3. Option B: Dev with Go +# 3. Option B: Full stack with Go npm run build:dev # Build Next.js + sync to Go -npm run dev:go # Run Go server +npm run dev:go # Run Go server → http://localhost:8080 ``` -### Workflow +## 💻 Development -**Frontend Development (Next.js):** +### Frontend Development (Next.js) ```bash -npm run dev:web # Hot reload on :3000 +npm run dev:web # Hot reload on port 3000 ``` -**Full Stack Development (Next.js + Go):** +### Full Stack Development (Next.js + Go) + +**Terminal 1: Build & sync when you change Next.js code** ```bash -# Terminal 1: Build & sync on changes npm run build:dev +``` -# Terminal 2: Run Go server +**Terminal 2: Run Go server** +```bash npm run dev:go # http://localhost:8080 ``` **After changing Next.js code:** ```bash npm run build:dev # Re-build and sync -# Go server will auto-serve new files +# Go server will auto-serve new files (no restart needed) ``` ## 🔨 Build @@ -62,38 +75,134 @@ npm run build:dev ```bash npm run build # → Builds Next.js + Go binary -# → Output: dist/catsave (single binary) +# → Output: dist/nekoflow (single binary ~10-30MB) ``` ### Available Commands + | Command | Description | |---------|-------------| -| `npm run dev:web` | Dev Next.js only (port 3000) | +| `npm run dev:web` | Dev Next.js only (port 3000, hot reload) | | `npm run dev:go` | Run Go server (port 8080) | | `npm run build:web` | Build Next.js static export | -| `npm run sync:static` | Copy Next.js → Go static | -| `npm run build:dev` | Build + sync (development) | -| `npm run build` | Full production build | +| `npm run sync:static` | Copy Next.js build → Go static folder | +| `npm run build:dev` | Build + sync (for development) | +| `npm run build` | Full production build (creates binary) | ## 🎯 Deploy +### Simple Deployment ```bash -# Just copy the binary -./dist/catsave +# Just copy and run the binary +./dist/nekoflow -# Runs on http://localhost:8080 +# Or specify port +PORT=8080 ./dist/nekoflow +``` + +### Deploy to Linux Server +```bash +# 1. Build for Linux +npm run build + +# 2. Upload +scp dist/nekoflow-linux user@server:/opt/nekoflow + +# 3. Run on server +ssh user@server +chmod +x /opt/nekoflow +./nekoflow +``` + +### Docker (Optional) +```dockerfile +FROM scratch +COPY dist/nekoflow /nekoflow +ENTRYPOINT ["/nekoflow"] ``` ## 🏗️ Architecture -- **Go**: API + serve static files (embedded) -- **Next.js**: Static export (HTML/CSS/JS) -- **Result**: One binary file (~10-30MB) +### How It Works -## 📝 Tech Stack +``` +┌─────────────────────────────────────┐ +│ Single Binary (nekoflow) │ +│ │ +│ ┌────────────┐ ┌──────────────┐ │ +│ │ Go Server │ │ Static Files │ │ +│ │ │ │ (Next.js) │ │ +│ │ - API │ │ - HTML │ │ +│ │ - Router │ │ - CSS │ │ +│ │ - Embedded │ │ - JS │ │ +│ └────────────┘ └──────────────┘ │ +└─────────────────────────────────────┘ + ↓ + Single Port (8080) + ↓ + ┌─────────────┐ + │ Browser │ + │ - UI │ + │ - API call │ + └─────────────┘ +``` -- Go 1.21+ -- Next.js 14 +### Tech Stack + +**Frontend:** +- Next.js 14 (Static Export) +- React 18 - TypeScript - Tailwind CSS +**Backend:** +- Go 1.21+ +- gorilla/mux (Router) +- embed (Static files) + +**Build:** +- npm workspaces +- Bash scripts +- Go build + +## ❓ FAQ + +### Is this SSR (Server-Side Rendering)? +**No.** This uses Next.js **Static Export** (SSG - Static Site Generation). +- Next.js pre-renders pages to HTML at build time +- Go only serves static files (HTML/CSS/JS) +- React hydrates on the client-side +- API calls happen client-side via `fetch()` + +### Can I use getServerSideProps? +**No.** Static Export doesn't support: +- `getServerSideProps()` +- `getServerData()` +- ISR (Incremental Static Regeneration) + +Use `'use client'` with `useEffect()` and `fetch()` instead. + +### Why Go + Next.js? +- ✅ **Single binary** - Easy deployment +- ✅ **No Node.js runtime** needed in production +- ✅ **Performance** - Go is fast and lightweight +- ✅ **Modern DX** - React + TypeScript + Tailwind +- ✅ **Cross-platform** - Compile for Linux/Mac/Windows + +### Binary size? +Typically **10-30MB** depending on: +- Go code size +- Next.js bundle size +- Static assets (images, fonts) + +## 📝 License + +MIT + +## 🤝 Contributing + +Contributions welcome! Feel free to open issues or PRs. + +--- + +**Built with ❤️ using Go + Next.js + TypeScript** diff --git a/README.vi.md b/README.vi.md new file mode 100644 index 0000000..dff6f71 --- /dev/null +++ b/README.vi.md @@ -0,0 +1,226 @@ +# 🐱 NekoFlow - Monorepo Go + Next.js + +[](README.md) +[](README.vi.md) + +> **[Read in English](README.md)** + +Ứng dụng single binary kết hợp Go backend với Next.js frontend. + +## 📦 Cấu Trúc Dự Án + +``` +nekoflow/ +├── apps/ +│ ├── web/ # Next.js 14 (Frontend - Static Export) +│ └── server-go/ # Go backend + Static file server +├── scripts/ # Build scripts +└── dist/ # Build output +``` + +## 🚀 Bắt Đầu Nhanh + +### Yêu Cầu +- Node.js 18+ +- Go 1.21+ + +### Cài Đặt + +```bash +# 1. Cài dependencies +npm install + +# 2. Tùy chọn A: Dev chỉ Next.js (có hot reload) +npm run dev:web # http://localhost:3000 + +# 3. Tùy chọn B: Full stack với Go +npm run build:dev # Build Next.js + sync sang Go +npm run dev:go # Chạy Go server → http://localhost:8080 +``` + +## 💻 Phát Triển + +### Phát Triển Frontend (Next.js) +```bash +npm run dev:web # Hot reload trên port 3000 +``` + +### Phát Triển Full Stack (Next.js + Go) + +**Terminal 1: Build & sync khi sửa code Next.js** +```bash +npm run build:dev +``` + +**Terminal 2: Chạy Go server** +```bash +npm run dev:go # http://localhost:8080 +``` + +**Sau khi sửa code Next.js:** +```bash +npm run build:dev # Build lại và sync +# Go server tự động serve files mới (không cần restart) +``` + +## 🔨 Build + +### Development Build (Nhanh) +```bash +npm run build:dev +# → Build Next.js + sync vào folder static của Go +``` + +### Production Binary +```bash +npm run build +# → Build Next.js + Go binary +# → Output: dist/nekoflow (single binary ~10-30MB) +``` + +### Các Lệnh Có Sẵn + +| Lệnh | Mô Tả | +|------|-------| +| `npm run dev:web` | Dev Next.js riêng (port 3000, hot reload) | +| `npm run dev:go` | Chạy Go server (port 8080) | +| `npm run build:web` | Build Next.js static export | +| `npm run sync:static` | Copy Next.js build → folder static của Go | +| `npm run build:dev` | Build + sync (cho development) | +| `npm run build` | Build production đầy đủ (tạo binary) | + +## 🎯 Deploy + +### Deploy Đơn Giản +```bash +# Chỉ cần copy và chạy binary +./dist/nekoflow + +# Hoặc chỉ định port +PORT=8080 ./dist/nekoflow +``` + +### Deploy Lên Linux Server +```bash +# 1. Build cho Linux +npm run build + +# 2. Upload +scp dist/nekoflow-linux user@server:/opt/nekoflow + +# 3. Chạy trên server +ssh user@server +chmod +x /opt/nekoflow +./nekoflow +``` + +### Docker (Tùy Chọn) +```dockerfile +FROM scratch +COPY dist/nekoflow /nekoflow +ENTRYPOINT ["/nekoflow"] +``` + +## 🏗️ Kiến Trúc + +### Cách Hoạt Động + +``` +┌─────────────────────────────────────┐ +│ Single Binary (nekoflow) │ +│ │ +│ ┌────────────┐ ┌──────────────┐ │ +│ │ Go Server │ │ Static Files │ │ +│ │ │ │ (Next.js) │ │ +│ │ - API │ │ - HTML │ │ +│ │ - Router │ │ - CSS │ │ +│ │ - Embedded │ │ - JS │ │ +│ └────────────┘ └──────────────┘ │ +└─────────────────────────────────────┘ + ↓ + Single Port (8080) + ↓ + ┌─────────────┐ + │ Browser │ + │ - UI │ + │ - API call │ + └─────────────┘ +``` + +### Tech Stack + +**Frontend:** +- Next.js 14 (Static Export) +- React 18 +- TypeScript +- Tailwind CSS + +**Backend:** +- Go 1.21+ +- gorilla/mux (Router) +- embed (Static files) + +**Build:** +- npm workspaces +- Bash scripts +- Go build + +## ❓ Câu Hỏi Thường Gặp + +### Đây có phải SSR (Server-Side Rendering)? +**Không.** Dự án này dùng Next.js **Static Export** (SSG - Static Site Generation). +- Next.js pre-render pages thành HTML tại thời điểm build +- Go chỉ serve static files (HTML/CSS/JS) +- React hydrate trên client-side +- API calls xảy ra client-side qua `fetch()` + +### Có thể dùng getServerSideProps? +**Không.** Static Export không hỗ trợ: +- `getServerSideProps()` +- `getServerData()` +- ISR (Incremental Static Regeneration) + +Dùng `'use client'` với `useEffect()` và `fetch()` thay thế. + +### Tại sao Go + Next.js? +- ✅ **Single binary** - Deploy dễ dàng +- ✅ **Không cần Node.js runtime** trong production +- ✅ **Performance** - Go nhanh và nhẹ +- ✅ **Modern DX** - React + TypeScript + Tailwind +- ✅ **Cross-platform** - Compile cho Linux/Mac/Windows + +### Kích thước binary? +Thường **10-30MB** tùy thuộc: +- Kích thước code Go +- Bundle size của Next.js +- Static assets (hình ảnh, fonts) + +### Next.js chỉ là tool để code HTML/CSS/JS dễ hơn? +**Đúng!** Với Static Export: +- Next.js giúp code dễ hơn (React, TypeScript, Components) +- Build ra HTML/CSS/JS thuần +- Go chỉ serve files tĩnh +- Giống như bạn tự viết HTML/CSS/JS nhưng với DX tốt hơn + +### HTML của Next.js có gọi Go API? +**Có!** Flow hoạt động: +1. User vào http://localhost:8080 +2. Go serve index.html (static) +3. Browser load HTML + React JS +4. React code chạy: `fetch('/api/health')` +5. Request về Go API endpoint +6. Go trả JSON response +7. React update UI + +## 📝 License + +MIT + +## 🤝 Đóng Góp + +Chào mừng mọi đóng góp! Thoải mái mở issues hoặc PRs. + +--- + +**Built with ❤️ using Go + Next.js + TypeScript** + diff --git a/apps/server-go/go.mod b/apps/server-go/go.mod index 83efee6..df4466f 100644 --- a/apps/server-go/go.mod +++ b/apps/server-go/go.mod @@ -1,4 +1,4 @@ -module github.com/catsave/server +module github.com/nekoflow/server go 1.21 diff --git a/apps/server-go/main.go b/apps/server-go/main.go index 3fda051..f932072 100644 --- a/apps/server-go/main.go +++ b/apps/server-go/main.go @@ -43,7 +43,7 @@ func main() { port = "8080" } - log.Printf("🚀 CatSave server starting on http://localhost:%s\n", port) + log.Printf("🚀 NekoFlow server starting on http://localhost:%s\n", port) log.Printf("📱 Web UI: http://localhost:%s\n", port) log.Printf("🔌 API: http://localhost:%s/api/health\n", port) @@ -57,7 +57,7 @@ func healthHandler(w http.ResponseWriter, r *http.Request) { response := HealthResponse{ Status: "ok", - Message: "Go backend is running! 🐹", + Message: "NekoFlow Go backend is running! 🐹", Timestamp: time.Now().Format(time.RFC3339), } diff --git a/apps/web/package.json b/apps/web/package.json index 013a74c..a8ee571 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,5 +1,5 @@ { - "name": "@catsave/web", + "name": "@nekoflow/web", "version": "1.0.0", "private": true, "scripts": { diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index cd34c7e..76701b3 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -2,7 +2,7 @@ import type { Metadata } from 'next' import './globals.css' export const metadata: Metadata = { - title: 'CatSave', + title: 'NekoFlow', description: 'Go + Next.js Single Binary Application', } diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index 42ad01e..c6802d7 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -21,7 +21,7 @@ export default function Home() { 🐱
Go + Next.js Single Binary diff --git a/package.json b/package.json index 57a964b..268dbca 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { - "name": "catsave-monorepo", + "name": "nekoflow-monorepo", "version": "1.0.0", "private": true, "workspaces": [ "apps/web" ], "scripts": { - "dev:web": "npm --workspace @catsave/web run dev", + "dev:web": "npm --workspace @nekoflow/web run dev", "dev:go": "cd apps/server-go && go run main.go", - "build:web": "npm --workspace @catsave/web run build", + "build:web": "npm --workspace @nekoflow/web run build", "sync:static": "bash scripts/sync-static.sh", "build:dev": "npm run build:web && npm run sync:static", "build:go": "bash scripts/build-go.sh", diff --git a/scripts/build-go.sh b/scripts/build-go.sh index 695cf67..3d34bf0 100644 --- a/scripts/build-go.sh +++ b/scripts/build-go.sh @@ -1,6 +1,6 @@ #!/bin/bash -echo "🔨 Building CatSave Single Binary..." +echo "🔨 Building NekoFlow Single Binary..." # Colors GREEN='\033[0;32m' @@ -36,31 +36,31 @@ cd apps/server-go go mod download # Build for Linux -GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ../../dist/catsave-linux main.go -echo " ✅ Built: dist/catsave-linux" +GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ../../dist/nekoflow-linux main.go +echo " ✅ Built: dist/nekoflow-linux" # Build for current OS -go build -ldflags="-s -w" -o ../../dist/catsave main.go -echo " ✅ Built: dist/catsave" +go build -ldflags="-s -w" -o ../../dist/nekoflow main.go +echo " ✅ Built: dist/nekoflow" cd ../.. # Get file sizes -SIZE_LINUX=$(du -h dist/catsave-linux 2>/dev/null | cut -f1) -SIZE_LOCAL=$(du -h dist/catsave 2>/dev/null | cut -f1) +SIZE_LINUX=$(du -h dist/nekoflow-linux 2>/dev/null | cut -f1) +SIZE_LOCAL=$(du -h dist/nekoflow 2>/dev/null | cut -f1) echo "" echo -e "${GREEN}✅ Build complete!${NC}" echo "" echo "📦 Output:" -echo " - dist/catsave (${SIZE_LOCAL:-N/A})" -echo " - dist/catsave-linux (${SIZE_LINUX:-N/A})" +echo " - dist/nekoflow (${SIZE_LOCAL:-N/A})" +echo " - dist/nekoflow-linux (${SIZE_LINUX:-N/A})" echo "" echo -e "${YELLOW}To run:${NC}" -echo " ./dist/catsave" +echo " ./dist/nekoflow" echo "" echo -e "${YELLOW}To deploy to Linux server:${NC}" -echo " scp dist/catsave-linux user@server:/opt/catsave" -echo " ssh user@server '/opt/catsave'" +echo " scp dist/nekoflow-linux user@server:/opt/nekoflow" +echo " ssh user@server '/opt/nekoflow'" echo ""