Complete guide for GitOps-based Application management: - App of Apps pattern explanation - One-time bootstrap setup - Daily usage (100% Git-based) - Self-healing demonstration - Troubleshooting guide - Complete GitOps workflow Key benefits: ✅ Only ONE manual kubectl command (bootstrap) ✅ All other operations via git commit + push ✅ Auto-create/delete Applications from Git ✅ Self-healing against manual changes ✅ Full audit trail via Git history Aligns with PROMPT_BLUEPRINT_V2.md Section 8: GitOps Deployment 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
LJWX Website
Official website for OmniVerse / Lingjing Wanxiang (灵境万象). Built with React 18, TypeScript, and Vite.
Table of Contents
- Overview
- Technology Stack
- Getting Started
- Development
- Content Management
- Deployment
- GitOps Workflow
- Project Structure
- Available Scripts
Overview
This is the official marketing and information website for the OmniVerse platform. It provides information about our products, services, and company.
Live URL: https://www.lingjingwanxiang.cn
Technology Stack
- Frontend Framework: React 18.3
- Build Tool: Vite 5.4
- Language: TypeScript
- Routing: React Router v7
- Styling: Tailwind CSS
- Animation: Framer Motion
- Internationalization: i18next
- Deployment: Kubernetes with GitOps (Argo CD)
- Container Registry: Harbor
- Web Server: Nginx (production)
Getting Started
Prerequisites
- Node.js 20 or higher
- npm or pnpm
Installation
# Clone the repository
git clone https://github.com/BrunoGaoSZ/ljwx-website.git
cd ljwx-website
# Install dependencies
npm install
# or
pnpm install
Development
Local Development
# Start development server with hot reload
npm run dev
# Access the application at http://localhost:5173
Build for Production
# Create production build
npm run build
# Preview production build locally
npm run preview
Linting and Type Checking
# Run ESLint
npm run lint
# Run TypeScript type checking
npm run type-check
Content Management
The website uses a markdown-based content management system that makes it easy to add and update content without touching React code.
Quick Content Creation
Create new content using interactive CLI tools:
# Create a blog post
npm run content:create:blog
# Create an article
npm run content:create:article
# Create documentation
npm run content:create:doc
# Create a project showcase
npm run content:create:project
Content Validation
Validate your markdown files for proper structure and Front Matter:
# Validate all content
npm run content:validate
# Validate specific file
node scripts/validate-content.js src/content/blog/my-post.md
Content Index Generation
Generate a searchable index of all content:
# Generate content index
npm run content:index
# Validate and index in one command
npm run content:init
Hot Module Replacement
When running npm run dev, markdown files are watched and the page automatically reloads when you save changes to any .md file in src/content/.
Content Types and Locations
- Blog Posts:
src/content/blog/- Company news and announcements - Articles:
src/content/articles/- Technical articles and insights - Documentation:
src/content/docs/- API docs and guides - Projects:
src/content/projects/- Product showcases and case studies
Complete Guide
See docs/CONTENT-MANAGEMENT-GUIDE.md for:
- Detailed Front Matter schemas
- Best practices for content creation
- Image management
- SEO optimization
- Troubleshooting
See docs/CONTENT-OPTIMIZATION-PLAN.md for:
- System architecture analysis
- Optimization strategies
- Implementation roadmap
Deployment
This project supports three deployment methods:
Option 1: Direct Deployment (Quick Deploy) ⚡
Recommended for quick deployments and testing
# One-click build, push to Harbor, and deploy to K8s
cd scripts
./one-click-deploy.sh
See QUICK-DEPLOY-GUIDE.md for detailed instructions.
Features:
- ✅ Interactive deployment with progress display
- ✅ Builds Docker image
- ✅ Pushes to Harbor registry
- ✅ Deploys to K8s
websitenamespace - ✅ Configures Traefik Ingress with TLS
- ✅ Health check verification
Option 2: Gitea CI/CD (Local/Self-hosted) 🏠
Recommended for local development and private deployments
This project uses Gitea Actions for fully localized CI/CD without external dependencies.
Deployment Architecture:
Gitea Push → Gitea Actions → Harbor Registry → ljwx-deploy Update → Argo CD → Kubernetes
Key Features:
- ✅ Fully Localized: No external dependencies (GitHub, Docker Hub, PyPI)
- ✅ Custom CI Image: Pre-built image with Node.js, git, yq
- ✅ Dual Runner Architecture:
- K8s Runner (
ubuntu-latest) - Fast lint/test with container - Host Runner (
docker-builder,macos) - Docker builds with buildx
- K8s Runner (
- ✅ Multi-arch Support: Builds for linux/amd64 and linux/arm64
- ✅ Auto-deployment: Updates deployment repo after successful build
Gitea Instance:
- URL: http://192.168.1.83:33000
- Repository: http://192.168.1.83:33000/gao/ljwx-website
- Actions: http://192.168.1.83:33000/gao/ljwx-website/actions
Automated Deployment Process:
- Push to main branch triggers Gitea Actions workflow
- Lint & Test Job runs on K8s runner:
- Container:
harbor.omniverseai.net/ljwx/ci-node:20 - Executes:
npm ci,npm run lint,npm run type-check,npm test
- Container:
- Build & Push Job runs on host runner (
docker-builder):- Builds Docker image with buildx (multi-arch)
- Tags:
main-<short-sha>andlatest - Pushes to Harbor:
harbor.omniverseai.net/ljwx/ljwx-website
- Update Deploy Job runs on K8s runner:
- Clones
ljwx-deployrepository - Updates image tag in
apps/ljwx-website/overlays/eu-dev/values.yaml - Commits and pushes directly to main branch
- Clones
- Argo CD detects change and syncs to Kubernetes cluster
Runner Configuration:
Host Runner (for Docker builds):
Labels:
- docker-builder:host
- macos:host
- self-hosted:host
K8s Runner (for lint/test):
Labels:
- ubuntu-latest:docker://harbor.omniverseai.net/ljwx/ci-node:20
Monitor Workflow:
# Watch workflow execution in real-time
./.gitea/watch-workflow.sh
# Check runner status
tail -f /Users/brunogao/gitea-runners/runner3/runner.log
# View workflow runs
# Visit: http://192.168.1.83:33000/gao/ljwx-website/actions
Trigger Deployment:
# Push to local Gitea instance
git push local main
# Check workflow status
curl -s http://192.168.1.83:33000/gao/ljwx-website/actions
Option 3: GitHub Actions CI/CD (Cloud) ☁️
Recommended for production deployments with GitHub
This project also supports GitHub Actions for cloud-based CI/CD.
Deployment Architecture:
GitHub Push → GitHub Actions → Harbor Registry → ljwx-deploy Update → Argo CD → Kubernetes
Live Environments:
- Production: https://www.lingjingwanxiang.cn
- Alternative: https://lingjingwanxiang.cn
Automated Deployment Process:
- Push to main branch triggers GitHub Actions CI/CD pipeline
- CI Pipeline runs:
- Lint and type checking
- Unit tests (if configured)
- Docker image build (multi-stage with Nginx)
- Image Push to Harbor registry:
harbor.eu.lingjingwanxiang.cn/ljwx/ljwx-website - GitOps Update: CI automatically commits new image tag to ljwx-deploy repository
- Argo CD detects change and syncs to Kubernetes cluster
- Rolling Update deploys new version with zero downtime
GitHub Secrets Required:
HARBOR_USERNAME: Harbor registry usernameHARBOR_PASSWORD: Harbor registry passwordDEPLOY_REPO_TOKEN: GitHub Personal Access Token with write access to ljwx-deploy
Manual Deployment
If needed, you can manually update the deployment:
# Update image tag in ljwx-deploy repository
cd ljwx-deploy
yq eval '.website.image.tag = "main-abc1234"' \
-i apps/ljwx-website/overlays/eu-dev/values.yaml
git add . && git commit -m "chore: update ljwx-website" && git push
GitOps Workflow
Helm Chart Structure
deploy/
├── helm/app/
│ ├── Chart.yaml # Helm chart metadata
│ ├── values.yaml # Default values
│ └── templates/
│ ├── _helpers.tpl # Template helpers
│ ├── deployment.yaml # Kubernetes Deployment
│ ├── service.yaml # Kubernetes Service
│ └── ingress.yaml # Traefik Ingress
└── environments/
├── dev-eu.yaml # EU dev environment overlay
└── prod.yaml # Production environment overlay
Key Configuration
Image: harbor.omniverseai.net/ljwx/ljwx-website:main-<sha>
Resources (dev):
- CPU: 25m request, 50m limit
- Memory: 32Mi request, 64Mi limit
Ingress:
- Class: traefik
- Host: website.lingjingwanxiang.cn
- TLS: Enabled
Project Structure
ljwx-website/
├── .github/workflows/
│ └── ci.yml # GitHub Actions CI/CD pipeline
├── .gitea/workflows/
│ ├── ci.yaml # Gitea Actions CI/CD pipeline
│ ├── watch-workflow.sh # Workflow monitoring script
│ └── monitor-workflow.sh # Alternative monitoring script
├── deploy/
│ ├── helm/app/ # Helm chart
│ └── environments/ # Environment overlays
├── k8s/
│ ├── website-lingjingwanxiang.yaml # K8s manifest for direct deployment
│ └── production.yaml # Legacy production manifest
├── scripts/
│ ├── one-click-deploy.sh # Interactive build-push-deploy script
│ ├── quick-build-push-deploy.sh # Fast deployment script
│ ├── test-deployment-readiness.sh # Pre-deployment checks
│ ├── setup-all.sh # Complete GitOps setup
│ ├── setup-harbor.sh # Harbor configuration
│ ├── setup-github-secrets.sh # GitHub secrets setup
│ ├── deploy-argocd.sh # Argo CD deployment
│ └── README.md # Scripts documentation
├── public/ # Static assets
├── src/
│ ├── assets/ # Images, fonts, etc.
│ ├── components/ # React components
│ ├── pages/ # Page components
│ ├── hooks/ # Custom React hooks
│ ├── utils/ # Utility functions
│ ├── i18n/ # Internationalization
│ ├── App.tsx # Root component
│ └── main.tsx # Entry point
├── Dockerfile # Multi-stage production build
├── nginx.conf # Nginx configuration
├── vite.config.ts # Vite configuration
├── tsconfig.json # TypeScript configuration
├── QUICK-DEPLOY-GUIDE.md # Quick deployment guide
├── CLAUDE.md # Developer guide for Claude Code
└── package.json # Dependencies
## Available Scripts
### Development
- `npm run dev` - Start development server (http://localhost:5174)
- `npm run build` - Build for production
- `npm run build:check` - TypeScript check + build
- `npm run preview` - Preview production build
- `npm run lint` - Run ESLint
### Content Management
- `npm run content:create:blog` - Create new blog post (interactive)
- `npm run content:create:article` - Create new article (interactive)
- `npm run content:create:doc` - Create new documentation (interactive)
- `npm run content:create:project` - Create new project showcase (interactive)
- `npm run content:list` - List all content files
- `npm run content:validate` - Validate all markdown content
- `npm run content:index` - Generate content index for search
- `npm run content:init` - Validate and index all content
### Deployment
- `./scripts/one-click-deploy.sh` - Interactive build-push-deploy
- `./scripts/quick-build-push-deploy.sh` - Fast deployment (requires env vars)
- `./scripts/test-deployment-readiness.sh` - Pre-deployment checks
- `./scripts/setup-all.sh` - Complete GitOps setup
## Docker Build
### Build locally
```bash
# Build Docker image
docker build -t ljwx-website .
# Run container
docker run -p 8080:80 ljwx-website
# Access at http://localhost:8080
Multi-stage build details
- Stage 1 (builder): Node 20 Alpine - Installs dependencies and builds the React app
- Stage 2 (production): Nginx Alpine - Serves static files with optimized configuration
Monitoring
- Health Check: https://www.lingjingwanxiang.cn/health
- Namespace:
website - Pods: 2 replicas with rolling updates
- Logs:
kubectl logs -f deployment/website -n website - Status:
kubectl get all -n website
Troubleshooting
Gitea CI/CD Pipeline Issues
Workflow not starting:
# Check runner status
tail -f /Users/brunogao/gitea-runners/runner3/runner.log
# Verify runner is registered
cat /Users/brunogao/gitea-runners/runner3/.runner | jq '.labels'
# Expected labels: ["docker-builder:host", "macos:host", "self-hosted:host"]
Runner label errors:
# If you see "ignored invalid label" errors
# Fix config.yaml and restart runner
cd /Users/brunogao/gitea-runners/runner3
vim config.yaml # Ensure labels use format: "labelname:host" or "labelname:docker://image"
# Restart runner
pkill -f "act_runner"
/Users/brunogao/gitea-runners/act_runner daemon --config config.yaml > runner.log 2>&1 &
Build job fails with "docker: command not found":
- Ensure build job uses
runs-on: docker-builder(host runner) - K8s runner (
ubuntu-latest) doesn't have Docker command available - Check workflow file:
.gitea/workflows/ci.yaml
Container jobs fail with "Cannot find: node":
- Use
container:config only with K8s runner (ubuntu-latest) - Host runner jobs should not use
container:directive - Ensure custom CI image is accessible:
harbor.omniverseai.net/ljwx/ci-node:20
Monitor workflow execution:
# Real-time monitoring
./.gitea/watch-workflow.sh
# Check workflow status via API
curl -s http://192.168.1.83:33000/gao/ljwx-website/actions
# View specific run
# Visit: http://192.168.1.83:33000/gao/ljwx-website/actions/runs/<run-id>
GitHub Actions Pipeline Fails
- Check GitHub Actions logs for specific errors
- Verify Harbor credentials in GitHub secrets
- Ensure
DEPLOY_REPO_TOKENhas write access
Deployment Not Updating
- Check Argo CD application status:
argocd app get ljwx-website-eu-dev - Verify ljwx-deploy repository was updated
- Check image tag in values.yaml matches built image
Website Not Accessible
- Check Ingress configuration:
kubectl get ingress -n website - Verify TLS certificate:
kubectl get secret wildcard-lingjingwanxiang-tls -n website - Check pod status:
kubectl get pods -n website -l app=website - Check service endpoints:
kubectl get endpoints website -n website - Test health endpoint:
curl https://www.lingjingwanxiang.cn/health
Direct Deployment Issues
See scripts/DEPLOY-README.md for detailed troubleshooting:
- Harbor login failures
- Image pull errors
- Ingress conflicts
- Pod startup issues
Contributing
- Create a feature branch from
main - Make your changes
- Run linting and tests
- Create a pull request
- After PR approval and merge to main, CI will automatically deploy
License
Copyright © 2024 Lingjing Wanxiang. All rights reserved.
Support
For issues and questions, please create an issue in the GitHub repository.