README
ReactGoLogin
A modern full-stack todo application with user authentication, built with React, Next.js, Go, and GraphQL.
๐ Documentation
- Deployment Guide - Complete production deployment instructions
- Development Setup - Local development setup
- Production Scripts - Automated deployment tools
- Architecture - System design and structure
Features
- User Authentication: Secure login and registration system
- Todo Management: Create, read, update, and delete todos
- Agile/Scrum Board: Kanban-style board with drag-and-drop between stages (Backlog, To Do, In Progress, Review, Done)
- Nested Todo Display: View all subtasks in hierarchical tree view with visual indentation
- Mobile Folder View: Group todos by folder hierarchy with collapsible sections
- Icon Support: Add emoji icons to todos for visual organization
- Image Attachments: Upload and manage images for each todo
- Priority Levels: Set low, medium, or high priority for todos
- Due Dates: Set deadlines with date and time
- Recurring Todos: Create tasks that repeat daily, weekly, monthly, yearly, or after completion
- Event System & Bounty Management: Complete audit trail with bounty locking and completion workflows
- Todo Event Logging: Professional event tracking for all todo actions with structured data
- Bounty System: Task rewards with locking mechanism to prevent double-work
- Completion Requests: Proxy workflow for bounty task approval/rejection
- Activity Timeline: Visual event history showing all todo interactions
- Search & Filter: Find todos quickly with search and status filters across all views
- Tab Filtering: All/Active/Completed tabs with persistent selection
- View Mode Toggle: Switch between mobile and desktop layouts with persistence
- Board View Modes: Standard and compact card layouts for the scrum board
- Statistics: View todo completion statistics
- Modern UI: Clean, responsive interface with Tailwind CSS
- Desktop Layouts: Optimized layouts for larger screens with sidebar navigation
- Direct Edit on Click: Clicking a todo item goes directly to edit mode for efficiency
- Storybook Integration: Component library with banking UI components
- GraphQL Code Generation: Automatic TypeScript type generation for schema safety
- Environment Sync: Easy data synchronization between development and production
Tech Stack
Frontend
- Next.js 15.3.3 with Turbopack
- React 19 with TypeScript
- Apollo Client for GraphQL
- Tailwind CSS for styling
- Radix UI for accessible components
- Storybook 9 for component development
Backend
- Go with Gin framework
- GraphQL with gqlgen
- MySQL database
- JWT authentication
- Docker containerization
Deployment
Setting Up SSH Access (New Servers)
When setting up a new Hetzner server, you'll need to configure SSH access first:
# From your local machine, run:
./scripts/hetzner-ssh-setup.sh
# Enter the server IP and rescue password when prompted
# Reboot to exit rescue mode
ssh root@YOUR_SERVER_IP 'reboot'
# Wait 2 minutes, then you can SSH with your key
Fresh Server Deployment (Recommended)
For a brand new Ubuntu server, use the automated deployment script:
# SSH into your fresh server, then run:
curl -fsSL https://raw.githubusercontent.com/jonathanleahy/reactgologin/master/scripts/deploy-fresh-server.sh | bash
# Or manually:
git clone https://github.com/jonathanleahy/reactgologin.git
cd reactgologin
./scripts/deploy-fresh-server.shThis single script will:
- Install Docker and dependencies
- Clone the repository
- Configure environment variables automatically
- Build and deploy all services
- Configure firewall
- Verify the deployment
Existing Server Deployment
# Clone the repository
git clone https://github.com/jonathanleahy/reactgologin.git
cd reactgologin
# Run the setup script to configure environment
./scripts/setup-prod.sh
# Use this to deploy from your local machine to production
./scripts/deploy-remote.sh
# If you're already SSH'd into the production server
./scripts/deploy-prod.sh
Important Notes
- The
setup-prod.shscript automatically detects your server's IP and configures the environment files - Environment variables are NOT committed to git for security
- The backend automatically runs database migrations on startup
- Default ports: 80 (nginx), 3000 (frontend), 8081 (backend), 3307 (database)
Troubleshooting
If you get "failed to fetch" errors:
NEXT_PUBLIC_API_URL is set correctly in frontend-next/.env.productiondocker compose -f docker-compose.prod.yml build --no-cache frontendlocalhost./scripts/fix-prod-api-url.shNuclear Option: Fresh Server Deployment
If you're having persistent issues, the fastest solution is often to deploy on a fresh server:
# Create new server, then run:
./scripts/deploy-fresh-server.shThis ensures a clean environment with all correct configurations.
Project Structure
reactgologin/
โโโ backend/ # Go backend with hexagonal architecture
โ โโโ cmd/api/ # Application entry point
โ โโโ internal/
โ โ โโโ domain/ # Core business logic (entities, value objects)
โ โ โโโ application/ # Use cases
โ โ โโโ infrastructure/ # External adapters (database, JWT)
โ โ โโโ interfaces/ # GraphQL resolvers
โ โโโ migrations/ # Database migrations
โโโ frontend-next/ # Next.js TypeScript frontend
โ โโโ app/ # Next.js App Router pages
โ โโโ components/ # React components
โ โโโ contexts/ # React contexts (Auth)
โ โโโ lib/ # Utilities (Apollo Client)
โ โโโ types/ # TypeScript type definitions
โโโ docker-compose.yml # Docker orchestration
Getting Started
Prerequisites
- Docker and Docker Compose
- Port 3000, 8081, and 3307 available
Running the Application
./test-setup.sh
./start.sh
# or manually with:
docker compose up -d --build
Default Setup
The application starts with an empty database. You'll need to either:
Using the Application
Development
Hot Reloading
Both frontend and backend support hot reloading:
- Frontend: Changes to Next.js/TypeScript code automatically refresh the browser with Fast Refresh
- Backend: Changes to Go code automatically rebuild and restart the server (using Air)
GraphQL API
The GraphQL API is available at http://localhost:8081/query
Available operations:
# Register a new user
mutation Register($email: String!, $password: String!) {
register(email: $email, password: $password) {
token
user {
id
email
}
}
}
# Login existing user
mutation Login($email: String!, $password: String!) {
login(email: $email, password: $password) {
token
user {
id
email
}
}
}
# Get current user (requires authentication)
query Me {
me {
id
email
createdAt
updatedAt
}
}
# Access protected content (requires authentication)
query Protected {
protected
}
Database
MySQL runs on port 3307 (to avoid conflicts with local MySQL):
- Host: localhost
- Port: 3307
- Database: reactgologin
- User: appuser
- Password: apppassword
Architecture Details
Hexagonal Architecture (Backend)
The backend follows hexagonal architecture principles:
internal/domain/):internal/application/):internal/infrastructure/):internal/interfaces/):This architecture ensures:
- Business logic is independent of frameworks
- Easy to test
- Easy to swap implementations (e.g., change database)
Security
- Passwords are hashed using bcrypt
- JWT tokens expire after 24 hours
- CORS is configured for localhost:3000
- SQL injection protection via prepared statements
Client-Side Storage
The application uses localStorage to persist user preferences:
- Authentication: JWT tokens are stored in localStorage
- Todo Filters: Selected tab (All/Active/Completed) persists across sessions
- View Mode: Mobile/Desktop view preference is remembered
Troubleshooting
docker compose restart backend
Stopping the Application
docker compose downTo also remove volumes (database data):
docker compose down -v
Environment Synchronization
Quick Start - Pull from Production
The easiest way to sync production data to your development environment:
# First time setup - configure your production server
./scripts/pull-from-prod.sh
# Choose option 4 and enter your server details
# Pull latest production data
./scripts/pull-from-prod.sh
# Choose option 1 for everything (database + files)
Push Development to Production
โ ๏ธ WARNING: This will overwrite production data!
To push your local development data to production:
# Interactive push with safety confirmation
./scripts/remote-sync.sh push
Advanced Sync Options
# Pull specific data types
./scripts/remote-sync.sh pull db # Database only
./scripts/remote-sync.sh pull files # Files only
./scripts/remote-sync.sh pull data # DB + files (no config)
# Local export/import
./scripts/sync-environments.sh export dev
./scripts/sync-environments.sh import ~/exports/reactgologin_*.tar.gz
Sync Configuration
The remote sync tools save your server details in ~/.reactgologin-sync.conf:
REMOTE_USER="root"
REMOTE_HOST="5.75.186.52"
REMOTE_PORT="22"
REMOTE_PROJECT_PATH="/root/reactgologin"To reconfigure:
./scripts/remote-sync.sh setupFor more details, see scripts/README-SYNC.md.
Production Deployment
New Server Setup (3-Step Process)
For deploying to a new production server:
# Step 1: Setup the server
./deploy-to-prod/1-setup-new-server.sh
# Step 2: Build Docker images locally
./deploy-to-prod/2-build-and-save-images.sh
# Step 3: Deploy to production
./deploy-to-prod/3-upload-and-deploy.shThis process:
- Sets up Ubuntu server with Docker
- Builds optimized Docker images (217MB frontend)
- Automatically exports and imports your local database
- Handles complex passwords with special characters
- Uploads images and configurations
Production Management Scripts
The project includes comprehensive scripts for managing the production environment.
Initial Setup
Run the setup script to configure remote access:
./scripts/setup-remote-sync.sh
This creates ~/.reactgologin-sync.conf with your remote server details.
Production Scripts Overview
| Script | Purpose | Usage |
|---|---|---|
deploy-remote.sh | Deploy latest code from GitHub | ./scripts/deploy-remote.sh [branch] |
prod-backup.sh | Backup production data to local | ./scripts/prod-backup.sh |
prod-status.sh | Check production health & status | ./scripts/prod-status.sh |
prod-restart.sh | Restart production containers | ./scripts/prod-restart.sh [--rebuild] [--logs] |
prod-logs.sh | View production logs | ./scripts/prod-logs.sh [container] [-f] [-n 100] |
prod-exec.sh | Execute commands in containers | ./scripts/prod-exec.sh <container> <command> |
pull-from-prod.sh | Sync production data to local | ./scripts/pull-from-prod.sh |
push-to-prod.sh | Push local data to production | ./scripts/push-to-prod.sh |
Common Production Tasks
#### Update Production to Latest Code
# Deploy from master branch (default)
./scripts/deploy-remote.sh
# Deploy from specific branch
./scripts/deploy-remote.sh feature/my-branchThis will:
#### Backup Production Data
# Create local backup of production
./scripts/prod-backup.sh
Backups are stored in ~/backups/reactgologin/ and include:
- Complete database export
- All uploaded files
- Code snapshot
# View comprehensive status
./scripts/prod-status.shShows:
- Git branch and latest commit
- Container status
- Health check results
- Database statistics
- Disk usage
- Recent error logs
# Simple restart
./scripts/prod-restart.sh
# Rebuild and restart
./scripts/prod-restart.sh --rebuild
# Restart and follow logs
./scripts/prod-restart.sh --logs#### View Production Logs
# View all logs
./scripts/prod-logs.sh
# Follow logs in real-time
./scripts/prod-logs.sh -f
# View specific container logs
./scripts/prod-logs.sh frontend -f
./scripts/prod-logs.sh backend -n 200
./scripts/prod-logs.sh mysql#### Execute Commands in Production
# Shell access
./scripts/prod-exec.sh backend sh
./scripts/prod-exec.sh frontend sh
# Run migrations
./scripts/prod-exec.sh backend go run cmd/migrate/main.go
# MySQL access
./scripts/prod-exec.sh mysql mysql -u root -prootpassword
# NPM commands
./scripts/prod-exec.sh frontend npm list
Production Deployment Workflow
./scripts/prod-status.sh
./scripts/prod-backup.sh
./scripts/deploy-remote.sh
./scripts/prod-logs.sh -f
./scripts/prod-status.sh
Troubleshooting Production
#### Container Not Starting
# Check logs
./scripts/prod-logs.sh backend -n 100
# Rebuild container
./scripts/prod-restart.sh --rebuild
# Check container status
./scripts/prod-status.sh#### Database Issues
# Access MySQL
./scripts/prod-exec.sh mysql mysql -u root -prootpassword
# Run migrations manually
./scripts/prod-exec.sh backend go run cmd/migrate/main.go#### Emergency Rollback
# Restore from backup
./scripts/sync-environments.sh import ~/backups/reactgologin/reactgologin_prod_export_[DATE].tar.gz
# Or checkout previous commit and rebuild
ssh root@5.75.186.52
cd /root/reactgologin
git checkout <previous-commit>
docker-compose build
docker-compose up -d
Production Environment Variables
After deployment, update the production .env file if needed:
./scripts/prod-exec.sh backend sh
# Then: cat .envImportant variables:
JWT_SECRET- Use a strong, unique secretAPI_URL- Set to your production URLNODE_ENV=production- Database passwords if different from defaults