# Gadget Code Landing Site

Static React/Vite landing page for Gadget Code, served at [https://g4dge7.com](https://g4dge7.com).

---

## Production Environment

### Host Configuration

| Setting | Value |
|---------|-------|
| **Provider** | DigitalOcean Droplet |
| **Hostname** | `gadget-site` |
| **Domain** | `g4dge7.com` |
| **Git Subdomain** | `git.g4dge7.com` |
| **OS** | Ubuntu 24.04.3 LTS |
| **Web Server** | Nginx 1.24.0 |
| **SSL** | Let's Encrypt (Certbot) |

### Service Architecture

```
g4dge7.com          → Nginx → /var/www/g4dge7.com (static site)
git.g4dge7.com      → Nginx → Gitea (port 3000)
```

### Directory Structure

| Path | Purpose |
|------|---------|
| `/var/www/g4dge7.com` | Production static site files |
| `/var/www/certbot` | Let's Encrypt ACME challenge files |
| `/etc/nginx/sites-available/g4dge7.com` | Nginx config for main site |
| `/etc/nginx/sites-available/git.g4dge7.com` | Nginx config for Gitea |
| `/etc/letsencrypt/live/g4dge7.com/` | SSL certificates for main domain |
| `/etc/letsencrypt/live/git.g4dge7.com/` | SSL certificates for git subdomain |

### Nginx Configuration Summary

**g4dge7.com** (`/etc/nginx/sites-available/g4dge7.com`):
- Listens on ports 80 and 443
- HTTP redirects to HTTPS (301)
- Serves static files from `/var/www/g4dge7.com`
- SPA fallback: all routes serve `index.html`
- Gzip compression enabled
- Security headers: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy
- Static assets cached for 1 year

**git.g4dge7.com** (`/etc/nginx/sites-available/git.g4dge7.com`):
- Listens on ports 80 and 443
- HTTP redirects to HTTPS (301)
- Proxies to Gitea at `http://127.0.0.1:3000`
- WebSocket support enabled for real-time features

---

## Development

### Prerequisites

- Node.js 18+
- pnpm (recommended) or npm

### Setup

```bash
cd site
pnpm install
```

### Commands

```bash
pnpm dev          # Start Vite dev server
pnpm build        # Type check and build for production
pnpm preview      # Preview production build locally
pnpm typecheck    # Run TypeScript type checking only
```

### Build Output

Production builds are output to `site/dist/`:
- `index.html` - Entry point
- `assets/` - Bundled JS, CSS, and other assets
- `*.png` - Static images (favicon, icons, etc.)

---

## Deployment to Production

### Full Deployment Process

```bash
# 1. Build the site
cd /home/rob/workspaces/core-001/gadget/site
pnpm build

# 2. Sync to production server
rsync -avz --delete dist/ g4dge7.com:/var/www/g4dge7.com/

# 3. Set correct ownership (if needed)
ssh g4dge7.com "chown -R www-data:www-data /var/www/g4dge7.com"

# 4. Reload Nginx (usually not needed, but safe to run)
ssh g4dge7.com "nginx -t && systemctl reload nginx"
```

### Quick Deploy (One-Liner)

```bash
pnpm build && rsync -avz --delete dist/ g4dge7.com:/var/www/g4dge7.com/ && ssh g4dge7.com "chown -R www-data:www-data /var/www/g4dge7.com"
```

### Deployment Checklist

- [ ] Build completes without errors
- [ ] rsync completes without errors
- [ ] Site loads at https://g4dge7.com
- [ ] No console errors in browser dev tools
- [ ] Git server still accessible at https://git.g4dge7.com

---

## SSL Certificate Management

### Renewal

Certbot is configured for automatic renewal via systemd timer. Manual renewal:

```bash
ssh g4dge7.com "certbot renew --dry-run"  # Test renewal
ssh g4dge7.com "certbot renew"            # Actual renewal
```

### Certificate Locations

| Domain | Certificate | Private Key |
|--------|-------------|-------------|
| g4dge7.com | `/etc/letsencrypt/live/g4dge7.com/fullchain.pem` | `/etc/letsencrypt/live/g4dge7.com/privkey.pem` |
| git.g4dge7.com | `/etc/letsencrypt/live/git.g4dge7.com/fullchain.pem` | `/etc/letsencrypt/live/git.g4dge7.com/privkey.pem` |

---

## Troubleshooting

### Site not loading

```bash
# Check Nginx status
ssh g4dge7.com "systemctl status nginx"

# Check Nginx config
ssh g4dge7.com "nginx -t"

# Check if files exist
ssh g4dge7.com "ls -la /var/www/g4dge7.com/"

# Check Nginx error logs
ssh g4dge7.com "tail -50 /var/log/nginx/error.log"
```

### SSL certificate issues

```bash
# Check certificate expiry
ssh g4dge7.com "certbot certificates"

# Force renewal
ssh g4dge7.com "certbot renew --force-renewal"
```

### Gitea not accessible

```bash
# Check Gitea status
ssh g4dge7.com "systemctl status gitea"

# Check if port 3000 is listening
ssh g4dge7.com "ss -tlnp | grep 3000"

# Check Gitea logs
ssh g4dge7.com "journalctl -u gitea --no-pager -n 50"
```

### SSH access issues

Use the direct IP for SSH (Cloudflare doesn't proxy SSH):

```bash
ssh root@157.230.50.250
```

---

## Security Notes

- **IP-only Git access**: Git SSH access requires the droplet IP (`157.230.50.250`), not the domain. This is intentional—Cloudflare doesn't proxy SSH, and this limits access to trusted parties.
- **No shell access for git user**: The `git` system user can only execute Gitea commands via authorized_keys restrictions.
- **Security headers**: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, and Referrer-Policy are all configured.
- **HTTPS only**: Both domains redirect HTTP to HTTPS automatically.

---

## Contact

For issues or questions about this deployment, contact the system administrator.
