{"id":42130730,"url":"https://github.com/ngthecoder/go_web_api","last_synced_at":"2026-01-26T15:34:00.220Z","repository":{"id":311362456,"uuid":"1043030689","full_name":"ngthecoder/go_web_api","owner":"ngthecoder","description":null,"archived":false,"fork":false,"pushed_at":"2025-11-17T01:29:16.000Z","size":264,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-17T03:23:05.570Z","etag":null,"topics":["api","golang","jwt-authentication","nextjs15","postgresql","sqlite3","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ngthecoder.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-23T02:21:29.000Z","updated_at":"2025-10-26T07:10:13.000Z","dependencies_parsed_at":"2025-08-24T10:52:36.264Z","dependency_job_id":"b914ba75-934c-430c-8cce-10fe7d83c503","html_url":"https://github.com/ngthecoder/go_web_api","commit_stats":null,"previous_names":["ngthecoder/go_web_api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ngthecoder/go_web_api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngthecoder%2Fgo_web_api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngthecoder%2Fgo_web_api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngthecoder%2Fgo_web_api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngthecoder%2Fgo_web_api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ngthecoder","download_url":"https://codeload.github.com/ngthecoder/go_web_api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngthecoder%2Fgo_web_api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28781508,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T13:55:28.044Z","status":"ssl_error","status_checked_at":"2026-01-26T13:55:26.068Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","golang","jwt-authentication","nextjs15","postgresql","sqlite3","typescript"],"created_at":"2026-01-26T15:34:00.152Z","updated_at":"2026-01-26T15:34:00.208Z","avatar_url":"https://github.com/ngthecoder.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go Recipe Web API + Next.js Frontend\n\nA production-ready full-stack recipe discovery application with secure authentication, demonstrating modern containerized application development and cloud deployment.\n\n## 🎯 Project Overview\n\nA full-stack web application that helps users discover recipes, manage their favorite dishes, and generate shopping lists based on available ingredients. Built with Go backend, Next.js frontend, PostgreSQL database, and deployed on AWS using Terraform and ECS Fargate.\n\n## 🛠️ Tech Stack\n\n**Backend**\n- Go 1.24.0\n- PostgreSQL 16 (production) / 15 (local)\n- JWT authentication with Argon2id password hashing\n- RESTful API with 14 endpoints\n\n**Frontend**\n- Next.js 15.5.0 with React 19.1.0\n- TypeScript\n- Tailwind CSS 4\n- Context API for state management\n\n**Infrastructure \u0026 DevOps**\n- **Local Development**: Docker Compose, Kubernetes (Minikube)\n- **Production**: AWS (Terraform, ECS Fargate, RDS, ECR, ALB)\n- Docker multi-stage builds\n- CloudWatch logging\n- AWS Secrets Manager\n\n**Database Schema**\n- 5 tables: `ingredients`, `recipes`, `recipe_ingredients`, `users`, `user_liked_recipes`\n- Normalized design with proper foreign keys and indexes\n\n## ✨ Key Features\n\n- 🔐 **Secure Authentication**: JWT tokens with Argon2 password hashing\n- 🔍 **Smart Recipe Search**: Find recipes by available ingredients with match scoring\n- ❤️ **Personal Collections**: Save and manage favorite recipes\n- 🛒 **Shopping Lists**: Generate ingredient lists from recipes\n- 📱 **Responsive Design**: Mobile-first UI with Tailwind CSS 4\n- ☁️ **Cloud-Native**: Containerized deployment on AWS\n- 🐳 **Multi-Environment**: Docker Compose for local, Kubernetes for staging, AWS for production\n\n## 🏗️ Architecture\n\n### Production (AWS)\n\n```\nInternet\n    ↓\n┌─────────────────────────────────────────────┐\n│  AWS VPC (10.0.0.0/16)                      │\n│                                             │\n│  ┌─────────────────┐  ┌─────────────────┐  │\n│  │ Frontend ALB    │  │ Backend ALB     │  │\n│  │ (Port 80)       │  │ (Port 80)       │  │\n│  └────────┬────────┘  └────────┬────────┘  │\n│           ↓                    ↓            │\n│  ┌─────────────────┐  ┌─────────────────┐  │\n│  │ Frontend ECS    │  │ Backend ECS     │  │\n│  │ (Next.js)       │  │ (Go API)        │  │\n│  │ Public Subnet   │  │ Public Subnet   │  │\n│  └─────────────────┘  └────────┬────────┘  │\n│                                 ↓            │\n│                        ┌─────────────────┐  │\n│                        │ RDS PostgreSQL  │  │\n│                        │ Private Subnet  │  │\n│                        └─────────────────┘  │\n└─────────────────────────────────────────────┘\n\nStorage:\n- ECR: Docker image registry\n- Secrets Manager: Passwords, JWT secret\n- CloudWatch: Application logs\n```\n\n### Local (Kubernetes)\n\n```\n┌────────────────────────────────────────────┐\n│  Kubernetes Cluster (Minikube)             │\n│                                            │\n│  Frontend Service (3 replicas)            │\n│  └─ Next.js + React + TypeScript          │\n│                                            │\n│  Backend Service (3 replicas)             │\n│  └─ Go REST API                            │\n│                                            │\n│  PostgreSQL Service (1 replica)           │\n│  └─ Database + PersistentVolume (5Gi)     │\n└────────────────────────────────────────────┘\n```\n\n## 🚀 Quick Start\n\n### Prerequisites\n\n- **For Docker Compose**: Docker Desktop\n- **For Kubernetes**: Docker Desktop + Minikube + kubectl\n- **For AWS**: AWS CLI configured + Terraform installed\n- Go 1.22+ and Node.js 18+ (for local development without containers)\n\n### Option 1: Docker Compose (Fastest)\n\n```bash\n# Clone repository\ngit clone https://github.com/ngthecoder/go_web_api.git\ncd go_web_api\n\n# Start all services\ndocker-compose up --build\n\n# Access application\n# Frontend: http://localhost:3000\n# Backend API: http://localhost:8000\n# Database: localhost:5432\n```\n\n### Option 2: Kubernetes with Minikube (Learning K8s)\n\n```bash\n# Start Minikube\nminikube start --cpus=4 --memory=8192\n\n# Build images in Minikube's Docker daemon\neval $(minikube docker-env)\ncd backend \u0026\u0026 docker build -t recipe-backend:v1 .\ncd ../frontend \u0026\u0026 docker build -t recipe-frontend:v1 .\ncd ..\n\n# Deploy to Kubernetes\nkubectl apply -f k8s/namespace.yaml\nkubectl apply -f k8s/configmap.yaml\nkubectl apply -f k8s/secret.yaml\nkubectl apply -f k8s/postgres.yaml\nkubectl apply -f k8s/backend.yaml\nkubectl apply -f k8s/frontend.yaml\n\n# Wait for pods to be ready\nkubectl wait --for=condition=ready pod --all -n recipe-app --timeout=120s\n\n# Access application via port-forward\nkubectl config set-context --current --namespace=recipe-app\nkubectl port-forward svc/frontend 3000:3000 \u0026\nkubectl port-forward svc/backend 8000:8000 \u0026\n\n# Open browser\nopen http://localhost:3000\n```\n\n### Option 3: Local Development (No Containers)\n\n```bash\n# Backend\ncd backend\ncat \u003e .env \u003c\u003c EOF\nDATABASE_URL=postgresql://recipeadmin:password@localhost:5432/recipes?sslmode=disable\nJWT_SECRET=local-dev-secret-at-least-32-characters-long\nPORT=8000\nALLOWED_ORIGINS=http://localhost:3000\nENVIRONMENT=development\nEOF\ngo run main.go  # Runs on http://localhost:8000\n\n# Frontend (in new terminal)\ncd frontend\ncat \u003e .env.local \u003c\u003c EOF\nNEXT_PUBLIC_API_URL=http://localhost:8000\nEOF\nnpm install\nnpm run dev  # Runs on http://localhost:3000\n```\n\n## ☁️ AWS Production Deployment\n\n### Prerequisites\n\n- **AWS Account** with CLI configured (`aws configure`)\n- **Terraform** 1.0+ installed\n- **Docker** installed\n- **Git** for version control\n\n### Environment Configuration\n\nCustomize these for your environment in `terraform/variables.tf`:\n\n- **AWS Region**: Default is `us-east-1`\n- **Project Name**: Default is `recipe-app`\n- **Resource Sizing**: Adjust CPU/memory based on your needs\n- **Replica Count**: Default 1 backend + 1 frontend (increase for production)\n\n### Step 1: Clone Repository\n\n```bash\ngit clone https://github.com/yourusername/go_web_api.git\ncd go_web_api\n```\n\n### Step 2: Deploy Infrastructure\n\n```bash\ncd terraform/\n\n# Initialize Terraform\nterraform init\n\n# Review what will be created\nterraform plan\n\n# Create AWS infrastructure\nterraform apply\n# Type 'yes' when prompted\n\n# Save important outputs\nterraform output backend_alb_dns     # Copy this URL\nterraform output frontend_alb_dns    # Copy this URL\nterraform output backend_ecr_repository_url\nterraform output frontend_ecr_repository_url\n```\n\n**What gets created**: VPC, subnets, security groups, RDS PostgreSQL, ECR repositories, ECS cluster, Application Load Balancers, CloudWatch logs, Secrets Manager (~$40-50/month)\n\n### Step 3: Build and Push Backend\n\n```bash\ncd ../backend/\n\n# Build Docker image\ndocker build -t recipe-app-backend .\n\n# Get your ECR URL from terraform output\nBACKEND_ECR=$(cd ../terraform \u0026\u0026 terraform output -raw backend_ecr_repository_url)\n\n# Tag for ECR\ndocker tag recipe-app-backend:latest $BACKEND_ECR:latest\n\n# Login to ECR\nAWS_REGION=us-east-1  # Change if you used different region\naws ecr get-login-password --region $AWS_REGION | \\\n  docker login --username AWS --password-stdin $BACKEND_ECR\n\n# Push to ECR\ndocker push $BACKEND_ECR:latest\n```\n\n### Step 4: Build and Push Frontend\n\n**Important**: Frontend needs the backend URL at build time.\n\n```bash\ncd ../frontend/\n\n# Get backend ALB URL from terraform\nBACKEND_URL=$(cd ../terraform \u0026\u0026 terraform output -raw backend_url)\nFRONTEND_ECR=$(cd ../terraform \u0026\u0026 terraform output -raw frontend_ecr_repository_url)\n\n# Build with backend URL\ndocker build \\\n  --build-arg NEXT_PUBLIC_API_URL=$BACKEND_URL \\\n  -t recipe-app-frontend .\n\n# Tag for ECR\ndocker tag recipe-app-frontend:latest $FRONTEND_ECR:latest\n\n# Push to ECR (already logged in from step 3)\ndocker push $FRONTEND_ECR:latest\n```\n\n### Step 5: Deploy to ECS\n\n```bash\n# Force ECS to pull and run the new images\naws ecs update-service \\\n  --cluster recipe-app-cluster \\\n  --service recipe-app-backend-service \\\n  --force-new-deployment \\\n  --region us-east-1\n\naws ecs update-service \\\n  --cluster recipe-app-cluster \\\n  --service recipe-app-frontend-service \\\n  --force-new-deployment \\\n  --region us-east-1\n```\n\n### Step 6: Verify Deployment\n\n```bash\n# Check backend logs\naws logs tail /ecs/recipe-app-backend --follow --region us-east-1\n# Look for: \"Database connection established successfully\"\n\n# Check frontend logs\naws logs tail /ecs/recipe-app-frontend --follow --region us-east-1\n\n# Get your application URL\ncd terraform/\nterraform output frontend_url\n```\n\n**Access your app**: Open the frontend URL in your browser\n\n## 🔄 Update Workflows\n\n### Update Backend Code\n\n```bash\ncd backend/\n# Make your code changes\n\ndocker build -t recipe-app-backend .\nBACKEND_ECR=$(cd ../terraform \u0026\u0026 terraform output -raw backend_ecr_repository_url)\ndocker tag recipe-app-backend:latest $BACKEND_ECR:latest\ndocker push $BACKEND_ECR:latest\n\naws ecs update-service \\\n  --cluster recipe-app-cluster \\\n  --service recipe-app-backend-service \\\n  --force-new-deployment \\\n  --region us-east-1\n```\n\n### Update Frontend Code\n\n```bash\ncd frontend/\n# Make your code changes\n\nBACKEND_URL=$(cd ../terraform \u0026\u0026 terraform output -raw backend_url)\nFRONTEND_ECR=$(cd ../terraform \u0026\u0026 terraform output -raw frontend_ecr_repository_url)\n\ndocker build --build-arg NEXT_PUBLIC_API_URL=$BACKEND_URL -t recipe-app-frontend .\ndocker tag recipe-app-frontend:latest $FRONTEND_ECR:latest\ndocker push $FRONTEND_ECR:latest\n\naws ecs update-service \\\n  --cluster recipe-app-cluster \\\n  --service recipe-app-frontend-service \\\n  --force-new-deployment \\\n  --region us-east-1\n```\n\n### Update Infrastructure\n\n```bash\ncd terraform/\n# Edit .tf files\n\nterraform plan    # Review changes\nterraform apply   # Apply changes\n```\n\n## 🛑 Teardown\n\n### Stop Services (saves ~80% cost, keeps data)\n\n```bash\naws ecs update-service --cluster recipe-app-cluster --service recipe-app-backend-service --desired-count 0 --region us-east-1\naws ecs update-service --cluster recipe-app-cluster --service recipe-app-frontend-service --desired-count 0 --region us-east-1\n```\n\n### Restart Services\n\n```bash\naws ecs update-service --cluster recipe-app-cluster --service recipe-app-backend-service --desired-count 1 --region us-east-1\naws ecs update-service --cluster recipe-app-cluster --service recipe-app-frontend-service --desired-count 1 --region us-east-1\n```\n\n### Destroy Everything\n\n```bash\ncd terraform/\nterraform destroy\n# Type 'yes' when prompted\n```\n\n**Warning**: This deletes all data including the database and Docker images in ECR.\n\n## 🐳 Docker Configuration\n\n### Multi-Stage Builds\n\n**Backend** (Alpine-based, CGO-enabled for PostgreSQL)\n```dockerfile\n# Stage 1: Build with Go 1.24 + gcc\nFROM golang:1.24-alpine AS builder\nRUN apk add --no-cache gcc musl-dev\n# ... build process\n\n# Stage 2: Runtime with Alpine + PostgreSQL libs\nFROM alpine:latest\nRUN apk --no-cache add ca-certificates curl\n# ... copy binary and run\n```\n**Image size**: ~50MB\n\n**Frontend** (Node.js standalone output)\n```dockerfile\n# Stage 1: Install dependencies\n# Stage 2: Build Next.js with backend URL\n# Stage 3: Runtime with minimal Node.js\n```\n**Image size**: ~150MB\n\n### Docker Compose Services\n\n```yaml\nservices:\n  postgres:    # PostgreSQL 15 with volume persistence\n  backend:     # Go API (port 8000)\n  frontend:    # Next.js UI (port 3000)\n```\n\n## ☸️ Kubernetes Features\n\n### Resources\n\n- **ConfigMaps**: Application configuration (ports, URLs, database connection)\n- **Secrets**: Sensitive data (passwords, JWT secret)\n- **Deployments**: \n  - Frontend (3 replicas)\n  - Backend (3 replicas)\n  - PostgreSQL (1 replica with PersistentVolume)\n- **Services**:\n  - Frontend: NodePort (30300)\n  - Backend: NodePort (30800)\n  - PostgreSQL: ClusterIP (internal only)\n\n### Key Features\n\n- **Persistent Storage**: 5Gi PersistentVolumeClaim for database\n- **Load Balancing**: Service-level load balancing across replicas\n- **Self-Healing**: Automatic pod restart on failure\n- **Rolling Updates**: Zero-downtime deployments\n- **Namespace Isolation**: All resources in `recipe-app` namespace\n\n## 🔐 Security Features\n\n**Network Security**\n- Database in private subnet with no internet access\n- Security groups with strict firewall rules (ALB → ECS → RDS only)\n- SSL/TLS required for RDS connections\n\n**Application Security**\n- Password Hashing: Argon2id (time=3, memory=64MB, 16-byte salt)\n- JWT Tokens: HMAC-SHA256, 24-hour expiration\n- CORS Protection: Configured allowed origins\n- Input Validation: All endpoints validate parameters\n- SQL Injection Prevention: Parameterized queries\n\n**Infrastructure Security**\n- AWS Secrets Manager for credentials\n- IAM roles with least-privilege permissions\n- No hardcoded secrets in code or containers\n\n## 📊 API Endpoints\n\n| Endpoint | Method | Auth | Description |\n|----------|--------|------|-------------|\n| `/api/auth/register` | POST | No | User registration |\n| `/api/auth/login` | POST | No | User login |\n| `/api/recipes` | GET | Optional | Browse recipes with filters |\n| `/api/recipes/{id}` | GET | Optional | Recipe details |\n| `/api/recipes/find-by-ingredients` | GET | Optional | Find recipes by ingredients |\n| `/api/recipes/shopping-list/{id}` | GET | No | Generate shopping list |\n| `/api/ingredients` | GET | No | Browse ingredients |\n| `/api/ingredients/{id}` | GET | No | Ingredient details |\n| `/api/user/profile` | GET | Yes | User profile |\n| `/api/user/liked-recipes` | GET | Yes | User's liked recipes |\n| `/api/user/liked-recipes/add` | POST | Yes | Add liked recipe |\n| `/api/user/liked-recipes/{id}` | DELETE | Yes | Remove liked recipe |\n| `/api/user/profile/update` | PUT | Yes | Update profile |\n| `/api/user/password` | PUT | Yes | Change password |\n| `/api/user/account` | DELETE | Yes | Delete account |\n| `/api/categories` | GET | No | Category statistics |\n| `/api/stats` | GET | No | Overall statistics |\n\n## 🧪 Testing\n\n```bash\ncd backend\ngo test ./... -v -cover\n\n# Current coverage: ~40%\n# Focus: Authentication security, core business logic\n```\n\n## 📁 Project Structure\n\n```\ngo_web_api/\n├── backend/\n│   ├── internal/\n│   │   ├── auth/           # JWT \u0026 authentication\n│   │   ├── database/       # DB connection \u0026 migrations\n│   │   ├── recipes/        # Recipe business logic\n│   │   ├── ingredients/    # Ingredient management\n│   │   ├── users/          # User profile management\n│   │   └── stats/          # Statistics\n│   ├── main.go\n│   ├── Dockerfile\n│   └── go.mod\n├── frontend/\n│   ├── app/\n│   │   ├── recipes/        # Recipe pages\n│   │   ├── ingredients/    # Ingredient pages\n│   │   ├── profile/        # User profile\n│   │   └── page.tsx        # Home page\n│   ├── components/         # Reusable React components\n│   ├── contexts/           # Auth context\n│   ├── Dockerfile\n│   └── package.json\n├── k8s/                    # Kubernetes manifests\n│   ├── namespace.yaml\n│   ├── configmap.yaml\n│   ├── secret.yaml\n│   ├── postgres.yaml\n│   ├── backend.yaml\n│   └── frontend.yaml\n├── terraform/              # AWS infrastructure\n│   ├── main.tf             # Provider configuration\n│   ├── vpc.tf              # VPC, subnets, networking\n│   ├── rds.tf              # PostgreSQL database\n│   ├── ecs.tf              # ECS cluster and services\n│   ├── alb.tf              # Application Load Balancers\n│   ├── ecr.tf              # Container registry\n│   ├── secrets.tf          # Secrets Manager\n│   ├── security.tf         # Security groups\n│   ├── cloudwatch.tf       # Logging\n│   ├── variables.tf        # Configuration variables\n│   └── outputs.tf          # Output values\n├── docker-compose.yml      # Local development\n└── README.md\n```\n\n## 🎓 What I Learned\n\n**Infrastructure as Code**\n- Terraform for reproducible AWS deployments\n- Managing state and dependencies between resources\n- Cost optimization with proper resource sizing\n\n**Container Orchestration**\n- Docker multi-stage builds for optimization\n- Kubernetes deployments with multiple replicas\n- ECS Fargate for serverless container management\n\n**Cloud Networking**\n- VPCs, subnets (public vs private), security groups\n- Application Load Balancers and target groups\n- Network isolation and firewall rules\n\n**Security Best Practices**\n- Secrets management with AWS Secrets Manager\n- SSL/TLS for database connections\n- Least-privilege IAM roles\n- Password hashing and JWT authentication\n\n**Full-Stack Development**\n- RESTful API design with Go\n- Server-side rendering with Next.js\n- Database schema design and migrations\n- CORS and cross-origin authentication\n\n## 🚧 Future Enhancements\n\n- HTTPS with ACM certificates\n- Custom domain with Route 53\n- CI/CD pipeline with GitHub Actions\n- Monitoring with Prometheus + Grafana\n- Rate limiting and API throttling\n- Email verification and password reset\n- Recipe image uploads to S3\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngthecoder%2Fgo_web_api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fngthecoder%2Fgo_web_api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngthecoder%2Fgo_web_api/lists"}