Technology Overview
Vega AI is built with a modern, lightweight technology stack optimized for performance, simplicity, and ease of deployment.
Core Technologies
Backend Go 1.24.0 with domain-driven layered architecture
Database SQLite with WAL mode and multi-tenant support
Frontend Go Templates + HTMX + Hyperscript + Tailwind CSS (CDN)
AI Google Gemini API for analysis, generation, and parsing
Backend Framework
Web Framework - Gin
Version: v1.10.0
import " github.com/gin-gonic/gin "
router := gin . Default ()
router . GET ( "/health" , func ( c * gin . Context ) {
c . JSON ( http . StatusOK , gin . H { "status" : "ok" })
})
Why Gin:
High performance with minimal overhead
Built-in middleware support
Excellent routing and parameter binding
Active community and maintenance
Middleware Stack
CORS github.com/gin-contrib/cors v1.7.5 - Cross-origin resource sharing
Authentication Custom JWT middleware with user ID injection
Security Headers Content-Security-Policy, X-Frame-Options, HSTS
CSRF Protection Token-based CSRF protection for forms
Database Layer
SQLite with modernc.org Driver
Version: modernc.org/sqlite v1.37.0
import _ " modernc.org/sqlite "
db , err := sql . Open ( "sqlite" , "/app/data/vega.db?_journal_mode=WAL" )
Key Features:
Pure Go implementation (no CGO required)
WAL mode for concurrent reads and writes
Composite indexes for multi-tenant queries
Foreign key constraints enforced
Configuration:
type DBConfig struct {
MaxOpenConns int // 25 (production)
MaxIdleConns int // 5 (production)
ConnMaxLifetime time . Duration // 5 minutes
ConnMaxIdleTime time . Duration // 1 minute
}
Query Builder - Squirrel
Version: github.com/Masterminds/squirrel v1.5.4
import sq " github.com/Masterminds/squirrel "
sql , args , err := sq . Select ( "*" ).
From ( "jobs" ).
Where ( sq . Eq { "user_id" : userID , "status" : status }).
OrderBy ( "created_at DESC" ).
Limit ( 10 ).
ToSql ()
Benefits:
Type-safe query construction
SQL injection prevention
Easy to test and mock
Readable query building
Database Migrations
Version: github.com/golang-migrate/migrate/v4 v4.18.3
migrations/sqlite/
├── 000001_initial_schema.up.sql
├── 000001_initial_schema.down.sql
├── 000003_add_quota_system.up.sql
├── 000003_add_quota_system.down.sql
└── ...
import " github.com/golang-migrate/migrate/v4 "
func MigrateDatabase ( dbPath , migrationsDir string ) error {
m , err := migrate . New (
"file://" + migrationsDir ,
"sqlite://" + dbPath ,
)
if err != nil {
return err
}
return m . Up ()
}
Caching Layer
Badger v4 - Embedded Key-Value Store
Version: github.com/dgraph-io/badger/v4 v4.7.0
import " github.com/dgraph-io/badger/v4 "
type BadgerCache struct {
db * badger . DB
ctx context . Context
cancel context . CancelFunc
}
func ( c * BadgerCache ) Set ( ctx context . Context , key string , value interface {}, ttl time . Duration ) error {
data , _ := json . Marshal ( value )
return c . db . Update ( func ( txn * badger . Txn ) error {
e := badger . NewEntry ([] byte ( key ), data ). WithTTL ( ttl )
return txn . SetEntry ( e )
})
}
Cache Configuration:
Memory Limit 256MB default (configurable via CACHE_MAX_MEMORY_MB)
Default TTL 1 hour (max TTL enforced)
Garbage Collection Runs every 5 minutes
Value Log 100MB files, 10,000 entries max
User-scoped Cache Keys:
// Pattern: entity:u{userID}:identifier
"job:u123:45" // Job 45 for user 123
"profile:u123:details" // Profile for user 123
"stats:u123:dashboard" // Dashboard stats for user 123
NoOp Cache (Fallback)
type NoOpCache struct {}
func ( n * NoOpCache ) Get ( ctx context . Context , key string , value interface {}) error {
return ErrCacheMiss // Always returns cache miss
}
Used when cache initialization fails for graceful degradation.
Authentication & Security
JWT - JSON Web Tokens
Version: github.com/golang-jwt/jwt/v5 v5.2.2
import " github.com/golang-jwt/jwt/v5 "
type Claims struct {
UserID int `json:"user_id"`
Username string `json:"username"`
Role string `json:"role"`
TokenType string `json:"token_type"` // "access" or "refresh"
jwt . RegisteredClaims
}
func ( s * AuthService ) GenerateTokenPair ( user * models . User ) ( * TokenPair , error ) {
accessToken := generateToken ( user , "access" , s . config . AccessTokenExpiry )
refreshToken := generateToken ( user , "refresh" , s . config . RefreshTokenExpiry )
return & TokenPair { AccessToken : accessToken , RefreshToken : refreshToken }, nil
}
Token Configuration:
Access Token: 60 minutes (configurable)
Refresh Token: 72 hours (configurable)
Storage: Secure HTTP-only cookies
Algorithm: HMAC-SHA256
OAuth 2.0 - Google Authentication
Version: golang.org/x/oauth2 v0.30.0
import " golang.org/x/oauth2 "
oauthConfig := & oauth2 . Config {
ClientID : cfg . GoogleClientID ,
ClientSecret : cfg . GoogleClientSecret ,
RedirectURL : cfg . GoogleClientRedirectURL ,
Scopes : [] string { "email" , "profile" },
Endpoint : google . Endpoint ,
}
OAuth Flow:
Initiate
User clicks “Sign in with Google”
Redirect
Application redirects to Google OAuth consent screen
Callback
Google redirects back with authorization code
Token Exchange
Exchange code for access token and user info
User Creation
Create/update user in database and issue JWT tokens
Password Hashing
Version: golang.org/x/crypto v0.46.0
import " golang.org/x/crypto/bcrypt "
func HashPassword ( password string ) ( string , error ) {
hash , err := bcrypt . GenerateFromPassword ([] byte ( password ), bcrypt . DefaultCost )
return string ( hash ), err
}
func VerifyPassword ( hashedPassword , password string ) error {
return bcrypt . CompareHashAndPassword ([] byte ( hashedPassword ), [] byte ( password ))
}
AI Provider
Google Gemini API
Version: google.golang.org/genai v1.11.1
import " google.golang.org/genai "
type GeminiProvider struct {
client * genai . Client
config * Config
jobModel * genai . GenerativeModel
cvModel * genai . GenerativeModel
}
func ( p * GeminiProvider ) Generate ( ctx context . Context , prompt string , modelType ModelType ) ( string , error ) {
model := p . selectModel ( modelType )
resp , err := model . GenerateContent ( ctx , genai . Text ( prompt ))
// ...
}
Model Configuration:
Default Model gemini-2.5-flash - Fast, general-purpose
CV Parsing gemini-2.5-flash - Quick profile extraction
Job Analysis gemini-2.5-flash - Deep compatibility analysis
Cover Letter gemini-2.5-flash - Professional letter generation
Environment Variables:
GEMINI_API_KEY = your-api-key
GEMINI_MODEL = gemini-2.5-flash
GEMINI_MODEL_CV_PARSING = gemini-2.5-flash
GEMINI_MODEL_JOB_ANALYSIS = gemini-2.5-flash
GEMINI_MODEL_COVER_LETTER = gemini-2.5-flash
Frontend Technologies
Go HTML Templates
router . SetFuncMap ( template . FuncMap {
"safeHTML" : func ( s string ) template . HTML {
return template . HTML ( s )
},
"dict" : func ( values ... interface {}) ( map [ string ] interface {}, error ) {
// Create dict for templates
},
})
router . LoadHTMLFiles ( files ... )
Custom Template Functions:
safeHTML - Render HTML without escaping
dict - Create key-value maps in templates
default - Provide default values
add, sub, mul, min, max - Math operations
pageRange - Pagination helpers
matchColors - Color coding for match scores
cappedQuota - Quota display helpers
HTMX - Dynamic HTML
<!-- Job form with HTMX -->
< form hx-post = "/jobs/new" hx-target = "#job-list" hx-swap = "afterbegin" >
< input type = "text" name = "title" required >
< button type = "submit" > Add Job </ button >
</ form >
<!-- Status update -->
< select hx-post = "/jobs/{{.ID}}/status"
hx-trigger = "change"
hx-target = "#job-{{.ID}}" >
< option value = "interested" > Interested </ option >
< option value = "applied" > Applied </ option >
</ select >
Tailwind CSS (CDN)
< link href = "https://cdn.jsdelivr.net/npm/tailwindcss@3/dist/tailwind.min.css" rel = "stylesheet" >
<!-- Example component -->
< div class = "bg-gray-800 rounded-lg p-6 shadow-lg" >
< h2 class = "text-xl font-bold text-primary" > Job Title </ h2 >
< p class = "text-gray-400 mt-2" > Company Name </ p >
</ div >
Logging & Monitoring
Zerolog - Structured Logging
Version: github.com/rs/zerolog v1.34.0
import " github.com/rs/zerolog/log "
log . Info (). Str ( "port" , serverPort ). Msg ( "Starting server" )
log . Error (). Err ( err ). Int ( "user_id" , userID ). Msg ( "Failed to create job" )
log . Debug (). Interface ( "config" , cfg ). Msg ( "Configuration loaded" )
GDPR-Compliant Logging:
type PrivacyLogger struct {
logger zerolog . Logger
}
func ( p * PrivacyLogger ) LogAuthEvent ( event string , userID int , success bool ) {
// Logs event without PII
p . logger . Info ().
Str ( "event" , event ).
Int ( "user_ref" , userID ).
Bool ( "success" , success ).
Msg ( "Auth event" )
}
func HashIdentifier ( identifier string ) string {
h := sha256 . Sum256 ([] byte ( identifier ))
return base64 . URLEncoding . EncodeToString ( h [:])
}
What NOT to Log:
Email addresses
Usernames or names
IP addresses
OAuth tokens
Any direct PII
Testing Stack
Testing Framework github.com/stretchr/testify v1.10.0 - Assertions and test suites
Mock Generation github.com/vektra/mockery/v2 v2.53.5 - Interface mocks
SQL Mocking github.com/DATA-DOG/go-sqlmock v1.5.2 - Database mocks
Validation github.com/go-playground/validator/v10 v10.26.0 - Struct validation
import (
" github.com/stretchr/testify/assert "
" github.com/stretchr/testify/mock "
)
func TestJobService_Create ( t * testing . T ) {
mockRepo := mocks . NewMockJobRepository ( t )
mockRepo . On ( "Create" , mock . Anything , 1 , mock . Anything ). Return ( nil )
service := NewJobService ( mockRepo )
err := service . Create ( context . Background (), 1 , & models . Job {})
assert . NoError ( t , err )
mockRepo . AssertExpectations ( t )
}
Development Dependencies
Complete Dependency List
require (
github . com / Masterminds / squirrel v1 . 5.4
github . com / dgraph - io / badger / v4 v4 . 7.0
github . com / gin - contrib / cors v1 . 7.5
github . com / gin - gonic / gin v1 . 10.0
github . com / golang - jwt / jwt / v5 v5 . 2.2
github . com / golang - migrate / migrate / v4 v4 . 18.3
github . com / go - playground / validator / v10 v10 . 26.0
github . com / google / uuid v1 . 6.0
github . com / rs / zerolog v1 . 34.0
golang . org / x / crypto v0 . 46.0
golang . org / x / oauth2 v0 . 30.0
google . golang . org / genai v1 . 11.1
modernc . org / sqlite v1 . 37.0
)
Infrastructure
Containerization Docker - Multi-stage builds for production
CI/CD GitHub Actions - Automated testing and deployment
Container Registry GitHub Container Registry (GHCR) - Docker image hosting
Deployment Docker Compose - Local and production deployments
Docker Configuration
# Multi-stage build
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o vega cmd/vega/main.go
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/vega .
COPY --from=builder /app/templates ./templates
COPY --from=builder /app/static ./static
COPY --from=builder /app/migrations ./migrations
EXPOSE 8765
CMD [ "./vega" ]
Configuration Management
All configuration via environment variables with sensible defaults:
# Core
SERVER_PORT = :8765
DB_CONNECTION_STRING = /app/data/vega.db? _journal_mode = WAL
TOKEN_SECRET = your-secret-key
# Authentication
ACCESS_TOKEN_EXPIRY = 60 # minutes
REFRESH_TOKEN_EXPIRY = 72 # hours
# Google OAuth (Cloud Mode)
GOOGLE_CLIENT_ID = your-client-id
GOOGLE_CLIENT_SECRET = your-client-secret
# AI
GEMINI_API_KEY = your-api-key
# Cache
CACHE_PATH = ./data/cache
CACHE_MAX_MEMORY_MB = 256
CACHE_DEFAULT_TTL = 1h
# Features
CLOUD_MODE = false
ENABLE_SECURITY_HEADERS = true
ENABLE_CSRF = true
All secrets support _FILE suffix for Docker secrets integration (e.g., TOKEN_SECRET_FILE=/run/secrets/token_secret).