Files
cv-site/doc/ARCHITECTURE.md
T
juanatsap 584cfe05b1 refactor: consolidate documentation into main README
- Removed redundant documentation files (ADDING-YOUR-PHOTO.md, ARCHITECTURE.md, DEPLOYMENT_SETUP.md)
- Moved essential information into the primary README for better discoverability
- Streamlined documentation structure to reduce maintenance overhead
2025-11-08 10:34:43 +00:00

396 lines
9.2 KiB
Markdown

# Architecture Documentation
## Overview
This CV website is built following Go best practices with a focus on:
- **Simplicity**: Clean, readable code
- **Maintainability**: Well-structured packages
- **Reliability**: Proper error handling and logging
- **Performance**: Efficient template caching
- **Security**: Multiple layers of protection
## Architecture Patterns
### 1. Package Structure (Internal Directory Pattern)
```
cv/
├── main.go # Application entry point
└── internal/ # Private packages (cannot be imported by other projects)
├── config/ # Configuration management
├── handlers/ # HTTP request handlers
├── middleware/ # HTTP middleware
├── models/ # Data models and business logic
└── templates/ # Template management
```
**Benefits**:
- Clear separation of concerns
- Encapsulation (internal packages cannot be imported externally)
- Easy to test and maintain
- Scalable structure
### 2. Dependency Injection
Handlers and services receive their dependencies through constructors:
```go
// ✅ Good: Dependencies injected
type CVHandler struct {
templates *templates.Manager
}
func NewCVHandler(tmpl *templates.Manager) *CVHandler {
return &CVHandler{templates: tmpl}
}
// ❌ Bad: Global state
var globalTemplates *template.Template
```
**Benefits**:
- Testability (easy to mock dependencies)
- Flexibility (swap implementations)
- Explicit dependencies
### 3. Error Handling Strategy
Three-tier error handling:
```go
// 1. Domain errors (AppError)
type AppError struct {
Err error // Original error
Message string // User-friendly message
StatusCode int // HTTP status
Internal bool // Hide details from client
}
// 2. Error constructors for common cases
NotFoundError("Resource not found")
BadRequestError("Invalid input")
InternalError(err)
// 3. Centralized error handler
HandleError(w, r, err)
```
**Benefits**:
- Consistent error responses
- Proper logging
- Security (internal errors hidden)
- Client-specific responses (JSON, HTML, HTMX)
### 4. Middleware Chain
Onion-like middleware wrapping:
```
Request → Recovery → Logger → Security → Handler → Response
↑ ↑ ↑ ↑
Panics Logging Headers Business Logic
```
**Implementation**:
```go
handler := middleware.Recovery(
middleware.Logger(
middleware.SecurityHeaders(mux),
),
)
```
**Benefits**:
- Separation of cross-cutting concerns
- Reusable components
- Easy to add/remove middleware
- Predictable request flow
## Component Details
### Configuration Management (`internal/config`)
**Pattern**: Environment-based configuration with sensible defaults
```go
cfg := config.Load() // Reads from env vars
cfg.Server.Port // Defaults to "1999"
cfg.Template.HotReload // Auto-detects development mode
```
**Features**:
- Environment variable support
- Type-safe configuration
- Development/production modes
- Sensible defaults
### Template Management (`internal/templates`)
**Pattern**: Template manager with hot-reload support
```go
manager := templates.NewManager(cfg)
manager.Render("index.html") // Hot-reloads in dev mode
```
**Features**:
- Centralized template loading
- Custom template functions
- Hot-reload in development
- Thread-safe caching
- Graceful error handling
### HTTP Handlers (`internal/handlers`)
**Pattern**: Handler structs with methods
```go
type CVHandler struct {
templates *templates.Manager
}
func (h *CVHandler) Home(w http.ResponseWriter, r *http.Request)
func (h *CVHandler) CVContent(w http.ResponseWriter, r *http.Request)
```
**Features**:
- Clean separation of routes
- Dependency injection
- Consistent error handling
- HTMX-aware responses
### Middleware (`internal/middleware`)
**Components**:
1. **Recovery**: Catches panics, logs stack traces
2. **Logger**: Structured request/response logging
3. **SecurityHeaders**: CSP, XSS protection, clickjacking prevention
## Security Features
### 1. Security Headers
```go
X-Frame-Options: SAMEORIGIN // Prevent clickjacking
X-Content-Type-Options: nosniff // Prevent MIME sniffing
X-XSS-Protection: 1; mode=block // XSS protection
Content-Security-Policy: ... // Restrict resource loading
Referrer-Policy: strict-origin-... // Control referrer info
```
### 2. Request Timeouts
```go
server := &http.Server{
ReadTimeout: 15 * time.Second, // Prevent slow clients
WriteTimeout: 15 * time.Second, // Prevent slow responses
IdleTimeout: 120 * time.Second, // Keep-alive timeout
}
```
### 3. Error Information Hiding
```go
appErr := NewAppError(err, "Database error", 500, true)
// Client sees: "Internal Server Error"
// Logs show: actual error details
```
## Performance Optimizations
### 1. Template Caching
```go
// Templates parsed once at startup
templates := template.New("").ParseGlob("*.html")
// Hot-reload only in development
if cfg.Template.HotReload {
templates.ParseGlob("*.html") // Re-parse on each request
}
```
### 2. Static File Caching
```go
// Development: 1 hour cache
// Production: 1 day cache
Cache-Control: public, max-age=86400
```
### 3. HTTP/2 Support
Go's `http.Server` automatically supports HTTP/2 when using HTTPS.
## Graceful Shutdown
```go
// 1. Listen for signals
shutdown := make(chan os.Signal, 1)
signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM)
// 2. Shutdown with timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
server.Shutdown(ctx)
```
**Features**:
- Finish in-flight requests
- 30-second grace period
- Forced shutdown if timeout exceeded
## HTMX Integration Patterns
### 1. Partial Content Rendering
```go
// Full page: /
// Partial: /cv?lang=es (returns only content div)
if r.Header.Get("HX-Request") != "" {
// HTMX request - return partial
renderPartial()
} else {
// Regular request - return full page
renderFull()
}
```
### 2. Language Switching
```html
<button hx-get="/cv?lang=es"
hx-target="#cv-content"
hx-swap="innerHTML">
🇪🇸 Español
</button>
```
**Benefits**:
- No JavaScript frameworks needed
- Progressive enhancement
- Server-rendered content
- Better SEO
## Testing Strategy
### Manual Testing
```bash
# 1. Health check
curl http://localhost:1999/health
# 2. Happy path
curl "http://localhost:1999/?lang=en"
# 3. Error cases
curl "http://localhost:1999/?lang=invalid" # 400 Bad Request
# 4. HTMX requests
curl -H "HX-Request: true" "http://localhost:1999/cv?lang=es"
# 5. Security headers
curl -I http://localhost:1999/
```
### Future: Automated Tests
```go
func TestCVHandler_Home(t *testing.T) {
// Setup
cfg := &config.TemplateConfig{Dir: "../../templates"}
tmpl, _ := templates.NewManager(cfg)
handler := handlers.NewCVHandler(tmpl)
// Execute
req := httptest.NewRequest("GET", "/?lang=en", nil)
w := httptest.NewRecorder()
handler.Home(w, req)
// Assert
assert.Equal(t, 200, w.Code)
}
```
## Deployment Options
### 1. Standalone Binary
```bash
go build -o cv-server -ldflags="-s -w" .
./cv-server
```
### 2. Docker
```bash
docker build -t cv-server .
docker run -p 1999:1999 cv-server
```
### 3. Cloud Platforms
**Recommended**:
- **Fly.io**: `fly launch` (auto-detects Dockerfile)
- **Railway**: Connect GitHub, auto-deploy
- **Google Cloud Run**: Serverless containers
- **AWS ECS/Fargate**: Container orchestration
## Best Practices Applied
1.**Standard Project Layout**: Internal packages, clear structure
2.**Error Handling**: Custom error types, consistent handling
3.**Logging**: Structured, informative logs
4.**Configuration**: Environment-based with defaults
5.**Security**: Multiple layers of protection
6.**Graceful Shutdown**: Clean service termination
7.**Dependency Injection**: Testable, maintainable code
8.**Middleware Pattern**: Separation of concerns
9.**Template Management**: Efficient, cached rendering
10.**Production-Ready**: Timeouts, health checks, monitoring hooks
## Scaling Considerations
### Current State: Single Instance
- Perfect for CV website (low traffic)
- ~1000s of requests/second capability
- Minimal resource usage
### Future: Multi-Instance (if needed)
1. **Load Balancer**: nginx, Caddy, or cloud LB
2. **Shared Storage**: For static files (S3, Cloud Storage)
3. **Health Checks**: `/health` endpoint already implemented
4. **Metrics**: Add Prometheus metrics
5. **Caching**: Redis for template cache (if very high traffic)
## Monitoring & Observability
### Current Implementation
- **Structured Logging**: Request/response logging
- **Health Check**: `/health` endpoint
- **Error Tracking**: Detailed error logs with stack traces
### Future Enhancements
```go
// Metrics
prometheus.InstrumentHandler("/", handler)
// Distributed Tracing
opentelemetry.Trace(handler)
// Error Monitoring
sentry.CaptureException(err)
```
## Conclusion
This architecture provides:
- ✅ Clean, maintainable code
- ✅ Production-ready error handling
- ✅ Security best practices
- ✅ Performance optimizations
- ✅ Easy deployment options
- ✅ Room for future growth
Perfect for a professional CV website with potential to scale.