Architecture decisions ¶
These decisions are owned by the implementation, as delegated in PLAN.md.
Runtime and packages ¶
Use Go 1.26.10 or newer in the 1.26 line initially, with PostgreSQL 18 as the only supported database. The module is github.com/fauzaanu/cicadel. Framework packages are small and public; CLI generation internals stay under internal/. Applications are ordinary Go modules with manage.go, project/settings, project/urls.go, and explicitly registered apps/ packages. SQLite, MySQL and MariaDB are excluded; there is no multi-provider roadmap.
ORM and migrations ¶
Use GORM v1.31.2 with its PostgreSQL driver. Applications receive *gorm.DB directly and attach request contexts with WithContext. GORM’s documented relationships, transactions and context support fit model-centered applications without requiring a new query abstraction. It uses an MIT license. Dependencies are pinned in go.mod/go.sum; upgrades require the integration suite and vulnerability checks.
Alternatives considered: Ent provides generated types and a schema/code-generation workflow (Apache-2.0); Bun offers a SQL-first interface (BSD-2-Clause). Both are credible choices. GORM is selected because plain model structs, associations, hooks, and direct queries most closely fit this project’s initial Django-familiar workflow. This is a design judgment, not a claim that GORM is universally faster or better. Dependency releases and licenses are inspectable through the pinned modules; popularity is not treated as a correctness guarantee.
Use the first-party recorded-history migration engine through management commands. It generates reviewable SQL from registered model state, validates version dependencies, and executes under a shared PostgreSQL advisory lock. SQL changes, compatible version records and checksums commit together. There is no automatic migration at startup. Supported concurrent-index operations use explicit recovery; separate migrations are not one atomic deployment.
Routing and application composition ¶
Use net/http.ServeMux with method/path patterns. urls.Route adds names and single-segment parameter reversal. urls.Include adds a path prefix and namespace. Duplicate names, overlapping patterns, and invalid parameter forms fail construction. Terminal slash routes match exactly. No regex converters or catch-all reversal in the initial API.
Apps register explicitly and declare dependencies; a stable topological sort rejects unknown dependencies and cycles. Middleware arguments run in the order supplied, outermost first. Host checks, body limits, response security headers, and panic recovery wrap application middleware. Settings are defaults → project assignments → environment overrides, validated before startup.
Component UI and development ¶
Use a component-first UI engine inspired by React and Django Cotton. Props, children, named slots and isolated composition are the public model. Django template syntax, inheritance and implicit context are not the foundation. The component UI specification defines the implemented initial scope and acceptance evidence.
The server engine uses templ v0.3.1100’s parser/IR and Go generator, with Cicadel contracts and AST instrumentation. Typed definitions, explicit slots, registry overrides, private request buffers and source-aware bounded render frames belong to Cicadel. The starter, articles and admin use compiled components. React/Node and hydration are excluded.
Use go tool cicadel dev for automatic component/CSS compilation and safe executable rebuild/restart. Failed builds preserve the working server; successful builds drain and reap the old process before replacement. Manual ui build, ui check and runserver remain supported. See the foundation contract. Keep production assets embedded or explicitly configured; never serve the repository root.
Sessions and authentication ¶
Use SCS with PostgreSQL-backed opaque sessions, hashed stored tokens, HttpOnly cookies, SameSite=Lax, secure cookies in production, absolute and idle expiry, token rotation at login, and destruction at logout. SCS owns session encoding and storage. Standard projects compose contrib/accounts through the public installable contract. Its browser bridge stores account tokens only in the server-side session and resolves the account on every request; its JSON API uses bearer headers. Applications own object permission policy. See authentication.
Use bcrypt with explicit byte-length validation; accept passwords of 12–72 bytes. Cookie-authenticated writes require a random synchronizer CSRF token stored in the session, submitted via form or header and compared in constant time. Login forms are protected too. Trust no forwarded host/protocol headers by default; terminate TLS at a configured reverse proxy and keep secure cookies enabled.
Performance and threat model ¶
Measure standard mux versus named-router dispatch, template rendering, database reads/writes, and full HTTP requests. Include allocations, throughput, latency percentiles, and error counts. Database data, connection limits, concurrency, and hardware must be recorded. No Django speedup claim is justified by language choice alone.
Primary threats: hostile Host headers; oversized inputs; SQL injection through raw query interpolation; HTML injection; open redirects; stolen/fixed sessions; cross-site writes; object-level authorization bypass; filesystem traversal; secret leakage through logs/errors; migration races and partial failures. Boundaries require targeted tests. This document is not an independent security audit.
Battery scope revision ¶
batteries.md supersedes any earlier implication that these integration decisions complete a Django-equivalent battery. PostgreSQL is the only supported and planned backend. SQLite, MySQL and MariaDB are excluded. Model-driven migration generation requires historical schema state, a version-level dependency graph and provider capabilities, not just GORM schema inspection or Goose SQL execution. Management commands use the first-party migration module for those contracts and its documented PostgreSQL operation subset.
Native i18n/l10n and GIS are excluded from first-party support. The experimental locale package has been removed. Third-party localization must be possible through public package/middleware/template contracts. Go modules handle distribution; the initial Cicadel lifecycle and compatibility contract is now implemented; component integration is verified; model integration and module extraction remain separately tracked.
Installable app foundation ¶
The first extension API uses explicit App descriptors with manifests, half-open dependency version ranges and a separately versioned app API. Go modules remain the dependency resolver. Registration happens in project/apps.go; imports never activate apps. Commands/checks/resources are namespaced, middleware is route-scoped, and lifecycle hooks acquire per-host state only after checks. PostgreSQL migration commands do not start runtime hooks. See the full contract and evidence.
Batteries should be developed against this public package boundary first. Promotion to first-party maintenance preserves app labels/migration identity and makes the capability a core default through the same public contracts.
First-party default styling ¶
Tailwind CSS v4 is the default component styling workflow, with a pinned standalone
compiler and checksum-verified explicit installation. Generated projects ship CSS
input/config, compiled CSS, a styled component, and an embedded asset route. The
compiler is development/CI tooling, never a production process. ui build/check
cover configured CSS and markup together. Applications may explicitly opt out
and retain another CSS system. See Tailwind and the tested
React-style authoring guide.
Browser starter and operations ¶
startproject composes the core accounts and formsets modules, PostgreSQL SCS store, compiled HTML screens and application-owned recovery delivery. The default project and account pages share a green-and-black Tailwind design. Email and logging define transport, configuration, redaction, cancellation and output-lifecycle contracts.