Parallel analysis of tech stack, architecture, structure, conventions, testing patterns, integrations, and concerns. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7.8 KiB
Coding Conventions
Analysis Date: 2026-03-23
Naming Patterns
Go Files:
- Package-level source files use the package name:
diunwebhook.go - Test files follow Go convention:
diunwebhook_test.go - Test-only export files:
export_test.go - Entry point:
main.goinsidecmd/diunwebhook/
Go Functions:
- PascalCase for exported functions:
WebhookHandler,UpdateEvent,InitDB,GetUpdates - Handler functions are named
<Noun>Handler:WebhookHandler,UpdatesHandler,DismissHandler,TagsHandler,TagByIDHandler,TagAssignmentHandler - Test functions use
Test<FunctionName>_<Scenario>:TestWebhookHandler_BadRequest,TestDismissHandler_NotFound
Go Types:
- PascalCase structs:
DiunEvent,UpdateEntry,Tag - JSON tags use snake_case:
json:"diun_version",json:"hub_link",json:"received_at"
Go Variables:
- Package-level unexported variables use short names:
mu,db,webhookSecret - Local variables use short idiomatic Go names:
w,r,err,res,n,e
TypeScript Files:
- Components: PascalCase
.tsxfiles:ServiceCard.tsx,AcknowledgeButton.tsx,Header.tsx,TagSection.tsx - Hooks: camelCase with
useprefix:useUpdates.ts,useTags.ts - Types: camelCase
.tsfiles:diun.ts - Utilities: camelCase
.tsfiles:utils.ts,time.ts,serviceIcons.ts - UI primitives (shadcn): lowercase
.tsxfiles:badge.tsx,button.tsx,card.tsx,tooltip.tsx
TypeScript Functions:
- camelCase for regular functions and hooks:
fetchUpdates,useUpdates,getServiceIcon - PascalCase for React components:
ServiceCard,StatCard,AcknowledgeButton - Helper functions within components use camelCase:
getInitials,getTag,getShortName - Event handlers prefixed with
handle:handleDragEnd,handleNewGroupSubmit
TypeScript Types:
- PascalCase interfaces:
DiunEvent,UpdateEntry,Tag,ServiceCardProps - Type aliases: PascalCase:
UpdatesMap - Interface properties use snake_case matching the Go JSON tags:
diun_version,hub_link
Code Style
Go Formatting:
gofmtenforced in CI (formatting check fails the build)- No additional Go linter (golangci-lint) configured
go vetruns in CI- Standard Go formatting: tabs for indentation
TypeScript Formatting:
- No ESLint or Prettier configured in the frontend
- No formatting enforcement in CI for frontend code
- Consistent 2-space indentation observed in all
.tsxand.tsfiles - Single quotes for strings in TypeScript
- No semicolons (observed in all frontend files)
- Trailing commas used in multi-line constructs
TypeScript Strictness:
strict: trueintsconfig.app.jsonnoUnusedLocals: truenoUnusedParameters: truenoFallthroughCasesInSwitch: truenoUncheckedSideEffectImports: true
Import Organization
Go Import Order: Standard library imports come first, followed by a blank line, then the project import using the module alias:
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"testing"
diun "awesomeProject/pkg/diunwebhook"
)
- The project module is aliased as
diunin bothmain.goand test files - The blank-import pattern
_ "modernc.org/sqlite"is used for the SQLite driver inpkg/diunwebhook/diunwebhook.go
TypeScript Import Order:
- React and framework imports (
react,@dnd-kit/core) - Internal imports using
@/path alias (@/hooks/useUpdates,@/components/Header) - Type-only imports:
import type { Tag, UpdatesMap } from '@/types/diun'
Path Aliases:
@/maps tofrontend/src/(configured invite.config.tsandtsconfig.app.json)
Error Handling
Go Patterns:
- Handlers use
http.Error(w, message, statusCode)for all error responses - Error messages are lowercase:
"bad request","internal error","not found","method not allowed" - Internal errors are logged with
log.Printfbefore returning HTTP 500 - Decode errors include context:
log.Printf("WebhookHandler: failed to decode request: %v", err) - Fatal errors in
main.gouselog.Fatalf errors.Is()used for sentinel error comparison (e.g.,http.ErrServerClosed)- String matching used for SQLite constraint errors:
strings.Contains(err.Error(), "UNIQUE")
TypeScript Patterns:
- API errors throw with HTTP status:
throw new Error(\HTTP ${res.status}`)` - Catch blocks use
console.errorfor logging - Error state stored in hook state:
setError(e instanceof Error ? e.message : 'Failed to fetch updates') - Optimistic updates used for tag assignment (update UI first, then call API)
Logging
Framework: Go standard log package
Patterns:
- Startup messages:
log.Printf("Listening on :%s", port) - Warnings:
log.Println("WARNING: WEBHOOK_SECRET not set ...") - Request logging on success:
log.Printf("Update received: %s (%s)", event.Image, event.Status) - Error logging before HTTP error response:
log.Printf("WebhookHandler: failed to store event: %v", err) - Handler name prefixed to log messages:
"WebhookHandler: ...","UpdatesHandler: ..."
Frontend: console.error for API failures, no structured logging
Comments
When to Comment:
- Comments are sparse in the Go codebase
- Handler functions have short doc comments describing the routes they handle:
// TagsHandler handles GET /api/tags and POST /api/tags // TagByIDHandler handles DELETE /api/tags/{id} // TagAssignmentHandler handles PUT /api/tag-assignments and DELETE /api/tag-assignments - Inline comments used for non-obvious behavior:
// Migration: add acknowledged_at to existing databases - No JSDoc/TSDoc in the frontend codebase
Function Design
Go Handler Pattern:
- Each handler is a standalone
func(http.ResponseWriter, *http.Request) - Method checking done at the top of each handler (not via middleware)
- Multi-method handlers use
switch r.Method - URL path parameters extracted via
strings.TrimPrefix - Request bodies decoded with
json.NewDecoder(r.Body).Decode(&target) - Responses written with
json.NewEncoder(w).Encode(data)orw.WriteHeader(status) - Mutex (
mu) used around write operations to SQLite
TypeScript Hook Pattern:
- Custom hooks return object with state and action functions
useCallbackwraps all action functionsuseEffectfor side effects (polling, initial fetch)- State updates use functional form:
setUpdates(prev => { ... })
Module Design
Go Exports:
- Single package
diunwebhookexports all types and handler functions - No barrel files; single source file
diunwebhook.gocontains everything - Test helpers exposed via
export_test.go(only visible to_testpackages)
TypeScript Exports:
- Named exports for all components, hooks, and utilities
- Default export only for the root
Appcomponent (export default function App()) - Type exports use
export interfaceorexport type @/components/ui/contains shadcn primitives (badge.tsx,button.tsx, etc.)
Git Commit Message Conventions
Format: Conventional Commits with bold markdown formatting
Pattern: **<type>(<scope>):** <description>
Types observed:
feat- new featuresfix- bug fixesdocs- documentation changeschore- maintenance tasks (deps, config)refactor- code restructuringstyle- UI/styling changestest- test additions
Scopes observed: docs, compose, webhook, ci, ui, main, errors, sql, api, deps, stats
Examples:
**feat(webhook):** add `WEBHOOK_SECRET` for token authentication support
**fix(ci):** improve version bump script for robustness and compatibility
**docs:** expand `index.md` with architecture, quick start, and tech stack
**chore(docs):** add `.gitignore` for `docs` and introduce `bun.lock` file
Multi-change commits: Use bullet list with each item prefixed by - **type(scope):**
Convention analysis: 2026-03-23