Add full-stack Hello World app with CI/CD

- Go backend with PostgreSQL connection
- Next.js frontend with TypeScript
- Docker Compose for local development
- Woodpecker CI pipeline for build and push
- Kubernetes manifests with Kustomize
- ArgoCD application for GitOps deployment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Erdenebat Tsenddorj
2026-01-21 21:06:08 +08:00
parent 2c4e7d2c38
commit f311439621
26 changed files with 955 additions and 1 deletions

118
frontend/app/page.tsx Normal file
View File

@@ -0,0 +1,118 @@
'use client'
import { useEffect, useState } from 'react'
interface ApiResponse {
message: string
db_status: string
}
export default function Home() {
const [data, setData] = useState<ApiResponse | null>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080'
fetch(`${apiUrl}/api/hello`)
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
.catch((err) => {
setError(err.message)
setLoading(false)
})
}, [])
return (
<main style={styles.main}>
<div style={styles.container}>
<h1 style={styles.title}>Hello World!</h1>
<p style={styles.subtitle}>Go + PostgreSQL + Next.js</p>
<div style={styles.card}>
{loading && <p>Loading...</p>}
{error && <p style={styles.error}>Error: {error}</p>}
{data && (
<>
<p style={styles.message}>{data.message}</p>
<p style={styles.status}>
Database:
<span style={{
color: data.db_status === 'connected' ? '#22c55e' : '#ef4444',
marginLeft: '8px'
}}>
{data.db_status}
</span>
</p>
</>
)}
</div>
<div style={styles.techStack}>
<span style={styles.badge}>Go</span>
<span style={styles.badge}>PostgreSQL</span>
<span style={styles.badge}>Next.js</span>
</div>
</div>
</main>
)
}
const styles: { [key: string]: React.CSSProperties } = {
main: {
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
fontFamily: 'system-ui, -apple-system, sans-serif',
},
container: {
textAlign: 'center',
color: 'white',
},
title: {
fontSize: '4rem',
marginBottom: '0.5rem',
textShadow: '2px 2px 4px rgba(0,0,0,0.2)',
},
subtitle: {
fontSize: '1.25rem',
opacity: 0.9,
marginBottom: '2rem',
},
card: {
background: 'rgba(255,255,255,0.95)',
borderRadius: '12px',
padding: '2rem',
color: '#333',
boxShadow: '0 10px 40px rgba(0,0,0,0.2)',
marginBottom: '2rem',
},
message: {
fontSize: '1.25rem',
fontWeight: 500,
},
status: {
marginTop: '1rem',
fontSize: '1rem',
},
error: {
color: '#ef4444',
},
techStack: {
display: 'flex',
gap: '1rem',
justifyContent: 'center',
},
badge: {
background: 'rgba(255,255,255,0.2)',
padding: '0.5rem 1rem',
borderRadius: '20px',
fontSize: '0.875rem',
},
}