This commit is contained in:
Tomáš Dvořák
2025-10-16 13:32:05 +02:00
commit 12cba639b9
663 changed files with 168914 additions and 0 deletions
+236
View File
@@ -0,0 +1,236 @@
# Umami Setup with Actual Club Name and Domain
## Changes Made
### Problem Solved
Previously, Umami created websites with:
- **Name:** "Fotbal Club (Dev)" (hardcoded)
- **Domain:** "localhost" (hardcoded)
Now it uses:
- **Name:** Actual club name from setup form
- **Domain:** Auto-detected from Host header (works with Cloudflare Tunnel!)
### How It Works with Cloudflare Tunnel
When you route through Cloudflare Tunnel to a club's domain:
```
User → fotbalklub.cz → Cloudflare Tunnel → Your Local Backend
```
The HTTP request will have:
```
Host: fotbalklub.cz
```
The backend reads this header and creates the Umami website with the correct domain!
### Implementation Details
**Frontend (`SetupPage.tsx`):**
- Calls `POST /api/v1/umami/initialize-setup` during step 3
- Sends: `{ "name": "SK Slavia Litomyšl" }` (from club name field)
- Domain is auto-detected by backend
**Backend (`umami_controller.go`):**
- New endpoint: `POST /api/v1/umami/initialize-setup`
- No authentication required (public, called during setup)
- Extracts domain from `c.Request.Host` header
- Removes port if present (`:8080` → ``)
- Calls Umami API to create website
- Stores website ID in memory
**Backend Flow:**
```go
// 1. Get club name from request
name := payload.Name // "SK Slavia Litomyšl"
// 2. Auto-detect domain from Host header
domain := c.Request.Host // "fotbalklub.cz" or "localhost:8080"
if i := strings.Index(domain, ":"); i >= 0 {
domain = domain[:i] // Remove port
}
// 3. Create Umami website
websiteID := umamiService.EnsureWebsite(name, domain)
```
## Testing
### 1. Local Development Test
```bash
# Restart backend
go run main.go
# Open setup page
# Fill in club name: "Test Club"
# Complete setup
# Backend will create:
# Name: "Test Club"
# Domain: "localhost"
```
### 2. Cloudflare Tunnel Test
```bash
# Start Cloudflare tunnel
cloudflared tunnel --url http://localhost:8080
# Or with named tunnel:
cloudflared tunnel run <tunnel-name>
# Access via club domain (e.g., fotbalklub.cz)
# Fill in club name: "SK Slavia Litomyšl"
# Complete setup
# Backend will create:
# Name: "SK Slavia Litomyšl"
# Domain: "fotbalklub.cz"
```
### 3. Verify in Umami Dashboard
1. Login to https://umami.tdvorak.dev
2. Check websites list
3. You should see the club's actual name and domain
### 4. Test via API
```powershell
# After setup, check the website was created
$body = @{
username = "admin"
password = "eevRQ6h3G@!c#y4A1T"
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "https://umami.tdvorak.dev/api/auth/login" `
-Method Post `
-ContentType "application/json" `
-Body $body
$token = $response.token
$headers = @{ Authorization = "Bearer $token" }
$websites = Invoke-RestMethod -Uri "https://umami.tdvorak.dev/api/websites" `
-Headers $headers
# Should show the new website with club name and domain
$websites.data | Format-Table name, domain, id
```
## Environment Configuration
Your `.env` file should have:
```env
# Umami Analytics
UMAMI_URL=https://umami.tdvorak.dev
UMAMI_USERNAME=admin
UMAMI_PASSWORD=eevRQ6h3G@!c#y4A1T
# Leave empty - will be auto-created during setup
UMAMI_WEBSITE_ID=
```
**Important:** No inline comments on `UMAMI_WEBSITE_ID` line!
## Cloudflare Tunnel Setup
### Quick Start
```bash
# Install cloudflared
# Windows: Download from https://github.com/cloudflare/cloudflared/releases
# Login to Cloudflare
cloudflared tunnel login
# Create tunnel
cloudflared tunnel create my-fotbal-club
# Configure tunnel (create config.yml):
tunnel: <tunnel-id>
credentials-file: C:\Users\<you>\.cloudflared\<tunnel-id>.json
ingress:
- hostname: fotbalklub.cz
service: http://localhost:8080
- service: http_status:404
# Create DNS record in Cloudflare dashboard:
# Type: CNAME
# Name: @ (or subdomain)
# Target: <tunnel-id>.cfargotunnel.com
# Run tunnel
cloudflared tunnel run my-fotbal-club
```
### Testing the Tunnel
```bash
# Check if tunnel is working
curl https://fotbalklub.cz/api/v1/health
# Should return 200 OK
```
## Files Modified
1. **Frontend:**
- `frontend/src/pages/SetupPage.tsx`
- Changed from `GET /umami/config` to `POST /umami/initialize-setup`
- Passes club name: `{ name: clubName }`
- Domain auto-detected by backend
2. **Backend:**
- `internal/controllers/umami_controller.go`
- Added `InitializeUmamiSetup()` function
- Auto-detects domain from `c.Request.Host`
- Removes port number
- Creates website with actual name and domain
- `internal/routes/routes.go`
- Added route: `POST /api/v1/umami/initialize-setup` (public, no auth)
## Benefits
1.**Correct club names** in Umami dashboard
2.**Correct domains** (not "localhost" in production)
3.**Works with Cloudflare Tunnel** automatically
4.**No manual configuration** needed
5.**Clean Umami dashboard** with proper website names
## Troubleshooting
### Issue: Still showing "localhost"
**Cause:** Accessing via `http://localhost:8080` directly
**Fix:** Access via Cloudflare Tunnel URL or set proper Host header
### Issue: Website name still "Fotbal Club (Dev)"
**Cause:** Old website exists from previous setup
**Solution:**
1. Login to Umami dashboard
2. Delete the old "Fotbal Club (Dev)" website
3. Clear `.env`: `UMAMI_WEBSITE_ID=`
4. Restart backend
5. Run setup again
### Issue: Domain includes port (e.g., "fotbalklub.cz:8080")
**Cause:** This shouldn't happen - the code strips ports
**Fix:** Check the backend logs for the actual domain being used
## Production Deployment Checklist
- [ ] Set up Cloudflare Tunnel
- [ ] Point club's domain to tunnel
- [ ] Verify `.env` has `UMAMI_WEBSITE_ID=` (empty)
- [ ] Clear any old Umami websites in dashboard
- [ ] Run initial setup via club's domain
- [ ] Verify in Umami dashboard: correct name and domain
- [ ] Test tracking: visit pages and check Umami stats
## Expected Result
After setup via `https://fotbalklub.cz`, Umami dashboard shows:
```
Name: SK Slavia Litomyšl
Domain: fotbalklub.cz
ID: <auto-generated-uuid>
```
Perfect! 🎉