tech
Use when writing or reviewing Go code in fusionaly-oss — adding routes, handlers, domain contexts, background jobs, the manager CLI, wiring the app, or writing tests. Covers the cartridge framework, matcha for the manager, Phoenix Contexts, lifecycle/shutdown, and the test conventions.
Best use case
tech is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when writing or reviewing Go code in fusionaly-oss — adding routes, handlers, domain contexts, background jobs, the manager CLI, wiring the app, or writing tests. Covers the cartridge framework, matcha for the manager, Phoenix Contexts, lifecycle/shutdown, and the test conventions.
Teams using tech should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/tech/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How tech Compares
| Feature / Agent | tech | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when writing or reviewing Go code in fusionaly-oss — adding routes, handlers, domain contexts, background jobs, the manager CLI, wiring the app, or writing tests. Covers the cartridge framework, matcha for the manager, Phoenix Contexts, lifecycle/shutdown, and the test conventions.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Fusionaly Tech & Conventions
## Overview
Fusionaly is a Go monolith (Fiber + GORM + SQLite, React/Inertia frontend). The guiding principle: **the libraries do the heavy lifting; app code stays thin and domain-focused.** Boilerplate — HTTP server, routing, sessions, CSRF, rate limiting, static serving, Inertia, SQLite WAL/serialized writes, graceful shutdown, deploys — lives in `cartridge` (the app) and `matcha` (the manager). The app *reuses* them; it does not re-implement them.
This is a deliberate, pragmatic stance: Go favors explicit, no-magic code, but here we push recurring infrastructure into a shared library so each app is a small amount of clean domain code on top. Don't hand-roll what the library already provides.
## The stack at a glance
| Concern | Owner | Where |
|---|---|---|
| HTTP server, lifecycle, graceful shutdown, routing, sessions, CSRF, rate limiting, static/Inertia | **cartridge** | `cartridge.NewApplication(...)` |
| SQLite connection, WAL, serialized writes, migrations plumbing | **cartridge/sqlite** + `internal/database` | `dbManager`, `sqlite.PerformWrite` |
| Background jobs lifecycle (start/stop with the server) | **cartridge** `BackgroundWorker` | `internal/jobs` |
| Install / update / deploy / backup / image swap (self-hosted ops) | **matcha** | `cmd/manager` |
| Domain logic (analytics, events, websites, feed, ai, …) | **app** (Phoenix Contexts) | `internal/<domain>/` |
| Frontend | React 19 + Inertia | `web/src` |
## cartridge: configure, don't reinvent
cartridge is our own framework — repo **https://github.com/karloscodes/cartridge** (Go module `github.com/karloscodes/cartridge`). When something feels like boilerplate, check there before writing it.
The whole app boots by handing cartridge a config struct. `internal/app.go` is the one place that wires it, and it's ~120 lines:
```go
app, err := cartridge.NewApplication(cartridge.ApplicationOptions{
Config: cfg,
Logger: logger, // cartridge.NewLogger(cfg, nil)
DBManager: dbManager, // wraps cartridge/sqlite
ServerConfig: serverConfig, // CORS, SecFetchSite, ProxyHeader, StaticFS
RouteMountFunc: MountAppRoutes, // your routes
BackgroundWorkers: []cartridge.BackgroundWorker{jobsManager},
})
// Application embeds *cartridge.Application and adds DBManager.
```
cartridge then owns the server, signal handling, and graceful shutdown — including stopping the registered `BackgroundWorker`s. The app never writes a `main()` event loop or shutdown handler.
Key sub-packages you reuse (don't reinvent): `cartridge/inertia` (`inertia.RenderPage`), `cartridge/cache` (`cache.Cache[K,V]`), `cartridge/sqlite` (`sqlite.PerformWrite` for serialized writes), `cartridge/testsupport` (test DBs), flash, session.
## Phoenix Contexts: thin handlers, fat contexts
Each domain is a package under `internal/<domain>/` exposing **top-level functions that take `*gorm.DB`** — no service objects, no HTTP imports.
```go
// internal/settings/setting.go — a context: plain functions + a model
type Setting struct { ID uint; Key string; Value string /* ... */ }
func GetOpenAIKey(db *gorm.DB) (string, error) { return GetSetting(db, KeyOpenAIKey) }
func SaveOpenAIKey(db *gorm.DB, key string) error { /* ... */ }
```
```go
// internal/http/*_handler.go — handlers stay thin: parse, delegate, render
func DashboardAction(ctx *cartridge.Context) error {
metrics := analytics.GetDashboardMetrics(ctx.DB(), websiteID, tf) // context does the work
return inertia.RenderPage(ctx.Ctx, "Dashboard", inertia.Props{"metrics": metrics})
}
```
Rules: contexts never import `internal/http`; handlers never hold business logic; writes go through `sqlite.PerformWrite` for SQLite's single-writer model. Pages use Inertia + PRG (no `fetch()` for page data).
## matcha: the manager owns ops
matcha is our own deploy/update tool — repo **https://github.com/karloscodes/matcha** (Go module `github.com/karloscodes/matcha`). `cmd/manager` is a thin wrapper over `matcha` — install, update, deploy, backup, image swap are library calls, not bespoke shell:
```go
m := matcha.New(matcha.Config{Name: "fusionaly", AppImage: "karloscodes/fusionaly:latest",
HealthPath: "/_health", Volumes: []string{"/app/storage", "/app/logs"},
CronUpdates: true, Backups: true, ManagerRepo: "karloscodes/fusionaly-oss"})
// commands delegate: m.Install(), m.Update(), m.Deploy(), m.BackupDB(), m.SetImage(...)
```
Add a manager command by mirroring an existing one (`runMigrateToOSS` mirrors the structure of the others). Don't script Docker by hand.
## Background jobs & shutdown
Jobs are a `BackgroundWorker` registered with cartridge, so they start and stop with the server. The scheduler runs each job on a ticker through `executeJobSafely` (panic-safe, single-flight). A job is just a struct with `Run() error` — the scheduler owns timing; jobs never spin their own goroutine/ticker. See `internal/jobs/scheduler.go` + `internal/jobs/feed.go`.
## Testing conventions
- **Real behavior, no mocks.** Use a real SQLite test DB via `testsupport.SetupTestDBManager(t)` (wraps `cartridge/testsupport`). Register new models in `testsupport.allModels()`.
- **Env:** tests require `FUSIONALY_ENV=test` — run with `make test` (sets it for you), not bare `go test`.
- **Four phases** with blank lines between: setup, exercise, verify, teardown. Assert with testify `assert`/`require`.
- **Contexts via `t.Run`** for related scenarios ("with valid key", "with no key").
- **Table-driven only when the cases are open-ended/homogeneous** — e.g. a list of SQL strings each expected to be rejected (`internal/ai/ai_test.go` `TestValidateReadOnlyQuery`). Don't force a table when a few `t.Run` blocks read clearer.
- E2E (`e2e/`) is Playwright, **sequential** (`workers: 1`, story order 001→…); specs build on each other (onboarding creates the user — setup does not). Wait on conditions, never race `networkidle`.
## Common mistakes
| Mistake | Instead |
|---|---|
| Writing a `main()` loop, shutdown handler, or middleware cartridge already provides | Configure `ApplicationOptions`; let cartridge own it |
| Business logic in an `internal/http` handler | Move it to the domain context; handler just parses + renders |
| A context importing `internal/http` | Contexts are HTTP-agnostic; pass `*gorm.DB` |
| Raw `db.Exec` writes scattered around | `sqlite.PerformWrite(...)` (single-writer safety) |
| Hand-rolled Docker/deploy logic in the manager | A `matcha` call |
| Mocks in tests | Real test DB via `testsupport` |
| A job that starts its own ticker/goroutine | `Run() error` + register in the scheduler |
| `fetch()` for page data | Inertia props + PRG |Related Skills
qa
Use after code changes, before releases, or when testing features - runs the right level of QA based on what changed
fusionaly
Use when user asks about website analytics, traffic, visitors, page views, referrers, or mentions "fusionaly". Queries Fusionaly analytics via SQL API.
fusionaly-deploy
Use ONLY when explicitly invoked. Installs Fusionaly on a server you can reach over SSH with a key. Optionally provisions a new Hetzner server or sets up Cloudflare DNS.
design
Use when styling Fusionaly UI components, pages, or charts - applies the Fusionaly design system with black/white palette and brand accents
hig-technologies
Check for .claude/apple-design-context.md before asking questions. Use existing context and only ask for information not already covered.
fda-medtech-compliance-auditor
Expert AI auditor for Medical Device (SaMD) compliance, IEC 62304, and 21 CFR Part 820. Reviews DHFs, technical files, and software validation.
codebase-cleanup-tech-debt
You are a technical debt expert specializing in identifying, quantifying, and prioritizing technical debt in software projects. Analyze the codebase to uncover debt, assess its impact, and create acti
code-refactoring-tech-debt
You are a technical debt expert specializing in identifying, quantifying, and prioritizing technical debt in software projects. Analyze the codebase to uncover debt, assess its impact, and create acti
simple-tech-analyzer - 简易技术分析器
**版本**: 1.0.0
tech-blog
Generates comprehensive technical blog posts, offering detailed explanations of system internals, architecture, and implementation, either through source code analysis or document-driven research.
technical-seo-audit
A comprehensive technical SEO audit skill that analyzes crawl data, identifies critical issues, and prioritizes actions based on business impact, delivering a detailed report and an actionable spreadsheet.
wellally-tech
Integrate multiple digital health data sources, connect to [WellAlly.tech](https://www.wellally.tech/) knowledge base, providing data import and knowledge reference for personal health management systems.