docs: migrate all planning docs from React to GoFiber + HTMX

- New ARCHITECTURE_HTMX.md — comprehensive HTMX architecture doc
- ARCHITECTURE.md — updated to point to HTMX version
- UI_COMPONENTS.md — replaced React tree with HTMX partials
- SPRINT_PLAN.md — all sprint tasks updated for HTMX
- BUILD_SYSTEM.md — simplified (no Vite, no npm)
- TIMELINE.md — 3.5 week HTMX timeline
- PROGRESS.md — updated status + HTMX
- AGENTS.md — updated checkpoint with HTMX decision
This commit is contained in:
swanadiva
2026-07-07 12:15:19 +07:00
parent c215d68c81
commit a0c8483c0e
8 changed files with 1442 additions and 2500 deletions
+109 -490
View File
@@ -1,564 +1,183 @@
# Hostkeeper V2 — Build System
> **Status**: V2 Planning Complete
> **Last Updated**: 2026-06-29
> **Status**: Updated untuk HTMX
> **Last Updated**: 2026-07-07
> **Frontend**: Go HTML template + HTMX + TailwindCSS v4 (tanpa Vite/npm/React)
---
## 1. Build Overview
Hostkeeper V2 produces **4 platform outputs** from a single codebase:
Hostkeeper V2 adalah **single Go binary** yang melayani HTML + static files.
| Platform | Output | Wrapper | Backend |
|----------|--------|---------|---------|
| macOS (ARM64) | `.dmg` | Electron | Go binary (embedded) |
| macOS (x64) | `.dmg` | Electron | Go binary (embedded) |
| Windows (x64) | `.exe` installer | Electron | Go binary (embedded) |
| Linux (x64) | `.AppImage` | Electron | Go binary (embedded) |
| Android (ARM64) | `.aab` / `.apk` | WebView | Go library (.aar) |
| macOS (ARM64) | `.dmg` | Electron (opsional) | Go binary |
| macOS (x64) | `.dmg` | Electron (opsional) | Go binary |
| Windows (x64) | `.exe` installer | Electron (opsional) | Go binary |
| Linux (x64) | `.AppImage` | Electron (opsional) | Go binary |
| Android (ARM64) | `.aab` | WebView | Go library (.aar) |
| iOS (ARM64) | `.ipa` | WKWebView | Go framework (.xcframework) |
**Catatan**: Tanpa Electron app tetap bisa jalan — tinggal buka `http://localhost:1947` di browser.
---
## 2. Build Pipeline
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
Go Build │ │ Frontend │ │ Electron │ │ Platform │
│ (backend) │ → │ Build │ → │ Package │ → │ Sign
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
┌──────────────┐ ┌─────────────┐ ┌─────────────
TailwindCSS │ │ Go Build │ │ Platform
│ Build │ → │ (single │ → │ Package
│ (CSS) │ │ binary) │ │ (opsional) │
└──────────────┘ └──────────────┘ └──────────────┘
```
### Step 1: Go Backend Cross-Compile
### Step 1: CSS Build
```bash
# macOS ARM64
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 \
go build -ldflags="-s -w" -o dist/hostkeeper-server .
# TailwindCSS v4 — input.css → output.css
npx @tailwindcss/cli -i static/css/input.css -o static/css/output.css
# macOS x64
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 \
go build -ldflags="-s -w" -o dist/hostkeeper-server .
# Windows x64
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 \
go build -ldflags="-s -w" -o dist/hostkeeper-server.exe .
# Linux x64
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="-s -w" -o dist/hostkeeper-server .
# Linux ARM64
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 \
go build -ldflags="-s -w" -o dist/hostkeeper-server .
# Atau via Makefile
make css
```
**Notes**:
- `CGO_ENABLED=0` — pure Go, no C dependencies
- `-ldflags="-s -w"` — strip debug info, reduce binary size
- Go binary size: ~15-20 MB (compressed)
### Step 2: Frontend Build
### Step 2: Go Build
```bash
cd app/frontend
npm ci
npm run build
# Output: app/frontend/dist/
# Development (hot reload via air)
go run .
# Production (single binary with embedded static)
CGO_ENABLED=0 go build -ldflags="-s -w" -o dist/hostkeeper .
# Cross-compile
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o dist/hostkeeper-darwin-arm64 .
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o dist/hostkeeper-linux-amd64 .
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o dist/hostkeeper-windows-amd64.exe .
```
**Vite config** (`app/frontend/vite.config.ts`):
```typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
outDir: 'dist',
sourcemap: false,
minify: 'terser',
rollupOptions: {
output: {
manualChunks: {
xterm: ['@xterm/xterm', '@xterm/addon-fit'],
react: ['react', 'react-dom'],
},
},
},
},
server: {
proxy: {
'/api': 'http://localhost:8080',
'/ws': {
target: 'ws://localhost:8080',
ws: true,
},
},
},
});
```
### Step 3: Electron Package
```yaml
# app/electron/electron-builder.yml
appId: com.hostkeeper.app
productName: Hostkeeper
copyright: Copyright © 2026
directories:
output: ../../dist
files:
- "**/*"
- "!**/node_modules/*/{CHANGELOG.md,README.md,readme.md,LICENSE}"
extraResources:
- from: "../backend/hostkeeper-server"
to: "hostkeeper-server"
- from: "../frontend/dist"
to: "frontend"
mac:
category: public.app-category.developer-tools
icon: assets/icon.icns
target:
- dmg
- zip
hardenedRuntime: true
notarize: true
win:
icon: assets/icon.ico
target:
- nsis
certificateFile: env.WIN_CERTIFICATE_FILE
linux:
icon: assets/icon.png
target:
- AppImage
- deb
category: Development
nsis:
oneClick: false
allowToChangeInstallationDirectory: true
```
---
## 3. Mobile Build
### Android
### Step 3: Elektron Package (Opsional)
```bash
# Prerequisites:
# - Android SDK installed
# - Go 1.26+ with gomobile
# - Java 17+
# Install gomobile
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
# Build Go library
cd mobile/gomobile
gomobile bind -target=android -o=../android/app/libs/hostkeeper.aar \
./go/
# Build Android app
cd ../android
./gradlew assembleRelease
# Output: mobile/android/app/build/outputs/apk/release/app-release.apk
```
### iOS
```bash
# Prerequisites:
# - Xcode 15+
# - Go 1.26+ with gomobile
# Build Go framework
cd mobile/gomobile
gomobile bind -target=ios -o=../ios/Hostkeeper/Hostkeeper.xcframework \
./go/
# Build iOS app
cd ../ios
xcodebuild -project Hostkeeper.xcodeproj \
-scheme Hostkeeper \
-sdk iphoneos \
-configuration Release
# Output: mobile/ios/build/Release-iphoneos/Hostkeeper.app
```
---
## 4. Build Scripts
### `scripts/build.sh` (Full Build)
```bash
#!/bin/bash
set -e
VERSION=${1:-"dev"}
PLATFORM=${2:-"all"}
echo "=== Building Hostkeeper V2 v${VERSION} ==="
# Step 1: Build Go backend
echo "Step 1: Building Go backend..."
cd app/backend
case $PLATFORM in
macos|all)
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w -X main.version=${VERSION}" -o ../electron/hostkeeper-server .
;;
windows|all)
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -X main.version=${VERSION}" -o ../electron/hostkeeper-server.exe .
;;
linux|all)
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=${VERSION}" -o ../electron/hostkeeper-server .
;;
esac
cd ../..
# Step 2: Build frontend
echo "Step 2: Building frontend..."
cd app/frontend
npm ci
npm run build
cd ../..
# Step 3: Package Electron
echo "Step 3: Packaging Electron..."
cd app/electron
case $PLATFORM in
macos)
npx electron-builder --mac --arm64
;;
windows)
npx electron-builder --win --x64
;;
linux)
npx electron-builder --linux --x64
;;
all)
npx electron-builder --mac --win --linux
;;
esac
cd ../..
# Step 4: Generate checksums
echo "Step 4: Generating checksums..."
cd dist
shasum -a 256 *.dmg *.exe *.AppImage 2>/dev/null > checksums.txt
echo "=== Build complete ==="
echo "Output: dist/"
ls -la dist/
```
### `scripts/build-mobile.sh`
```bash
#!/bin/bash
set -e
PLATFORM=${1:-"android"}
echo "=== Building Hostkeeper Mobile (${PLATFORM}) ==="
case $PLATFORM in
android)
cd mobile/gomobile
gomobile bind -target=android -o=../android/app/libs/hostkeeper.aar ./go/
cd ../android
./gradlew assembleRelease
echo "APK: mobile/android/app/build/outputs/apk/release/"
;;
ios)
cd mobile/gomobile
gomobile bind -target=ios -o=../ios/Hostkeeper/Hostkeeper.xcframework ./go/
cd ../ios
xcodebuild -project Hostkeeper.xcodeproj -scheme Hostkeeper -sdk iphoneos -configuration Release
echo "IPA: mobile/ios/build/Release-iphoneos/"
;;
esac
echo "=== Mobile build complete ==="
npm install
npm run build # produces .dmg / .exe / .AppImage
```
---
## 5. Development Workflow
### Quick Start
## 3. Development Workflow
```bash
# Terminal 1: Go backend
# Terminal 1: Go backend (dengan hot reload)
cd app/backend
go run .
# Terminal 2: Frontend (with hot reload)
cd app/frontend
npm run dev
# Terminal 2: CSS watch
cd app/backend
npx @tailwindcss/cli -i static/css/input.css -o static/css/output.css --watch
# Open browser: http://localhost:5173
# Buka browser
open http://localhost:1947
```
### With Electron
### Hot Reload Tools
```bash
# Terminal 1: Go backend
cd app/backend
go run .
# Install air
go install github.com/air-verse/air@latest
# Terminal 2: Frontend
cd app/frontend
npm run dev
# Terminal 3: Electron
cd app/electron
npm run dev
# Electron opens with hot reload
```
### VS Code Launch Config
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Go Backend",
"type": "go",
"request": "launch",
"program": "${workspaceFolder}/app/backend",
"cwd": "${workspaceFolder}/app/backend"
},
{
"name": "Electron",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/app/electron/node_modules/.bin/electron",
"args": ["."],
"cwd": "${workspaceFolder}/app/electron"
}
]
}
# Run
air
```
---
## 6. CI/CD (GitHub Actions)
```yaml
# .github/workflows/build.yml
name: Build
on:
push:
tags: ['v*']
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
- run: go test -race ./app/backend/...
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: cd app/frontend && npm ci && npm test
build-macos:
needs: test
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: ./scripts/build.sh ${{ github.ref_name }} macos
- uses: actions/upload-artifact@v4
with:
name: hostkeeper-macos
path: dist/*.dmg
build-windows:
needs: test
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: ./scripts/build.sh ${{ github.ref_name }} windows
- uses: actions/upload-artifact@v4
with:
name: hostkeeper-windows
path: dist/*.exe
build-linux:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: ./scripts/build.sh ${{ github.ref_name }} linux
- uses: actions/upload-artifact@v4
with:
name: hostkeeper-linux
path: dist/*.AppImage
```
---
## 7. Binary Size Optimization
| Technique | Impact |
|-----------|--------|
| `-ldflags="-s -w"` | -20% Go binary size |
| UPX compression (optional) | -60% Go binary size |
| Vite tree shaking | -40% JS bundle size |
| Code splitting (lazy load) | -30% initial load |
| Image optimization | -50% icon sizes |
| Terser minification | -30% JS size |
| CSS purging (Tailwind) | -80% CSS size |
**Target sizes**:
- Go backend binary: ~15 MB (5 MB compressed)
- Frontend dist: ~2 MB (500 KB compressed)
- Electron package: ~200 MB total
- Mobile APK: ~50 MB
- Mobile IPA: ~60 MB
---
## 8. Version Management
### Version Format
## 4. Struktur Build Output
```
vMAJOR.MINOR.PATCH
dist/
├── hostkeeper ← Go binary (single file)
├── static/ ← Embedded static assets
│ ├── css/
│ ├── js/
│ ├── xterm/
│ └── img/
└── views/ ← Embedded HTML templates
├── layout.html
└── partials/
```
- **MAJOR**: Breaking changes (data format, API)
- **MINOR**: New features
- **PATCH**: Bug fixes
### Version Injection
GoFiber `embed` package untuk embed static + views:
```go
// In main.go
var version = "dev"
//go:embed static/* views/*
var embedFS embed.FS
func main() {
fmt.Printf("Hostkeeper v%s\n", version)
// ...
app := fiber.New()
app.Static("/static", "./static")
engine := html.NewFileSystem(http.FS(embedFS), ".html")
app.Settings.Views = engine
}
```
```bash
# Build with version
go build -ldflags="-X main.version=v2.0.0" -o hostkeeper-server .
---
## 5. Dependencies
### Go
```
github.com/gofiber/fiber/v2
github.com/gofiber/contrib/websocket
github.com/gofiber/template/html/v2
github.com/fasthttp/websocket
```
### Changelog Format
### JavaScript (static files — download, bukan npm)
```markdown
## [v2.1.0] - 2026-07-15
```
static/js/htmx.min.js ← https://unpkg.com/htmx.org@2
static/js/alpine.min.js ← https://cdn.jsdelivr.net/npm/alpinejs@3
static/xterm/xterm.js ← https://unpkg.com/@xterm/xterm
static/xterm/xterm.css ← https://unpkg.com/@xterm/xterm/css
```
### Added
- Port forwarding support (local, remote, dynamic)
- Import from ~/.ssh/config
### CSS Tooling
### Changed
- Improved terminal performance with WebGL renderer
### Fixed
- Fixed SFTP upload progress not updating
- Fixed vault auto-lock not triggering on sleep
```
@tailwindcss/cli ← npx, build time only
```
---
## 9. Code Signing
## 6. Makefile
### macOS
```makefile
.PHONY: dev build css clean
```bash
# Requires Apple Developer account + certificates
export CSC_LINK="path/to/certificate.p12"
export CSC_KEY_PASSWORD="certificate-password"
dev:
@echo "Starting dev server..."
@go run .
# electron-builder handles signing + notarization
npx electron-builder --mac --publish always
```
### Windows
```bash
# Requires code signing certificate
export WIN_CERTIFICATE_FILE="path/to/certificate.pfx"
export WIN_CERTIFICATE_PASSWORD="certificate-password"
npx electron-builder --win --publish always
```
### Linux
No code signing required. AppImage is self-contained.
---
## 10. Release Workflow
```bash
# 1. Update version
npm version minor # or major, patch
# 2. Update CHANGELOG.md
# 3. Commit
git add .
git commit -m "chore: release v2.1.0"
# 4. Tag
git tag -a v2.1.0 -m "Release v2.1.0"
# 5. Push
git push origin main --tags
# 6. GitHub Actions builds + publishes artifacts
# 7. Create GitHub Release
gh release create v2.1.0 \
--title "Hostkeeper v2.1.0" \
--notes-file CHANGELOG.md \
dist/*.dmg dist/*.exe dist/*.AppImage
css:
npx @tailwindcss/cli -i static/css/input.css -o static/css/output.css
css-watch:
npx @tailwindcss/cli -i static/css/input.css -o static/css/output.css --watch
build:
CGO_ENABLED=0 go build -ldflags="-s -w" -o dist/hostkeeper .
build-all:
GOOS=darwin GOARCH=arm64 go build -o dist/hostkeeper-darwin-arm64 .
GOOS=darwin GOARCH=amd64 go build -o dist/hostkeeper-darwin-amd64 .
GOOS=linux GOARCH=amd64 go build -o dist/hostkeeper-linux-amd64 .
GOOS=windows GOARCH=amd64 go build -o dist/hostkeeper-windows-amd64.exe .
clean:
rm -rf dist/
```