Remove the module "xxx" { source = "./module" } indirection layer
from all 66 service stacks. Resources are now defined directly in
each stack's main.tf instead of through a wrapper module.
- Merge module/main.tf contents into stack main.tf
- Apply variable replacements (var.tier -> local.tiers.X, renamed vars)
- Fix shared module paths (one fewer ../ at each level)
- Move extra files/dirs (factory/, chart_values, subdirs) to stack root
- Update state files to strip module.<name>. prefix
- Update CLAUDE.md to reflect flat structure
Verified: terragrunt plan shows 0 add, 0 destroy across all stacks.
8.4 KiB
8.4 KiB
Codebase Structure
Analysis Date: 2026-02-17
Directory Layout
f1-stream/
├── main.go # Entry point, service initialization, signal handling
├── go.mod # Go module definition
├── go.sum # Dependency lock file
├── Dockerfile # Container image definition
├── redeploy.sh # Kubernetes redeployment script
├── index.html # HTML template served at root
├── internal/ # Private Go packages
│ ├── auth/ # WebAuthn authentication and session management
│ ├── models/ # Domain data types
│ ├── server/ # HTTP handlers, routes, middleware
│ ├── store/ # File-based persistence layer
│ ├── scraper/ # Reddit content scraper
│ └── proxy/ # HTTP proxy with rate limiting
├── static/ # Frontend assets served to clients
│ ├── index.html # Main SPA template
│ ├── css/ # Stylesheets
│ └── js/ # Client-side JavaScript modules
└── .planning/ # Planning/documentation directory
└── codebase/ # Architecture analysis documents
Directory Purposes
Root Level:
- Purpose: Service configuration and entry point
- Contains: Go module, main executable, Docker configuration, shell scripts
- Key files:
main.go(service bootstrap),go.mod(dependencies)
internal/:
- Purpose: Private packages (not importable by external code)
- Contains: All business logic, separated by concern
- Key pattern: Each subdirectory is a distinct Go package with clear responsibility
internal/auth/:
- Purpose: User authentication, session management, context helpers
- Contains: WebAuthn ceremony handlers, session token management, user-in-context utilities
- Key files:
auth.go: Registration/login handlers, ceremony session storage, credential validationcontext.go: Request context helpers for passing user data between middleware and handlers
internal/models/:
- Purpose: Domain model definitions
- Contains: User, Stream, ScrapedLink, Session type definitions
- Key files:
models.go(all types, includes WebAuthn interface implementations)
internal/server/:
- Purpose: HTTP API and routing layer
- Contains: Handler functions, route registration, middleware implementations
- Key files:
server.go: Server struct, route registration, API handlers (streams, admin, public endpoints)middleware.go: LoggingMiddleware, RecoveryMiddleware, AuthMiddleware, RequireAuth, RequireAdmin, OriginCheck
internal/store/:
- Purpose: Persistent storage abstraction over file system
- Contains: JSON file operations, per-entity storage methods, atomic write patterns
- Key files:
store.go: Store struct, directory initialization, JSON helper functions (readJSON, writeJSON)streams.go: Stream CRUD operations, publish toggle, seedingusers.go: User lookup, credential updates, admin countsessions.go: Session creation, validation, expiry cleanupscraped.go: Scraped link persistence, active link filtering
internal/scraper/:
- Purpose: Background content aggregation
- Contains: Interval-based scraper, Reddit-specific scraper logic
- Key files:
scraper.go: Scraper service, interval-based run loop, manual trigger mechanism, deduplication logicreddit.go: Reddit API polling, F1 keyword filtering, URL extraction (not included in sample reads but referenced)
internal/proxy/:
- Purpose: HTTP content fetching with security controls and rate limiting
- Contains: Rate limiter, private IP validation, response modification
- Key files:
proxy.go(implements http.Handler, rate limiting, content fetching, base tag injection)
static/:
- Purpose: Frontend assets served to browser
- Contains: HTML template and client-side code
- Key files:
index.html: SPA HTML template (includes script tags loading js/)js/app.js: Toast notifications, dialog system, tab switching, initializationjs/auth.js: Registration/login UI, WebAuthn client ceremonyjs/streams.js: Stream display, filtering, admin operationsjs/utils.js: Shared utilities (HTML escaping)css/: Stylesheets for app UI
Key File Locations
Entry Points:
main.go: Service initialization, dependency injection, signal handling, goroutine startup
Configuration:
- Environment variables read in
main.go(LISTEN_ADDR, DATA_DIR, SCRAPE_INTERVAL, etc.) - WebAuthn config passed to
auth.New() .envfiles not tracked (see .gitignore)
Core Logic:
- Request routing:
internal/server/server.go:registerRoutes() - Auth logic:
internal/auth/auth.go - Data storage:
internal/store/store.goand per-entity files - Scraping:
internal/scraper/scraper.go - Proxying:
internal/proxy/proxy.go
Testing:
- No test files present in codebase (see TESTING.md concerns section)
Naming Conventions
Files:
- Go source files: lowercase with underscores (e.g.,
auth.go,middleware.go) - JavaScript files: lowercase with hyphens or underscores (e.g.,
app.js,auth.js) - JSON data files: lowercase (e.g.,
streams.json,users.json,sessions.json)
Directories:
- Go packages: lowercase, single word preferred (e.g.,
auth,store,models) - Frontend assets: plural nouns (e.g.,
static,css,js)
Functions:
- Go: CamelCase (exported), camelCase (unexported)
- JavaScript: camelCase throughout (e.g.,
loadPublicStreams(),showToast())
Types:
- Go structs: CamelCase (e.g.,
User,Stream,Store,Auth) - Methods: CamelCase (e.g.,
BeginLogin(),AddStream())
Variables:
- Go: camelCase (e.g.,
listenAddr,dataDir,adminUsername) - JavaScript: camelCase (e.g.,
container,userID,sessionToken)
Where to Add New Code
New Feature (e.g., new stream filter):
- Primary code: Add handler in
internal/server/server.go, register route inregisterRoutes() - Store operations: Add method to appropriate file in
internal/store/(likelystreams.go) - Frontend: Add UI in
static/and API call instatic/js/streams.jsor new module - Models: Extend types in
internal/models/models.goif new fields needed
New Authentication Method:
- Core implementation: New file in
internal/auth/(e.g.,oauth.go) - Handlers: Add methods following WebAuthn pattern (BeginXxx, FinishXxx)
- Routes: Register in
registerRoutes() - Frontend: Add form/button in
static/js/auth.js
New Background Service (e.g., content validator):
- Implementation: New file in
internal/or new packageinternal/validator/ - Integration: Initialize in
main()alongsidescraper.New() - Lifecycle: Use context pattern from scraper's
Run(ctx)method - Storage: Use existing
Storeinstance
Utilities/Helpers:
- Shared by Go packages: Add to package where most useful, or create new
internal/util/package - Shared by frontend: Add to
static/js/utils.jsor create new module - Shared helpers pattern: Functions not tied to single package, used across multiple
Special Directories
internal/:
- Purpose: Enforce package privacy (cannot be imported by external code)
- Generated: No
- Committed: Yes
static/:
- Purpose: Served directly to clients via
http.FileServer - Generated: No (hand-written frontend)
- Committed: Yes
.planning/codebase/:
- Purpose: Architecture documentation for development guidance
- Generated: No (manually created by mapping process)
- Committed: Yes
Data Directory (runtime):
- Purpose: Persistent JSON files (streams.json, users.json, sessions.json, scraped.json)
- Location: Specified by DATA_DIR env var (default
/data) - Generated: Yes (created on first run)
- Committed: No (varies per deployment environment)
Import Patterns
Go Package Imports:
- Standard library first:
import ("context" "fmt" "log") - Internal packages second:
import ("f1-stream/internal/auth" "f1-stream/internal/store") - External third-party last:
import ("github.com/go-webauthn/webauthn/webauthn")
Cross-Package Dependencies:
- Server depends on: Auth, Store, Proxy, Scraper, Models
- Auth depends on: Store, Models
- Scraper depends on: Store, Models
- Proxy depends on: none (standalone service)
- Store depends on: Models
- Models depends on: external WebAuthn library only
Structure analysis: 2026-02-17