Add a machine-parseable 'embed_ui_in_binary' yes/no question to both the product specification (DesignSpecification.md) and the reusable framework template (DesignSpecificationTemplate.md). Default is 'yes' so the released binary ships the full product (API + UI) from a single artifact via //go:embed. Document the behavior contract for both answers (embedded-binary vs separate-deployment) and add a new UI Delivery Model section covering: static-export requirements for Next.js, SPA fallback for deep links while preserving /api/v1 and /healthz routes, cache/content-type expectations, build ordering (frontend before backend), and a clear build failure when the UI output directory is missing or empty. Extend the Binary Branding / Embedded Resources sections and MVP acceptance criteria in both docs to cross-reference the question so AI implementers can trace the answer through every affected area.
20 KiB
Generic Application Framework Specification
1. Purpose
This document defines the standard framework, architecture, operational patterns, security model, build conventions, and UI expectations that should be reused across future applications.
It is intentionally product-agnostic.
The goal is to provide a reusable implementation blueprint so new applications can be built consistently without re-deciding the same foundational concerns every time.
This framework should be treated as the default starting point for all future applications unless a project explicitly requires justified deviations.
2. Core Principles
-
One strong foundation, many apps
- Foundational concerns should be solved once and reused.
-
Centralization over duplication
- Shared logic for auth, logging, configuration, error handling, build/versioning, persistence patterns, API behavior, and UI patterns must be centralized.
-
Operational clarity first
- Logs, health, configuration, and runtime behavior must be easy to understand and operate.
-
Secure by default
- Secrets, sessions, tokens, credentials, and privileged actions must be designed with least privilege and strong defaults.
-
Build in the correct order
- Foundations must be implemented before domain features to avoid rework.
-
Cross-platform by default
- Applications should run on Windows, macOS, Linux, and Docker unless the product clearly requires otherwise.
-
API-first and UI-friendly
- Backend capabilities should be accessible through a clean API, and the UI should consume those capabilities without embedding domain logic into components.
-
Future-proofing without overengineering
- The architecture should support reasonable growth without requiring premature complexity.
2.1 Implementation Configuration Questions
This framework exposes a small set of configurable implementation choices that each concrete application must answer. The questions are written as structured blocks so an AI implementer (Claude Code, Augment, or similar) can read them, honor the answers, and apply the correct implementation sections.
For each application, copy the blocks below into the application's own specification and fill in the answer field. If no override is provided, the default is assumed.
Question: Embed the built web UI into the backend binary?
id: embed_ui_in_binary
question: Should the built web UI be embedded into the backend binary so a single binary ships the full product (API + UI)?
allowed_values: [yes, no]
default: yes
answer: yes
Behavior contract:
- When
answer: yes(framework default):- The frontend must be buildable as a fully static export and placed in a deterministic output directory (e.g.
frontend/out/). - The backend must embed that directory via
//go:embedand serve it from its own HTTP server. - The backend router must mount the embedded UI on all non-API routes as an SPA fallback so deep links resolve to
index.html, while/api/v1/*,/healthz, and other reserved routes continue to be served by their handlers. - The build pipeline must build the frontend before the backend and must fail clearly if the expected UI output directory is missing or empty.
- The single produced binary must be sufficient to run the full product without any separate web server, Node.js runtime, or static asset host.
- The frontend must be buildable as a fully static export and placed in a deterministic output directory (e.g.
- When
answer: no:- The backend must not embed any frontend assets and must not serve UI routes.
- The frontend is deployed as an independent artifact (container, static host, CDN, etc.).
- CORS must be configured explicitly for the chosen frontend origin(s); localhost must remain allowed for development.
Cross-references: see Section 3.2 (Frontend), Section 3.4 (UI Delivery Model), Section 5.2 (Embedded Resources), and Section 16 (MVP Acceptance Template).
3. Standard Technology Direction
3.1 Backend
Preferred backend language: Go
Reasons:
- Strong cross-platform support
- Excellent fit for long-running services and CLIs
- Simple deployment model with single binaries
- Strong standard library
- Good concurrency model
- Mature ecosystem for API servers, background processing, logging, and packaging
Recommended backend stack:
- HTTP router: Chi
- OpenAPI / Swagger: OpenAPI-first generation or swaggo
- Database access: sqlc + database/sql by default
- Migrations: golang-migrate
- Logging: slog with lumberjack for rotation
- Scheduling:
robfig/cronwhere recurring background jobs are needed - Password hashing: argon2id
- Encryption: AES-GCM with centralized key handling
- Config loading: environment variables first, optional config file support
3.2 Frontend
Preferred frontend direction:
- Next.js
- TypeScript
- Material UI
- Tailwind CSS
- TanStack Query
- react-hook-form
- Zod
Preferred UI template baseline:
Spike-NextJS-PRO-Templateshould be considered the default dashboard/admin UI foundation- It should be brought in via subtree and adapted, not copied ad hoc into each project
Static-export compatibility:
- Frontends built on this framework should remain compatible with Next.js static export (
output: "export") so the embedded-binary delivery model in Section 3.4 stays viable. - Avoid server-only Next.js features (Route Handlers,
getServerSideProps, server-onlynext/headersusage, per-request dynamic rendering) unless a specific application explicitly opts out of the embedded delivery model. - Runtime-dependent values (API base URL, feature flags) should be resolved at runtime from the current window origin or an application-provided config endpoint, not hard-coded at build time.
3.3 Data Layer
Preferred default database:
- SQLite for single-node applications and early-phase products
- WAL mode enabled by default
- Foreign key enforcement enabled
- Migration support required from day one
Future portability:
- Repositories and schema patterns should be designed so migration to PostgreSQL or another relational database is possible later if needed
3.4 UI Delivery Model
The UI delivery model is governed by the embed_ui_in_binary question in Section 2.1. The framework default is yes: the built UI ships inside the backend binary, so a single artifact hosts the full product.
Embedded-binary mode (default)
- The frontend must be buildable as a fully static export and must produce a deterministic output directory (e.g.
frontend/out/). - The backend must embed that directory via
//go:embedbehind a small assets package. - The HTTP server must:
- continue to serve API routes (e.g.
/api/v1/*) and operational routes (e.g./healthz) from their existing handlers - serve static assets from the embedded filesystem for all other routes
- implement SPA fallback: GET requests for non-API routes that do not match a static file must return
index.htmlwith HTTP 200 so client-side routing works for deep links - serve assets with appropriate
Content-Typeand long-lived cache headers for hashed/chunked assets
- continue to serve API routes (e.g.
- The build pipeline must build the frontend first, then the backend. If the expected UI output directory is missing or empty when building the backend, the build must fail with a clear, actionable error.
- The single produced binary must fully host the product. No separate Node.js runtime, web server, or static file host is required for normal operation.
- Development ergonomics are unaffected: running the frontend dev server against the backend API over CORS remains acceptable during development, as long as production builds use the embedded flow.
Separate-deployment mode (embed_ui_in_binary: no)
- The backend must not embed frontend assets and must not serve UI routes.
- The frontend is built and deployed as an independent artifact (container, static host, or CDN).
- CORS must be configured explicitly for the frontend origin(s); localhost must remain allowed for development.
- Version reporting must still ensure the UI and backend report the same version at runtime so operators can verify they are paired correctly.
4. Runtime Model
Applications should support the following modes where applicable:
- foreground run
- service install
- service uninstall
- service start
- service stop
- init (bootstrap + install + start)
- migration run
- backup
- restore
- health/doctor diagnostics
Runtime Requirements
- foreground mode and service mode should behave consistently
- graceful shutdown is required
- Docker deployment must be supported
- stdout logging should work well in containers
- rolling file logs should be supported for non-container deployments
5. Build, Versioning, and Artifact Standards
5.1 Versioning
All applications should use the version format:
yyyy.MM.dd.HHmm
Requirements:
- version must be generated centrally once per build
- the same version must be applied consistently across:
- binaries
- UI-visible version display
- API/system version endpoints
- release artifacts
- Windows metadata where applicable
5.2 Embedded Resources
If /resources/icons exists and contains the expected Windows icon asset:
- the Windows build should embed the icon into the Windows binary
- the build should fail clearly if required icon resources are invalid or missing for Windows builds
When embed_ui_in_binary: yes (see Section 2.1):
- the built web UI must also be embedded into the backend binary via
//go:embedand served by the backend as described in Section 3.4 - the build must fail clearly if the expected UI output directory is missing or empty, so a binary without a UI is never produced silently
- the build pipeline order must ensure the frontend is built before the backend
5.3 Binary Output Structure
Build automation should copy artifacts into:
/binaries
/windows
/amd64
/arm64
/macos
/amd64
/arm64
/linux
/amd64
/arm64
Requirements:
- compile for Windows, macOS, Linux
- compile for amd64 and arm64 where supported
- copy outputs into predictable paths automatically
- naming should be deterministic
6. Standard Project Structure
/resources
/icons
/binaries
/windows
/amd64
/arm64
/macos
/amd64
/arm64
/linux
/amd64
/arm64
/backend
/frontend
/docs
6.1 Backend Suggested Structure
/backend
/cmd
/src or /internal
/api
/auth
/config
/crypto
/db
/migrations
/repositories
/logging
/scheduler
/services
/system
/types
/validation
6.2 Frontend Suggested Structure
/frontend
/src
/app
/components
/features
/hooks
/lib
/schemas
/theme
/types
7. Authentication and Authorization Framework
7.1 Browser Authentication
Default recommendation:
- Use NextAuth/Auth.js for interactive browser authentication and session management only
Supported approaches:
- OIDC via NextAuth/Auth.js
- local username/password via NextAuth Credentials provider, with credential verification handled by the backend
7.2 Backend Authority
The backend must remain the source of truth for:
- authorization
- RBAC / permissions
- API keys
- business-security decisions
- credential validation logic
- audit policy
NextAuth/Auth.js must not become the backend security boundary.
7.3 API Keys
API keys must be a separate authentication mechanism from user/browser authentication.
Requirements:
- may expire or never expire
- separately created, revoked, enabled, and audited
- shown only once at creation
- never retrievable again in plaintext
- displayed in a modal/dialog with copy-to-clipboard support
- stored using a secure verification strategy, not plaintext
7.4 CSRF and Session Security
- browser mutation flows must be CSRF protected
- secure cookie handling must be used where cookies are involved
- token/session policy must be centralized
8. Logging and Error Handling Framework
8.1 Standard Logging Format
-
Standard logs:
[TimestampUTC] - [Component] - [Level] - Message -
Error logs only:
[TimestampUTC] - [Component] - [Level] - [File:Line:Column] - Message
8.2 Logging Style Requirements
- log messages must be plain and easy to understand
- messages should explain what is happening before, during, and after an operation when practical
- long-running tasks should emit progress-oriented messages at a reasonable cadence
- routine logs must not dump giant stack traces
- errors should be human-readable first
- component names must be consistent and centralized
8.3 Error Handling Requirements
- errors must be wrapped centrally
- error formatting must be centralized
- errors should capture source context automatically where possible
- file and line are required where practical for errors
- column should be included when available
- user-facing/API-facing errors must be understandable and safe
- low-level details should be reserved for debugging paths, not routine noise
9. Configuration Framework
9.1 Configuration Sources
Applications should support:
- environment variables
- secret files / mounted secrets
- optional configuration objects in the database if the product needs runtime-managed config
9.2 Config Export and Import
Applications that store runtime configuration in the database should support export/import.
Requirements:
- export format should be JSON initially
- exports should include schema/version metadata
- imports should support validation before apply
- imports should support dry-run preview
- secrets must never be exported in plaintext
- encrypted secrets may remain portable only when encryption keys match
- if keys do not match, imported secret-bearing records must be flagged for re-entry
10. Security and Secrets Framework
10.1 Key Material
Applications should support key/secret input via:
- environment variable
- mounted secret file
A 32-byte key minimum should be supported for encryption/signing where applicable.
10.2 Secrets Handling
- sensitive values must be encrypted at rest where needed
- secrets must never appear in plaintext in logs
- secrets must never be exposed back through normal APIs after creation
- sensitive fields must be redacted consistently
10.3 Password Handling
- use Argon2id for password hashing
- password verification and policy enforcement should be centralized
11. Database Standards
11.1 Global Data Rules
- UUIDv4 for all PK/FK by default
- UTC timestamps for all created/updated/deleted fields
- migrations required from day one
- WAL mode enabled for SQLite
- summary tables should be used where dashboards would otherwise rely on expensive queries
11.2 Backup and Restore
Applications using a local relational database should support:
- automatic backups
- manual backups
- restore with safety checks
- configurable retention count
- pre-restore safety backup
Default backup retention count:
3
12. API Standards
12.1 API Design Principles
- versioned API paths, e.g.
/api/v1 - OpenAPI/Swagger support
- consistent error envelope
- pagination/filtering/sorting where appropriate
- server-side validation required
- resource-oriented route design preferred
12.2 CORS and Proxy Rules
- localhost should be allowed by default for development
- production CORS origins must be configurable
- trusted proxy handling must be configurable
- forwarded headers should only be trusted from configured proxies
- auth/security decisions must correctly account for proxy-forwarded scheme/host/IP when trust is enabled
13. UI / UX Standards
13.1 Design Direction
The UI should feel:
- polished
- premium
- modern
- spacious
- clear without being sparse
- dashboard-quality without clutter
Use:
- layered cards
- soft shadows
- rounded corners
- balanced whitespace
- strong visual hierarchy
- centralized design tokens for spacing, radii, typography, shadows, and color roles
13.2 Frontend Architecture Rules
- do not embed business logic in components
- keep forms schema-driven where practical
- centralize reusable layouts and primitives
- derive shared types from OpenAPI or a shared schema pipeline when practical
- integrate adopted templates cleanly so the UI feels native to the product
14. Cross-Cutting Maintainability Rules
- No duplicated business logic across layers.
- Centralize auth decisions.
- Centralize logging helpers.
- Centralize error wrapping and formatting.
- Centralize timestamp generation in UTC.
- Centralize UUID generation policy.
- Centralize validation rules and enums.
- Keep route handlers thin.
- Keep frontend components presentation-focused.
- Keep repositories organized and avoid scattered raw queries.
- Make major architectural decisions once and document them.
- Prefer reusable framework modules over per-app reinvention.
15. Standard Implementation Order
This order should be followed unless the app has a strong reason not to.
Phase 1 — Foundation
- repository structure
- config loading
- centralized logging
- centralized error wrapping
- secret/key loading
- DB bootstrap
- migrations
- UUID/timestamp helpers
- health endpoint
- runtime/service abstraction
- CLI commands
- version generation
- build scripts
- binary output copying
- Windows icon embedding if applicable
Phase 2 — Security and Auth
- local auth model if needed
- NextAuth/Auth.js integration for browser login if UI exists
- OIDC integration if needed
- RBAC/authorization framework
- API key framework
- CSRF/session security
- audit core
Phase 3 — Core Domain and CRUD
- core tables/models
- repositories/services
- API endpoints
- frontend CRUD/admin flows
- summary tables where useful
Phase 4 — Background Work and Operational Features
- scheduling/background jobs if needed
- backup/restore
- export/import
- health/doctor tooling
- history/audit views
Phase 5 — UX Polish and Hardening
- dashboard composition
- guided workflows
- empty states
- performance cleanup
- documentation
16. MVP Acceptance Template
A generic application built on this framework is considered aligned when:
- It runs in foreground and Docker.
- Service lifecycle support exists where applicable.
- Versioning follows
yyyy.MM.dd.HHmm. - Build outputs land in
/binaries/<os>/<arch>. - Logging follows the standard format.
- Error logs include source context.
- Config/env/secret loading is centralized.
- DB migrations are in place from day one.
- UUIDv4 and UTC timestamps are consistently used.
- Local auth and/or OIDC are integrated correctly when required.
- API keys remain separate from interactive auth.
- CORS and trusted proxy handling are configured correctly.
- Backups and restore exist when local DB storage is used.
- Config export/import exists when runtime DB config is used.
- UI follows the shared design system direction.
- Code is modular and avoids obvious duplication.
- The UI delivery model matches the application's answer to the
embed_ui_in_binaryquestion (Section 2.1). For the framework default (yes), the released binary serves the full UI from its own HTTP server via//go:embed, with SPA fallback for deep links and no dependency on a separate web server, Node.js runtime, or static host.
17. Deviation Policy
If a future application deviates from this framework, the deviation should be explicit and documented.
Examples of acceptable reasons:
- the app is CLI-only and has no UI
- the app requires PostgreSQL from day one
- the app is Windows-only and uses native-only capabilities
- the app has no auth because it is a local-only utility
Deviations should be conscious, not accidental.
18. Final Positioning
This framework is the default blueprint for future applications.
It is intended to standardize:
- architecture
- security
- runtime behavior
- logging
- build outputs
- versioning
- data handling
- UI quality
- maintainability
So each new application can focus on domain value instead of repeatedly redesigning the same foundation.