Remove legacy infrastructure, keep only shared rule contracts

Deleted: demo app, designsync/exports bundle system, bible meta-docs,
theme CSS, scaffolds, examples, empty pattern placeholders, go.mod,
CHANGELOG, VERSIONING

Kept: kit/patterns/*/contract.md (all engineering rules),
kit/ai/claude/CLAUDE.template.md, CLAUDE.md, AGENTS.md, README.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 16:55:11 +03:00
parent a37aec8790
commit 34d813d7ce
92 changed files with 12 additions and 18154 deletions
-10
View File
@@ -1,10 +0,0 @@
# {{ .project_name }} — Agent Instructions
Read and follow `bible/README.md` as the architecture source of truth.
## Rules
- Keep architecture documentation in English.
- Update Bible docs in the same change set as architecture/code contract changes.
- Keep README and agent docs minimal; avoid duplicating Bible architecture content.
-11
View File
@@ -1,11 +0,0 @@
# Architecture Documentation Policy
This project uses a Bible-style architecture documentation folder as the single source of truth.
## Mandatory Rules
- Record architecture decisions before or together with implementation.
- Use English for architecture documentation.
- Remove or update obsolete architectural guidance in the same change.
- Keep non-Bible docs concise and reference the Bible instead of duplicating it.
-20
View File
@@ -1,20 +0,0 @@
# Project Bible
The Bible is the single source of truth for this project's architecture.
## Documentation Rules
- All architecture decisions must be recorded in this Bible.
- The documentation language is English only.
- If a decision is superseded, update the Bible immediately and remove or mark obsolete content.
- Do not duplicate architecture documentation in `README.md`, `CLAUDE.md`, or other files.
## Structure
- `governance/documentation-policy.md` - mandatory rules for maintaining architecture docs.
- `architecture/system-overview.md` - current scope, boundaries, and high-level system composition.
- `architecture/api-surface.md` - HTTP API and UI route contracts.
- `architecture/runtime-flows.md` - critical runtime behavior and failure invariants.
- `architecture/ui-information-architecture.md` - required UI structure and semantics.
- `decisions/README.md` - how to capture new and updated architecture decisions.
@@ -1,10 +0,0 @@
# API Surface
Document all HTTP endpoints and UI routes that are part of the active contract.
## Rules
- Keep request/response shapes explicit.
- Record compatibility aliases and deprecations.
- Update this file when route behavior changes.
@@ -1,11 +0,0 @@
# Runtime Flows
Document the critical runtime flows and failure invariants.
Recommended sections:
- Startup flow
- Request handling flow
- Background tasks
- Failure / retry / cancellation behavior
@@ -1,32 +0,0 @@
# System Overview
## Product
Describe the product in one paragraph.
## Active Scope
- List current in-scope modules/features
- List user-visible surfaces
- List operational responsibilities
## Explicitly Removed / Out of Scope
- List legacy or excluded modules to avoid accidental restoration
## Runtime Composition
- HTTP server package(s)
- Domain/service orchestration
- Persistence layer(s)
- Migrations / background workers (if any)
## Local Execution
- `make run`
- `go run ./cmd/<binary>`
## Verification
- `go test ./...`
@@ -1,7 +0,0 @@
# UI Information Architecture
Document page structure, required section order, UI interaction contracts, and list/filter/
pagination behavior.
Use explicit route names and action contracts so AI agents can implement changes consistently.
@@ -1,18 +0,0 @@
# Architecture Decision Records
Use this directory to capture architecture decisions and significant updates.
## Required
- Every architecture decision must be recorded in the Bible.
- If a decision replaces an older one, update the older document in the same change.
- Keep entries short, explicit, and linked to the affected architecture files.
## Minimal Entry Template
- Date (`YYYY-MM-DD`)
- Decision
- Context
- Consequences
- Supersedes (if any)
@@ -1,21 +0,0 @@
# Documentation Policy
## Purpose
This policy defines how architectural knowledge is captured and maintained.
## Mandatory Rules
- Record every architecture decision in the Bible before or together with implementation.
- Use English for all architecture documentation.
- Keep only current architecture in active sections.
- When a solution is replaced, update or remove obsolete guidance in the same change.
- Keep architecture details centralized in `bible/`; other top-level docs should only reference it.
## Change Workflow
1. Update the relevant file(s) in `bible/architecture/`.
2. If behavior changed, add or update a decision note in `bible/decisions/`.
3. Remove duplicated or outdated statements from non-Bible docs.
4. Validate consistency against current code paths.
@@ -1,7 +0,0 @@
# Gin Admin App Integration Notes (Example)
Suggested use:
- use `ai-rules` templates only if they do not conflict with existing agent instructions
- reuse UI pattern bundles for admin tables and modal workflows
- keep domain-specific hard rules in project-local Bible docs
@@ -1,10 +0,0 @@
# Greenfield App Integration Notes (Example)
Suggested use:
- apply `ai-rules`
- apply `bible-core` (or merge selectively if a Bible already exists)
- apply `ui-theme-vapor` for active visual baseline (CSS + icon sprite)
- copy selected UI patterns into new modules/pages
Keep domain-specific business rules in the host project's own Bible.
@@ -1,9 +0,0 @@
# net/http Enterprise App Integration Notes (Example)
This example assumes the host repo already has a mature Bible structure and detailed UI contracts.
Use this kit primarily for:
- shared AI instruction wording
- pattern bundles that codify existing host UI contracts
- future cross-project standardization docs
-13
View File
@@ -1,13 +0,0 @@
# Operator Tools Pattern
Universal pattern for complex operator/admin dashboards in Go web applications.
This pattern standardizes:
- scope tabs and queue/status filters
- operations queue tables with row actions
- batch actions with explicit selection
- import/export shortcuts near operator workflows
- safety checklists and confirmation routing
See `contract.md` for behavior rules.
-43
View File
@@ -1,43 +0,0 @@
# Contract: Operator Tools Dashboard
## Shared Base
- This pattern inherits the shared `table-management` contract:
`kit/patterns/table-management/contract.md`.
- Reuse shared toolbar/table/icon geometry from the base contract first, then define only
operator-specific behavior.
## Purpose
Provide a canonical structure for high-density operator/admin screens without encoding
domain-specific terminology or business rules.
## Required UI Regions
- Scope tabs (or equivalent segmented navigation)
- Queue/status filters
- Batch action bar with explicit selection count
- Primary queue table/list with stable row actions
- Safety/guardrail region (checklist, warnings, runbook notes)
## Selection and Batch Actions
- Batch actions must require explicit selection; never infer hidden rows by default.
- The UI must display selection counts for the current view and, if applicable, outside the current view/filter.
- Destructive or high-impact actions must route through an explicit confirmation step (modal or dedicated confirm state).
## Status and Queue Semantics
- Queue/status labels must be consistent across filters, row badges, and summaries.
- Failed items must remain easy to filter and retry without losing current scope context.
- Running/queued states should be visually distinct from done/failed states.
## Import / Export Placement
- Import preview and export actions should be discoverable near operator workflows.
- Export scope must remain explicit (`selected`, `filtered`, `all`) when ambiguity exists.
## Reuse Boundary
- Keep the pattern generic: host projects provide their own tool names, domain fields, and backend execution logic.
- This contract standardizes interaction semantics and layout zones, not business workflows.
-4
View File
@@ -1,4 +0,0 @@
# Status Indicators Pattern (Planned)
Reserved for health badges, sync status indicators, and severity labels.
-7
View File
@@ -1,7 +0,0 @@
# Table + Pagination Pattern
This pattern package captures a shared contract for table-based UI pages with server-side
filters and pagination.
It is derived from mature server-rendered admin UIs and list-page conventions across multiple
Go web codebases.
@@ -1,3 +0,0 @@
// Placeholder template for pagination helpers.
// Adapt from existing host codebase conventions (net/http or Gin).
-27
View File
@@ -1,27 +0,0 @@
# Contract: Table + Server-Side Filters + Pagination
## Required Behavior
- Filters apply to the full query scope before pagination (not page-local filtering).
- Pagination state is controlled by URL query parameters.
- Changing a filter resets the page parameter to page `1`.
- UI shows a summary (`Showing XY of N`) and an explicit active page state in pagination controls.
- Canonical demo visual style uses a centered dot pager while preserving page semantics via URL parameters and accessible labels.
- Demo/base contract includes a `rows per page` control.
- Status badge columns should be centered when the column semantics are status-only values.
- Small modules (no internal scroll, no more than 2 actions) should place actions in the module header row.
- Shared table/filter controls should inherit the repository baseline component theme
(currently Vapor Soft / Vapor Night in the canonical demo/scaffold) rather than redefining
per-pattern primitives.
## Recommended Query Parameters
- `page` for single-list pages
- `per_page` when the page-size control is user-visible
- section-specific params (for example `active_page`, `chronology_page`) for multi-list pages
## Interaction Guardrails
- Same-page filter/pagination interactions should preserve user reading position (for example via module anchors such as `#table-filters` / `#table-list`).
- Table status badges should remain readable under the shared theme baseline (including tinted badge variants when a host project opts into a legacy or alternate visual preset).
- Dot pager interactions should remain keyboard accessible and expose page meaning via labels/`aria-current`, even if numbers are visually hidden.
@@ -1,2 +0,0 @@
/* Placeholder styles for table pagination pattern. */
@@ -1,2 +0,0 @@
<!-- Placeholder table + pager partial. -->
-18
View File
@@ -1,18 +0,0 @@
# Aqua Theme Module (Legacy Archive Layer)
Status: legacy archive/reference layer (not the active demo/scaffold baseline).
This directory preserves the Aqua visual language archive for the design code:
- global visual tokens and component surfaces
- reusable control geometry (buttons, segmented controls, table chrome)
- icon rendering baseline (stroke style + sprite integration)
Active pattern contracts should target the current baseline and may reference this module only
for migration/comparison purposes.
Contents:
- `demo-aqua-freeze.css` — frozen Aqua stylesheet snapshot
- `templates/icon_sprite.html` — canonical icon sprite for reusable action semantics
- `notes.md` — scope and usage policy for this theme module
File diff suppressed because it is too large Load Diff
-23
View File
@@ -1,23 +0,0 @@
# Aqua Theme Notes
This module is a reusable Aqua style archive for design-code consumers.
## What it captures
- Aqua-style control surfaces and button hierarchy
- segmented controls and grouped tab geometry
- table/filter/toolbars visual primitives
- icon rendering baseline and shared icon sprite usage
- modal and status component style language
## How to use
- Treat this module as a legacy reference snapshot, not the active baseline.
- Pattern contracts should inherit the active baseline first and use this module only when a host
project explicitly opts into Aqua-like styling.
- Do not move new baseline decisions here.
## Boundary
- This module standardizes visual language only.
- Domain behavior, labels, and business workflow semantics belong to pattern contracts.
@@ -1,103 +0,0 @@
<!-- Canonical Aqua icon sprite for shared UI actions -->
<svg class="icon-sprite" aria-hidden="true" focusable="false" width="0" height="0">
<symbol id="ico-select-visible" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="11" height="11" rx="2"></rect>
<path d="M5 8.2l2 2.1 4-4.3"></path>
</symbol>
<symbol id="ico-select-filtered" viewBox="0 0 16 16">
<path d="M2.5 3h11l-4.2 4.6v3.1l-2.6 1.5V7.6L2.5 3z"></path>
<path d="M11.4 10.2h3M12.9 8.7v3"></path>
</symbol>
<symbol id="ico-clear-visible" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="11" height="11" rx="2"></rect>
<path d="M5 8h6"></path>
</symbol>
<symbol id="ico-clear-filtered" viewBox="0 0 16 16">
<path d="M2.5 3h11L9.3 7.6v3.1l-2.6 1.5V7.6L2.5 3z"></path>
<path d="M10.5 10.2l3 3M13.5 10.2l-3 3"></path>
</symbol>
<symbol id="ico-clear-selection" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="11" height="11" rx="2"></rect>
<path d="M5 5l6 6M11 5l-6 6"></path>
</symbol>
<symbol id="ico-run" viewBox="0 0 16 16">
<path d="M5 3.5l7 4.5-7 4.5z"></path>
</symbol>
<symbol id="ico-edit" viewBox="0 0 16 16">
<path d="M3 13l1.2-3.6L10 3.6l2.4 2.4-5.8 5.8L3 13z"></path>
<path d="M8.8 4.8l2.4 2.4"></path>
</symbol>
<symbol id="ico-remove" viewBox="0 0 16 16">
<path d="M4.2 4.2l7.6 7.6M11.8 4.2l-7.6 7.6"></path>
</symbol>
<symbol id="ico-cancel" viewBox="0 0 16 16">
<circle cx="8" cy="8" r="5.5"></circle>
<path d="M5.5 5.5l5 5M10.5 5.5l-5 5"></path>
</symbol>
<symbol id="ico-archive" viewBox="0 0 16 16">
<rect x="2.5" y="3" width="11" height="2.8" rx="1"></rect>
<path d="M3.5 5.8V13h9V5.8"></path>
<path d="M6.2 8h3.6"></path>
</symbol>
<symbol id="ico-import" viewBox="0 0 16 16">
<path d="M3 4.2v8.6h10V4.2"></path>
<path d="M8 1.8v6.2"></path>
<path d="M5.8 5.8L8 8l2.2-2.2"></path>
<path d="M5 10.2h6"></path>
</symbol>
<symbol id="ico-export" viewBox="0 0 16 16">
<path d="M3 4.2v8.6h10V4.2"></path>
<path d="M8 8V1.8"></path>
<path d="M5.8 4L8 1.8 10.2 4"></path>
<path d="M5 10.2h6"></path>
</symbol>
<symbol id="ico-export-filtered" viewBox="0 0 16 16">
<path d="M2 4.2v8.6h10.8"></path>
<path d="M7 8V1.8"></path>
<path d="M4.8 4L7 1.8 9.2 4"></path>
<path d="M10 5.1h5.2L13.1 7.5v3.1l-1.3.7V7.5z"></path>
</symbol>
<symbol id="ico-export-selected" viewBox="0 0 16 16">
<path d="M2 4.2v8.6h10.8"></path>
<path d="M7 8V1.8"></path>
<path d="M4.8 4L7 1.8 9.2 4"></path>
<rect x="10.1" y="5.2" width="5" height="5" rx="0.6"></rect>
<path d="M11.2 6.3l2.8 2.8M14 6.3l-2.8 2.8"></path>
</symbol>
<symbol id="ico-retry" viewBox="0 0 16 16">
<path d="M12.2 6A4.8 4.8 0 0 0 4.8 4.4"></path>
<path d="M5.6 2.9L4.1 4.6 5.9 5.8"></path>
<path d="M3.8 10A4.8 4.8 0 0 0 11.2 11.6"></path>
<path d="M10.4 13.1L11.9 11.4 10.1 10.2"></path>
</symbol>
<symbol id="ico-review" viewBox="0 0 16 16">
<circle cx="8" cy="8" r="5.5"></circle>
<path d="M8 7.2v3.6"></path>
<path d="M8 5.1h.01"></path>
</symbol>
<symbol id="ico-mark-review" viewBox="0 0 16 16">
<path d="M8 2.6l5.2 2v3.7c0 2.3-1.5 4.4-5.2 5.7-3.7-1.3-5.2-3.4-5.2-5.7V4.6l5.2-2z"></path>
<path d="M8 6.1v3.2"></path>
<path d="M8 11.1h.01"></path>
</symbol>
<symbol id="ico-confirm" viewBox="0 0 16 16">
<path d="M8 2.5l5 2v3.8c0 2.2-1.3 4.1-5 5.3-3.7-1.2-5-3.1-5-5.3V4.5l5-2z"></path>
<path d="M5.7 8.3l1.6 1.7 3-3.1"></path>
</symbol>
<symbol id="ico-inspect" viewBox="0 0 16 16">
<circle cx="7" cy="7" r="3.8"></circle>
<path d="M9.8 9.8l3.2 3.2"></path>
</symbol>
<symbol id="ico-scope" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="4.2" height="4.2"></rect>
<rect x="9.3" y="2.5" width="4.2" height="4.2"></rect>
<rect x="2.5" y="9.3" width="4.2" height="4.2"></rect>
<rect x="9.3" y="9.3" width="4.2" height="4.2"></rect>
</symbol>
<symbol id="ico-queue" viewBox="0 0 16 16">
<path d="M5.4 4h8.1M5.4 8h8.1M5.4 12h8.1"></path>
<circle cx="3.2" cy="4" r="0.7"></circle>
<circle cx="3.2" cy="8" r="0.7"></circle>
<circle cx="3.2" cy="12" r="0.7"></circle>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

-17
View File
@@ -1,17 +0,0 @@
# Vapor Theme Module (Active Design Layer)
Status: active visual baseline for reusable UI primitives.
This module defines the shared Vapor visual language used by the demo and intended host-project
integration:
- baseline tokens and surface treatment
- reusable component geometry (buttons, segmented controls, table chrome)
- shared icon sprite for table-management and operator workflows
Contents:
- `static/vapor.css` - active stylesheet baseline
- `templates/icon_sprite.html` - active icon sprite
- `notes.md` - usage boundaries and integration rules
- `palette-catalog.md` - preset list for app-shell header and accent colors
-28
View File
@@ -1,28 +0,0 @@
# Vapor Theme Notes
This module is the active reusable theme source for design-code consumers.
## What it captures
- Vapor control surfaces and button hierarchy
- segmented controls and grouped tab geometry
- table/filter/toolbar primitives
- icon rendering baseline and shared sprite usage
- modal and status component style language
- app-shell color/height presets for host-level branding fit within Vapor aesthetics
## How to use
- Use this module as the visual baseline for host projects that adopt the canonical demo style.
- Pattern contracts should reference shared behavior contracts and rely on this module for visual primitives.
- When baseline visuals change, update this module first to keep downstream integration deterministic.
- For shell color selection, use `palette-catalog.md` and set `data-vapor-shell` on `<html>`.
- For runtime switching, the recommended query key is `vapor_shell` (same IDs as the catalog).
- Keep host-specific brand overrides outside this module unless they are reusable presets.
## Boundary
- This module standardizes visual language only.
- Domain behavior, labels, and business workflow semantics belong to pattern contracts.
- Preset palette IDs are part of the reusable contract; host projects may choose one, but should not
rename/remove preset IDs in downstream copies without migration notes.
@@ -1,50 +0,0 @@
# Vapor Shell Palette Catalog
This catalog defines reusable `app-shell` presets for host projects that consume `theme-vapor`.
Apply a preset on the root element:
```html
<html data-vapor-shell="miami-sunset">
```
Optional: host project can override shell height without changing preset IDs:
```css
:root { --shell-height: 72px; }
```
## Selection Approach
Recommended precedence for host integration:
1. `?vapor_shell=<preset-id>` query parameter (preview/share links)
2. `localStorage["vapor_shell"]` (remembered user choice)
3. `<html data-vapor-shell="...">` static default from server/templates
4. fallback preset: `miami-sunset`
The scaffold and demo JavaScript implement this precedence.
## Presets (Header + Accent)
| Preset ID | Header core | Accent core | Default shell height |
|---|---|---|---|
| `miami-sunset` | `#fbe5f8` | `#ff7ec7` | `66px` |
| `neon-grid` | `#f5eeff` | `#ff4fd8` | `64px` |
| `laser-flamingo` | `#ffe8f4` | `#ff6fae` | `70px` |
| `synth-lagoon` | `#e8f6ff` | `#67d7ff` | `62px` |
| `mall-soft` | `#fff1f8` | `#ffb5d7` | `68px` |
| `hologram-sky` | `#edf9ff` | `#5ce4ff` | `64px` |
| `peach-drive` | `#fff0e6` | `#ff9a6a` | `72px` |
| `ultraviolet-plaza` | `#f0e8ff` | `#b26dff` | `66px` |
| `cyber-mint` | `#ebfff7` | `#57f0c1` | `62px` |
## Token Surface
Each preset resolves these tokens in `static/vapor.css`:
- `--shell-height`
- `--shell-bg-light`, `--shell-bg-dark`
- `--shell-border-light`, `--shell-border-dark`
- `--shell-accent-light`, `--shell-accent-dark`
- `--shell-accent-line-light`, `--shell-accent-line-dark`
File diff suppressed because it is too large Load Diff
@@ -1,102 +0,0 @@
<svg class="icon-sprite" aria-hidden="true" focusable="false" width="0" height="0">
<symbol id="ico-select-visible" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="11" height="11" rx="2"></rect>
<path d="M5 8.2l2 2.1 4-4.3"></path>
</symbol>
<symbol id="ico-select-filtered" viewBox="0 0 16 16">
<path d="M2.5 3h11l-4.2 4.6v3.1l-2.6 1.5V7.6L2.5 3z"></path>
<path d="M11.4 10.2h3M12.9 8.7v3"></path>
</symbol>
<symbol id="ico-clear-visible" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="11" height="11" rx="2"></rect>
<path d="M5 8h6"></path>
</symbol>
<symbol id="ico-clear-filtered" viewBox="0 0 16 16">
<path d="M2.5 3h11L9.3 7.6v3.1l-2.6 1.5V7.6L2.5 3z"></path>
<path d="M10.5 10.2l3 3M13.5 10.2l-3 3"></path>
</symbol>
<symbol id="ico-clear-selection" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="11" height="11" rx="2"></rect>
<path d="M5 5l6 6M11 5l-6 6"></path>
</symbol>
<symbol id="ico-run" viewBox="0 0 16 16">
<path d="M5 3.5l7 4.5-7 4.5z"></path>
</symbol>
<symbol id="ico-edit" viewBox="0 0 16 16">
<path d="M3 13l1.2-3.6L10 3.6l2.4 2.4-5.8 5.8L3 13z"></path>
<path d="M8.8 4.8l2.4 2.4"></path>
</symbol>
<symbol id="ico-remove" viewBox="0 0 16 16">
<path d="M4.2 4.2l7.6 7.6M11.8 4.2l-7.6 7.6"></path>
</symbol>
<symbol id="ico-cancel" viewBox="0 0 16 16">
<circle cx="8" cy="8" r="5.5"></circle>
<path d="M5.5 5.5l5 5M10.5 5.5l-5 5"></path>
</symbol>
<symbol id="ico-archive" viewBox="0 0 16 16">
<rect x="2.5" y="3" width="11" height="2.8" rx="1"></rect>
<path d="M3.5 5.8V13h9V5.8"></path>
<path d="M6.2 8h3.6"></path>
</symbol>
<symbol id="ico-import" viewBox="0 0 16 16">
<path d="M3 4.2v8.6h10V4.2"></path>
<path d="M8 1.8v6.2"></path>
<path d="M5.8 5.8L8 8l2.2-2.2"></path>
<path d="M5 10.2h6"></path>
</symbol>
<symbol id="ico-export" viewBox="0 0 16 16">
<path d="M3 4.2v8.6h10V4.2"></path>
<path d="M8 8V1.8"></path>
<path d="M5.8 4L8 1.8 10.2 4"></path>
<path d="M5 10.2h6"></path>
</symbol>
<symbol id="ico-export-filtered" viewBox="0 0 16 16">
<path d="M2 4.2v8.6h10.8"></path>
<path d="M7 8V1.8"></path>
<path d="M4.8 4L7 1.8 9.2 4"></path>
<path d="M10 5.1h5.2L13.1 7.5v3.1l-1.3.7V7.5z"></path>
</symbol>
<symbol id="ico-export-selected" viewBox="0 0 16 16">
<path d="M2 4.2v8.6h10.8"></path>
<path d="M7 8V1.8"></path>
<path d="M4.8 4L7 1.8 9.2 4"></path>
<rect x="10.1" y="5.2" width="5" height="5" rx="0.6"></rect>
<path d="M11.2 6.3l2.8 2.8M14 6.3l-2.8 2.8"></path>
</symbol>
<symbol id="ico-retry" viewBox="0 0 16 16">
<path d="M12.2 6A4.8 4.8 0 0 0 4.8 4.4"></path>
<path d="M5.6 2.9L4.1 4.6 5.9 5.8"></path>
<path d="M3.8 10A4.8 4.8 0 0 0 11.2 11.6"></path>
<path d="M10.4 13.1L11.9 11.4 10.1 10.2"></path>
</symbol>
<symbol id="ico-review" viewBox="0 0 16 16">
<circle cx="8" cy="8" r="5.5"></circle>
<path d="M8 7.2v3.6"></path>
<path d="M8 5.1h.01"></path>
</symbol>
<symbol id="ico-mark-review" viewBox="0 0 16 16">
<path d="M8 2.6l5.2 2v3.7c0 2.3-1.5 4.4-5.2 5.7-3.7-1.3-5.2-3.4-5.2-5.7V4.6l5.2-2z"></path>
<path d="M8 6.1v3.2"></path>
<path d="M8 11.1h.01"></path>
</symbol>
<symbol id="ico-confirm" viewBox="0 0 16 16">
<path d="M8 2.5l5 2v3.8c0 2.2-1.3 4.1-5 5.3-3.7-1.2-5-3.1-5-5.3V4.5l5-2z"></path>
<path d="M5.7 8.3l1.6 1.7 3-3.1"></path>
</symbol>
<symbol id="ico-inspect" viewBox="0 0 16 16">
<circle cx="7" cy="7" r="3.8"></circle>
<path d="M9.8 9.8l3.2 3.2"></path>
</symbol>
<symbol id="ico-scope" viewBox="0 0 16 16">
<rect x="2.5" y="2.5" width="4.2" height="4.2"></rect>
<rect x="9.3" y="2.5" width="4.2" height="4.2"></rect>
<rect x="2.5" y="9.3" width="4.2" height="4.2"></rect>
<rect x="9.3" y="9.3" width="4.2" height="4.2"></rect>
</symbol>
<symbol id="ico-queue" viewBox="0 0 16 16">
<path d="M5.4 4h8.1M5.4 8h8.1M5.4 12h8.1"></path>
<circle cx="3.2" cy="4" r="0.7"></circle>
<circle cx="3.2" cy="8" r="0.7"></circle>
<circle cx="3.2" cy="12" r="0.7"></circle>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

-12
View File
@@ -1,12 +0,0 @@
# Timeline Cards Pattern
Canonical timeline UX for operational history views:
- cards grouped by day
- summary chips for aggregated actions
- source labels (`ingest`, `manual`, `system`, etc.)
- single drilldown modal (no nested modals)
- in-card search/filtering for event lists
This pattern is intended for history/audit/timeline surfaces in server-rendered Go web UIs.
-29
View File
@@ -1,29 +0,0 @@
# Contract: Timeline Cards + Drilldown
## Card Grouping
- Render timeline as grouped cards (typically by day), not raw event rows.
- Correlated or visually equivalent events may be collapsed into one card with counts.
- Card summaries should be human-readable and avoid repeating page-scope identity labels.
## Filters
- Timeline filters are server-side when timeline is paginated or large.
- Filters should preserve grouping semantics and timezone behavior.
- Scope-invariant filters may be hidden on entity detail pages.
## Drilldown
- One card opens one drilldown modal/panel.
- Drilldown contains:
- event list (left/top)
- selected event details (right/bottom)
- No nested modal inside drilldown.
- Card-local search/filter may be applied within the drilldown.
## UX Rules
- Use human-readable source labels.
- Prefer action-oriented card titles (`Installed N components`, `Removed N components`).
- Empty states must explain whether filters removed all results.
-12
View File
@@ -1,12 +0,0 @@
run:
go run ./cmd/demo-server
build:
go build ./cmd/demo-server
test:
go test ./...
fmt:
gofmt -w $$(find . -name '*.go' -type f)
-15
View File
@@ -1,15 +0,0 @@
# Go net/http Web Skeleton
Minimal starter skeleton for a Go web app using:
- `net/http`
- `html/template`
- embedded templates and static assets
This scaffold is intended as a starting point that host repositories can adapt.
Vapor shell preset integration is included:
- default preset via `<html data-vapor-shell="miami-sunset">`
- runtime override via `?vapor_shell=<preset-id>`
- persisted selection via `localStorage["vapor_shell"]`
@@ -1,23 +0,0 @@
package web
import (
"net/http"
)
type IndexViewData struct {
Title string
}
func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
_ = s.render(w, "base.html", IndexViewData{Title: "Home"})
}
func (s *Server) handleHealthz(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok"))
}
@@ -1,37 +0,0 @@
package web
import (
"html/template"
"io/fs"
"net/http"
appweb "{{ .module_path }}/web"
)
type Server struct {
mux *http.ServeMux
tmpl *template.Template
}
func NewServer() (*Server, error) {
tmpl, err := parseTemplates()
if err != nil {
return nil, err
}
s := &Server{
mux: http.NewServeMux(),
tmpl: tmpl,
}
s.registerRoutes()
return s, nil
}
func (s *Server) Handler() http.Handler { return s.mux }
func (s *Server) registerRoutes() {
s.mux.HandleFunc("/", s.handleIndex)
s.mux.HandleFunc("/healthz", s.handleHealthz)
staticFS, _ := fs.Sub(appweb.Assets, "static")
s.mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS))))
}
@@ -1,27 +0,0 @@
package web
import (
"fmt"
"html/template"
"net/http"
appweb "{{ .module_path }}/web"
)
func parseTemplates() (*template.Template, error) {
t, err := template.ParseFS(appweb.Assets, "templates/*.html")
if err != nil {
return nil, fmt.Errorf("parse templates: %w", err)
}
return t, nil
}
func (s *Server) render(w http.ResponseWriter, name string, data any) error {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := s.tmpl.ExecuteTemplate(w, name, data); err != nil {
http.Error(w, "template error", http.StatusInternalServerError)
return fmt.Errorf("render %s: %w", name, err)
}
return nil
}
@@ -1,9 +0,0 @@
package web
import "embed"
// Assets contains templates and static files.
//
//go:embed templates/* static/*
var Assets embed.FS
@@ -1,46 +0,0 @@
:root {
--bg: #e6e8ee;
--ink: #1f2023;
--muted: #5d646f;
--card: linear-gradient(180deg, rgba(252,252,253,0.99), rgba(240, 244, 249, 0.97) 44%, rgba(228, 238, 248, 0.96) 78%, rgba(221, 234, 248, 0.96));
--line: #b9cbe0;
--accent: linear-gradient(180deg, #85b8ef 0%, #93c6fb 26%, #abd8ff 55%, #c7e8ff 82%, #def2ff 100%);
--accent-line: #88a4d4;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "Lucida Grande", "Helvetica Neue", Helvetica, Arial, sans-serif;
background:
radial-gradient(760px 360px at 14% 6%, rgba(255,255,255,0.82), transparent 72%),
radial-gradient(760px 360px at 88% 8%, rgba(154, 203, 247, 0.16), transparent 74%),
repeating-linear-gradient(to bottom, rgba(255,255,255,0.05) 0 1px, rgba(170,182,198,0.03) 1px 3px),
linear-gradient(#eef1f6, #dde2ea);
color: var(--ink);
}
.shell {
max-width: 880px;
margin: 0 auto;
padding: 24px 16px 48px;
}
.hero { margin-bottom: 16px; }
.eyebrow {
margin: 0;
color: #5f6772;
text-transform: uppercase;
letter-spacing: 0.08em;
font-size: 12px;
}
h1 { margin: 6px 0 0; font-size: 32px; }
.card {
background:
linear-gradient(180deg, rgba(255,255,255,0.70), rgba(255,255,255,0.18) 28%, rgba(255,255,255,0.0) 29%),
repeating-linear-gradient(to bottom, rgba(255,255,255,0.26) 0 1px, rgba(188,205,223,0.10) 1px 3px),
var(--card);
border: 1px solid var(--line);
border-radius: 14px;
padding: 16px;
box-shadow: 0 10px 20px rgba(78, 107, 139, 0.09), inset 0 1px 0 rgba(255,255,255,0.96);
}
code { background: #eef3fb; padding: 1px 5px; border-radius: 6px; }
@@ -1,65 +0,0 @@
(() => {
const root = document.documentElement;
const storageKey = "vapor_shell";
const queryKey = "vapor_shell";
const fallbackPreset = "miami-sunset";
const allowed = new Set([
"miami-sunset",
"neon-grid",
"laser-flamingo",
"synth-lagoon",
"mall-soft",
"hologram-sky",
"peach-drive",
"ultraviolet-plaza",
"cyber-mint",
]);
const normalizePreset = (value) => {
const trimmed = (value || "").trim().toLowerCase();
if (!trimmed || !allowed.has(trimmed)) {
return "";
}
return trimmed;
};
const setPreset = (value) => {
const preset = normalizePreset(value);
if (!preset) {
return false;
}
root.setAttribute("data-vapor-shell", preset);
return true;
};
root.classList.add("js");
const url = new URL(window.location.href);
const fromQuery = normalizePreset(url.searchParams.get(queryKey));
if (fromQuery) {
setPreset(fromQuery);
try {
window.localStorage.setItem(storageKey, fromQuery);
} catch (_err) {
// Keep behavior deterministic even when storage is blocked.
}
return;
}
const fromMarkup = normalizePreset(root.getAttribute("data-vapor-shell"));
if (fromMarkup) {
return;
}
try {
const fromStorage = normalizePreset(window.localStorage.getItem(storageKey));
if (fromStorage) {
setPreset(fromStorage);
return;
}
} catch (_err) {
// Fallback handled below.
}
setPreset(fallbackPreset);
})();
@@ -1,21 +0,0 @@
{{ define "base.html" }}
<!doctype html>
<html lang="en" data-vapor-shell="miami-sunset">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ .Title }}</title>
<link rel="stylesheet" href="/static/css/app.css">
</head>
<body>
<main class="shell">
<header class="hero">
<p class="eyebrow">Go Web Scaffold</p>
<h1>{{ .Title }}</h1>
</header>
{{ template "content" . }}
</main>
<script src="/static/js/app.js" defer></script>
</body>
</html>
{{ end }}
@@ -1,11 +0,0 @@
{{ define "content" }}
<section class="card">
<p>Minimal net/http + html/template scaffold.</p>
<ul>
<li><code>GET /</code> page</li>
<li><code>GET /healthz</code> healthcheck</li>
<li><code>/static/*</code> embedded assets</li>
</ul>
</section>
{{ end }}