synorch 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +56 -0
- package/dist/application/doctor-service.d.ts +24 -0
- package/dist/application/doctor-service.d.ts.map +1 -0
- package/dist/application/doctor-service.js +508 -0
- package/dist/application/doctor-service.js.map +1 -0
- package/dist/application/project-discovery.d.ts +23 -0
- package/dist/application/project-discovery.d.ts.map +1 -0
- package/dist/application/project-discovery.js +741 -0
- package/dist/application/project-discovery.js.map +1 -0
- package/dist/application/skill-resolver.d.ts +25 -0
- package/dist/application/skill-resolver.d.ts.map +1 -0
- package/dist/application/skill-resolver.js +90 -0
- package/dist/application/skill-resolver.js.map +1 -0
- package/dist/application/structure-service.d.ts +11 -0
- package/dist/application/structure-service.d.ts.map +1 -0
- package/dist/application/structure-service.js +116 -0
- package/dist/application/structure-service.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +170 -0
- package/dist/cli.js.map +1 -0
- package/dist/domain/config.d.ts +210 -0
- package/dist/domain/config.d.ts.map +1 -0
- package/dist/domain/config.js +108 -0
- package/dist/domain/config.js.map +1 -0
- package/dist/domain/errors.d.ts +5 -0
- package/dist/domain/errors.d.ts.map +1 -0
- package/dist/domain/errors.js +9 -0
- package/dist/domain/errors.js.map +1 -0
- package/dist/domain/generation.d.ts +21 -0
- package/dist/domain/generation.d.ts.map +1 -0
- package/dist/domain/generation.js +2 -0
- package/dist/domain/generation.js.map +1 -0
- package/dist/domain/product.d.ts +3 -0
- package/dist/domain/product.d.ts.map +1 -0
- package/dist/domain/product.js +3 -0
- package/dist/domain/product.js.map +1 -0
- package/dist/domain/skill-packs.d.ts +39 -0
- package/dist/domain/skill-packs.d.ts.map +1 -0
- package/dist/domain/skill-packs.js +98 -0
- package/dist/domain/skill-packs.js.map +1 -0
- package/dist/domain/skill-sources.d.ts +20 -0
- package/dist/domain/skill-sources.d.ts.map +1 -0
- package/dist/domain/skill-sources.js +95 -0
- package/dist/domain/skill-sources.js.map +1 -0
- package/dist/infrastructure/bundled-skill-library.d.ts +10 -0
- package/dist/infrastructure/bundled-skill-library.d.ts.map +1 -0
- package/dist/infrastructure/bundled-skill-library.js +108 -0
- package/dist/infrastructure/bundled-skill-library.js.map +1 -0
- package/dist/infrastructure/file-system.d.ts +21 -0
- package/dist/infrastructure/file-system.d.ts.map +1 -0
- package/dist/infrastructure/file-system.js +72 -0
- package/dist/infrastructure/file-system.js.map +1 -0
- package/dist/infrastructure/serialization.d.ts +3 -0
- package/dist/infrastructure/serialization.d.ts.map +1 -0
- package/dist/infrastructure/serialization.js +11 -0
- package/dist/infrastructure/serialization.js.map +1 -0
- package/dist/templates/structure-templates.d.ts +4 -0
- package/dist/templates/structure-templates.d.ts.map +1 -0
- package/dist/templates/structure-templates.js +471 -0
- package/dist/templates/structure-templates.js.map +1 -0
- package/dist/templates/technology-skill-templates.d.ts +3 -0
- package/dist/templates/technology-skill-templates.d.ts.map +1 -0
- package/dist/templates/technology-skill-templates.js +73 -0
- package/dist/templates/technology-skill-templates.js.map +1 -0
- package/package.json +59 -0
- package/skill-sources/ingenium/NOTICE.md +11 -0
- package/skill-sources/ingenium/skills/db-schema-craft/SKILL.md +127 -0
- package/skill-sources/ingenium/skills/debug-detective/SKILL.md +67 -0
- package/skill-sources/ingenium/skills/design-system/SKILL.md +57 -0
- package/skill-sources/ingenium/skills/docs-sync/SKILL.md +68 -0
- package/skill-sources/ingenium/skills/dotnet-backend/SKILL.md +110 -0
- package/skill-sources/ingenium/skills/frontend-craft/SKILL.md +69 -0
- package/skill-sources/ingenium/skills/game-audio/SKILL.md +73 -0
- package/skill-sources/ingenium/skills/game-design/SKILL.md +92 -0
- package/skill-sources/ingenium/skills/godot-dev/SKILL.md +78 -0
- package/skill-sources/ingenium/skills/human-made-design/SKILL.md +73 -0
- package/skill-sources/ingenium/skills/java-backend/SKILL.md +98 -0
- package/skill-sources/ingenium/skills/jev/SKILL.md +150 -0
- package/skill-sources/ingenium/skills/motion-craft/SKILL.md +66 -0
- package/skill-sources/ingenium/skills/multiplayer-netcode/SKILL.md +63 -0
- package/skill-sources/ingenium/skills/node-backend/SKILL.md +113 -0
- package/skill-sources/ingenium/skills/node-backend/reference.md +144 -0
- package/skill-sources/ingenium/skills/perf-audit/SKILL.md +70 -0
- package/skill-sources/ingenium/skills/pixel-art-assets/SKILL.md +91 -0
- package/skill-sources/ingenium/skills/pixel-art-assets/scripts/px.py +169 -0
- package/skill-sources/ingenium/skills/pixel-game-dev/SKILL.md +79 -0
- package/skill-sources/ingenium/skills/project-onboard/SKILL.md +78 -0
- package/skill-sources/ingenium/skills/pwa-offline/SKILL.md +70 -0
- package/skill-sources/ingenium/skills/query-tuning/SKILL.md +137 -0
- package/skill-sources/ingenium/skills/react-modern/SKILL.md +92 -0
- package/skill-sources/ingenium/skills/refactor-safe/SKILL.md +63 -0
- package/skill-sources/ingenium/skills/release-prep/SKILL.md +57 -0
- package/skill-sources/ingenium/skills/safe-merge/SKILL.md +91 -0
- package/skill-sources/ingenium/skills/session-recap/SKILL.md +95 -0
- package/skill-sources/ingenium/skills/session-recap/scripts/extract_session.py +409 -0
- package/skill-sources/ingenium/skills/shader-vfx/SKILL.md +70 -0
- package/skill-sources/ingenium/skills/tailwind-v4-tokens/SKILL.md +165 -0
- package/skill-sources/ingenium/skills/task-conductor/SKILL.md +158 -0
- package/skill-sources/ingenium/skills/tauri-game-dev/SKILL.md +81 -0
- package/skill-sources/ingenium/skills/ui-ux-design/SKILL.md +96 -0
- package/skill-sources/ingenium/skills/vue-modern/SKILL.md +88 -0
- package/skill-sources/ingenium/skills/web-kickoff/SKILL.md +63 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: db-schema-craft
|
|
3
|
+
description: Relational data modeling and schema evolution, engine-agnostic with per-engine notes (PostgreSQL, SQL Server, Oracle, MySQL) - turning a domain into tables, choosing keys (surrogate versus natural, bigint versus UUIDv7), picking exact column types instead of string-for-everything, modeling one-to-many and many-to-many with payload join tables, normalizing to 3NF and denormalizing only with a stated reason, enforcing truth with constraints rather than application code, handling money, time zones, enums, soft deletes and audit history, designing indexes at the same time as the table, partitioning when it is actually warranted, and zero-downtime migrations via expand/contract. Use when designing or reviewing a database schema, adding tables or columns, modeling relationships, deciding key or column types, or planning a risky migration on a live system. Türkçe tetikleyiciler - "veritabanı tasarla", "tablo yapısı kur", "şema tasarımı", "ilişkileri modelle", "many to many nasıl", "primary key seçimi", "uuid mi int mi", "migration nasıl yapılmalı", "kolon tipi ne olmalı", "veritabanını normalize et".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DB Schema Craft
|
|
7
|
+
|
|
8
|
+
A schema is the longest-lived artifact in the system. Application code gets rewritten; the data outlives three frameworks. Design it so the database itself refuses to hold a wrong row — every rule you leave to application code is a rule that will be violated by a script, a second service, or a future you.
|
|
9
|
+
|
|
10
|
+
Always communicate with the user in their own language.
|
|
11
|
+
|
|
12
|
+
## Phase 1 — Understand before drawing tables
|
|
13
|
+
|
|
14
|
+
Establish, in the user's language, before any DDL:
|
|
15
|
+
|
|
16
|
+
- **The entities and the language around them.** Use the business's words for tables and columns. A table named `data1` costs the team forever.
|
|
17
|
+
- **The cardinalities and their reality**: is one order really one customer, or can it be transferred? Is an email unique per user or per tenant? Ask about the exceptional case — that is what breaks a model.
|
|
18
|
+
- **Access patterns**: which queries run per page load, which run nightly, which filter by what. A schema designed without knowing the reads is a guess.
|
|
19
|
+
- **Volume and growth**: thousands or hundreds of millions of rows changes key type, index strategy and partitioning.
|
|
20
|
+
- **Multi-tenancy**: shared table with a `tenant_id`, schema per tenant, or database per tenant — decide now, because retrofitting is a rewrite.
|
|
21
|
+
- **Retention and compliance**: what must be deletable, what must be immutable, what must be auditable.
|
|
22
|
+
|
|
23
|
+
If the schema already exists, read it first — tables, foreign keys, indexes, and a sample of real rows. The existing conventions (naming, key style, timestamp columns) are the contract you follow; a table styled differently from every other one is a defect even if it is "better".
|
|
24
|
+
|
|
25
|
+
## Phase 2 — Entities, keys and types
|
|
26
|
+
|
|
27
|
+
**Keys**
|
|
28
|
+
|
|
29
|
+
| Choice | When |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `bigint` identity/sequence | Default. Small, sequential, index-friendly, join-cheap |
|
|
32
|
+
| **UUIDv7** | IDs generated client-side or across services, or IDs exposed publicly. Time-ordered, so unlike UUIDv4 it does not shred index locality |
|
|
33
|
+
| UUIDv4 | Only when unpredictability matters more than write performance — and then not as the clustered key |
|
|
34
|
+
| Natural key as PK | Only for genuinely immutable, universally agreed codes (ISO country code). Anything a human can edit is not a key |
|
|
35
|
+
| Composite PK | Correct for pure join tables; annoying everywhere else because every child FK inherits all its columns |
|
|
36
|
+
|
|
37
|
+
A surrogate primary key does not excuse you from a **unique constraint on the natural key**. Without it, the same customer gets inserted twice with different ids and every report is wrong.
|
|
38
|
+
|
|
39
|
+
**Types — be exact, not convenient**
|
|
40
|
+
|
|
41
|
+
| Data | Use | Never |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| Money | `numeric(19,4)` / `decimal` plus an explicit currency column | `float`/`double` — rounding errors in money are unrecoverable |
|
|
44
|
+
| Timestamps | `timestamptz` (PostgreSQL) / `datetimeoffset` (SQL Server), stored in UTC | Naive local-time columns; a timestamp without a zone is a bug with a delay |
|
|
45
|
+
| Dates with no time | `date` | A timestamp at midnight in an unknown zone |
|
|
46
|
+
| Enumerated states | A lookup table with an FK, or a native enum plus a `CHECK` | A free-text `varchar` holding `"Active"`, `"active"`, `"ACTIVE"` |
|
|
47
|
+
| Text | `text`/`varchar(n)` with a length that reflects a real rule | `varchar(255)` chosen by reflex |
|
|
48
|
+
| Flags | `boolean` / `bit` | `char(1)` holding `'Y'`/`'N'`/`'y'`/`null` |
|
|
49
|
+
| Structured extras | `jsonb` for genuinely variable attributes | JSON as a way to avoid designing columns you query and filter on |
|
|
50
|
+
| Files | A URL or object key | The blob itself in a hot transactional table |
|
|
51
|
+
|
|
52
|
+
Every table gets `created_at` and `updated_at`. Nullability is a decision, not a default: `NOT NULL` unless "unknown" is a meaningful state, and never a magic sentinel like `''`, `0` or `1900-01-01`.
|
|
53
|
+
|
|
54
|
+
## Phase 3 — Relationships
|
|
55
|
+
|
|
56
|
+
- **One-to-many**: the foreign key lives on the many side. Always declare it as a real `FOREIGN KEY` — "we enforce it in the application" is how orphan rows appear.
|
|
57
|
+
- **Many-to-many**: a join table named for the relationship (`order_items`, not `order_product`), with its own surrogate key when it carries payload (quantity, price, added_at) and a unique constraint on the pair. A join table with attributes is an entity; treat it like one.
|
|
58
|
+
- **One-to-one**: usually a sign the two tables should be one. Legitimate when a rarely-used, wide, or differently-secured block of columns is split off — then the child's PK *is* the parent's PK.
|
|
59
|
+
- **Inheritance / polymorphic types**: prefer a shared table with a discriminator plus nullable specifics when the variants are similar; separate tables when they diverge. Avoid the "polymorphic FK" pattern (`owner_type` + `owner_id`) — the database cannot enforce it; use separate nullable FKs with a `CHECK` that exactly one is set.
|
|
60
|
+
- **Self-referencing hierarchies**: `parent_id` is fine for shallow trees; for deep trees plan the read strategy up front (recursive CTE, materialized path, or closure table) rather than discovering it under load.
|
|
61
|
+
- **`ON DELETE` is a domain decision**: `CASCADE` only where the child is genuinely part of the parent (order lines), `RESTRICT` for anything referenced elsewhere, `SET NULL` only when null is a legal state.
|
|
62
|
+
|
|
63
|
+
## Phase 4 — Let the database enforce the truth
|
|
64
|
+
|
|
65
|
+
Every invariant you can express in DDL, express in DDL:
|
|
66
|
+
|
|
67
|
+
- `NOT NULL` on everything that is required.
|
|
68
|
+
- `UNIQUE` on every natural key and on every "can only exist once" rule — including partial/filtered uniques (`WHERE deleted_at IS NULL`) for soft-deleted rows.
|
|
69
|
+
- `CHECK` for ranges, state values, and cross-column rules (`ends_at > starts_at`, `discount BETWEEN 0 AND 100`).
|
|
70
|
+
- `FOREIGN KEY` on every reference, with an index on the referencing column.
|
|
71
|
+
- `DEFAULT` for values the database can supply itself.
|
|
72
|
+
|
|
73
|
+
**Normalize to 3NF first.** Every fact in one place; a value you can derive is not stored. Then denormalize deliberately, and only with a written reason: a counter or a cached total is acceptable when the read cost is proven and you say how it stays correct (trigger, transactional update, or scheduled reconciliation). Denormalization without a correctness plan is just a future data bug.
|
|
74
|
+
|
|
75
|
+
**Soft delete** (`deleted_at timestamptz NULL`) is a real decision with a real cost: every query must filter it, unique constraints must become partial, and foreign keys keep pointing at "deleted" rows. Use it when history matters; otherwise delete, and archive elsewhere.
|
|
76
|
+
|
|
77
|
+
**Audit history**: an append-only `*_history` table (or system-versioned/temporal tables where the engine supports them) beats trying to reconstruct the past from logs. Decide at design time — retrofitting history over existing data is guesswork.
|
|
78
|
+
|
|
79
|
+
## Phase 5 — Indexes belong to the design
|
|
80
|
+
|
|
81
|
+
Design indexes with the table, not after the first outage:
|
|
82
|
+
|
|
83
|
+
- The primary key is indexed automatically; **foreign key columns are not** in most engines and are the single most common missing index.
|
|
84
|
+
- Index the columns your known access patterns filter, join and sort on. Composite index column order follows equality → range → sort.
|
|
85
|
+
- A unique constraint is also an index; do not duplicate it.
|
|
86
|
+
- Every index costs write throughput and storage. An unused index is pure loss — plan to check usage after release.
|
|
87
|
+
- Beyond this, sizing, plan reading and fixing a slow query belong to **query-tuning**; this phase is only about not shipping a table with no way to read it.
|
|
88
|
+
|
|
89
|
+
**Partitioning** is warranted when a table is genuinely large (hundreds of millions of rows) *and* has a natural range key (usually time) *and* you drop or archive whole ranges. Partitioning a five-million-row table adds complexity and buys nothing. Choose the partition key from the query patterns, never from convenience.
|
|
90
|
+
|
|
91
|
+
## Phase 6 — Migrations that do not take the system down
|
|
92
|
+
|
|
93
|
+
- **Migrations are versioned, reviewed, forward-only files in the repo** (Flyway, Liquibase, EF Core, Prisma, Alembic, Knex — whatever the project uses). Never change a schema by hand in a shared environment, and never edit a migration that has already run.
|
|
94
|
+
- **Read the generated SQL before applying it.** ORM migration generators produce destructive drops with complete confidence.
|
|
95
|
+
- **Expand / contract for anything a running version still reads**:
|
|
96
|
+
1. **Expand** — add the new nullable column, table or index; deploy.
|
|
97
|
+
2. **Backfill** in batches, with the application writing to both old and new.
|
|
98
|
+
3. **Switch** reads to the new shape; deploy and observe.
|
|
99
|
+
4. **Contract** — make it `NOT NULL`, drop the old column, in a later release once nothing references it.
|
|
100
|
+
- Rename is never in-place under load: it is add, dual-write, backfill, switch, drop.
|
|
101
|
+
- **Long locks are the real danger.** Adding an index concurrently, adding a column with a volatile default, or validating a constraint can lock a hot table. Know your engine's behavior, set a `lock_timeout`, and run heavy DDL in a maintenance window if it is not online-safe.
|
|
102
|
+
- **Backfill in bounded batches** with commits between them. One `UPDATE` over fifty million rows is a transaction log incident.
|
|
103
|
+
- Every migration has a stated rollback plan — a down script, or an explicit "forward-fix only, here is how".
|
|
104
|
+
- Test the migration against a restored copy of production-shaped data, not an empty schema.
|
|
105
|
+
|
|
106
|
+
## Engine notes
|
|
107
|
+
|
|
108
|
+
| Engine | Worth knowing |
|
|
109
|
+
|---|---|
|
|
110
|
+
| **PostgreSQL** | `timestamptz`, `jsonb`, partial and expression indexes, `GENERATED ALWAYS AS IDENTITY` over `serial`, `CREATE INDEX CONCURRENTLY`, `ADD CONSTRAINT ... NOT VALID` then `VALIDATE` to avoid long locks |
|
|
111
|
+
| **SQL Server** | The clustered index *is* the row order — pick it narrow, static and increasing; `datetimeoffset` over `datetime`; filtered indexes; `ONLINE = ON` rebuilds on supported editions; temporal tables for history |
|
|
112
|
+
| **Oracle** | Sequences plus identity columns, `VARCHAR2`, no native boolean before 23ai (use `NUMBER(1)` + `CHECK`), invisible indexes for safe testing, partitioning is mature and license-gated |
|
|
113
|
+
| **MySQL / MariaDB** | InnoDB clusters on the PK, so a random UUID PK hurts badly — use UUIDv7 or bigint; `utf8mb4` always; DDL online-ness varies sharply by version and operation |
|
|
114
|
+
|
|
115
|
+
## Rules
|
|
116
|
+
|
|
117
|
+
1. Understand the domain, the access patterns and the volume before writing DDL.
|
|
118
|
+
2. Follow the existing schema's conventions; a differently-styled table is a defect.
|
|
119
|
+
3. Names come from the business vocabulary, and one naming convention applies to the whole schema.
|
|
120
|
+
4. Every invariant expressible as a constraint is a constraint — `NOT NULL`, `UNIQUE`, `CHECK`, `FOREIGN KEY`.
|
|
121
|
+
5. Exact types: decimal for money, timezone-aware timestamps in UTC, no `varchar(255)` by reflex, no floats for anything counted or paid.
|
|
122
|
+
6. Normalize to 3NF; denormalize only with a stated reason and a stated correctness mechanism.
|
|
123
|
+
7. Every foreign key column gets an index; every table ships with the indexes its known reads require.
|
|
124
|
+
8. Soft delete, history and multi-tenancy are decided at design time, not retrofitted.
|
|
125
|
+
9. Migrations are reviewed files, read before applying, batched on backfill, and expand/contract for anything live.
|
|
126
|
+
10. No destructive change without a rollback plan and a test against production-shaped data.
|
|
127
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debug-detective
|
|
3
|
+
description: Systematic root-cause debugging for stubborn, non-obvious or flaky bugs - reproduce first, bisect the search space, instrument with evidence, prove the mechanism before fixing, then lock it in with a regression test. Use when a bug resists quick fixes, behavior is inconsistent or flaky, an error's origin is unclear, or the user asks why something does not work. Türkçe tetikleyiciler - "hatayı bul", "bug'ı araştır", "neden çalışmıyor", "kök neden analizi yap", "hata ayıkla", "sorunun kaynağını bul", "bazen çalışıyor bazen çalışmıyor".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Debug Detective
|
|
7
|
+
|
|
8
|
+
You are a systematic debugger. Prime directive: **no fix before a proven root cause.** A fix that works without an explanation is a time bomb; you find the mechanism, then change the code.
|
|
9
|
+
|
|
10
|
+
Always communicate with the user in their own language.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
- Reproduce before you theorize. If you cannot reproduce it, that is your first problem to solve — not a reason to guess.
|
|
15
|
+
- Change ONE variable at a time. Batched changes destroy the evidence.
|
|
16
|
+
- The root cause must explain ALL symptoms. A theory that explains 4 of 5 symptoms is the wrong theory.
|
|
17
|
+
- Never "fix" by deleting the failing test, silencing the error, widening a try/catch, or adding a sleep. Those are confessions, not fixes.
|
|
18
|
+
- Write your hypothesis down before testing it. Track them; a rejected hypothesis is progress.
|
|
19
|
+
- Read the actual error text carefully, twice. The answer is in the message more often than pride allows.
|
|
20
|
+
|
|
21
|
+
## Phase 1 — Reproduce
|
|
22
|
+
|
|
23
|
+
- Build the smallest deterministic reproduction you can: exact command, exact input, exact environment.
|
|
24
|
+
- Flaky bug? Run it in a loop (20–100×) to measure the failure rate; capture seeds, timestamps, ordering. A flake rate is a measurement you will re-use to prove the fix.
|
|
25
|
+
- Record the last-known-good state if one exists (version, commit, date).
|
|
26
|
+
|
|
27
|
+
## Phase 2 — Evidence collection
|
|
28
|
+
|
|
29
|
+
- Exact error message + full stack trace, from the first error, not the last (later errors are usually fallout).
|
|
30
|
+
- Logs around the failure window; application state at the moment of failure.
|
|
31
|
+
- `git log --oneline <last-good>..HEAD` — what changed since it last worked? Dependency updates count (`git diff <last-good>..HEAD -- package.json pnpm-lock.yaml` or equivalent).
|
|
32
|
+
- Environment diffs: works-on-my-machine means the environments differ — find the axis (OS, node/runtime version, env vars, data, locale, timezone, network).
|
|
33
|
+
|
|
34
|
+
## Phase 3 — Bisect the search space
|
|
35
|
+
|
|
36
|
+
Halve, don't wander:
|
|
37
|
+
|
|
38
|
+
- **Time axis**: `git bisect run <repro-command>` when a last-good commit exists — this is the fastest tool you have; use it before manual code reading.
|
|
39
|
+
- **Code axis**: disable/stub half the pipeline; does it still fail? Recurse into the failing half.
|
|
40
|
+
- **Data axis**: fails with production data but not fixtures → binary-search the dataset to the minimal failing record.
|
|
41
|
+
- **Config axis**: reset to defaults, reintroduce settings in halves.
|
|
42
|
+
|
|
43
|
+
## Phase 4 — Instrument
|
|
44
|
+
|
|
45
|
+
- Add targeted logging/asserts at the boundaries of the suspected region: log actual values, not assumptions ("expected X, got Y" style).
|
|
46
|
+
- Inspect real runtime values — a debugger session or printed state beats reading code and imagining values.
|
|
47
|
+
- For race conditions: log thread/task ids and ordering; artificially widen the suspected window (small delay) to make the race reproducible, then remove it.
|
|
48
|
+
|
|
49
|
+
## Phase 5 — Prove the mechanism
|
|
50
|
+
|
|
51
|
+
State it as a causal chain: *X happens, which causes Y, because Z.* Then prove it both ways:
|
|
52
|
+
|
|
53
|
+
- With the fix applied, the reproduction passes — including the flaky loop at 0 failures.
|
|
54
|
+
- With the fix reverted, it fails again.
|
|
55
|
+
- The mechanism explains every symptom collected in Phase 2. Unexplained symptoms mean a second bug or the wrong theory — say which.
|
|
56
|
+
|
|
57
|
+
## Phase 6 — Fix, lock, sweep
|
|
58
|
+
|
|
59
|
+
- Minimal fix at the root cause, not at the symptom site.
|
|
60
|
+
- Add a regression test that fails without the fix and passes with it.
|
|
61
|
+
- Sweep for the same bug class elsewhere (`grep` for the pattern: same misused API, same unchecked null, same off-by-one shape) and report what you find.
|
|
62
|
+
- Summarize for the user: root cause, mechanism, fix, proof, and any remaining risks.
|
|
63
|
+
|
|
64
|
+
## Anti-patterns (never do these)
|
|
65
|
+
|
|
66
|
+
Shotgun debugging (many changes, then "it works now"); blaming the framework/compiler first; fixing where the error appears instead of where it originates; catching-and-ignoring; adding retries/sleeps to hide races; declaring victory without re-running the original reproduction.
|
|
67
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-system
|
|
3
|
+
description: Design and build a component library or design system - design tokens (semantic color, spacing, typography scales), light/dark theming as a token swap, primitive-first component architecture on headless libraries (Radix, React Aria), clean variant APIs instead of boolean prop explosions, baked-in accessibility, documentation and versioning. Use when starting a component library, standardizing inconsistent UI, implementing design tokens, adding theming or dark mode infrastructure, or building reusable components properly. Türkçe tetikleyiciler - "design system kur", "component library oluştur", "tasarım sistemi", "ui'ı standardize et", "tema sistemi ekle", "dark mode altyapısı kur", "design token yapısı", "ortak component kütüphanesi".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Design System
|
|
7
|
+
|
|
8
|
+
You build design systems that fit their team. Reality check first: a solo project needs a *lightweight* system — tokens plus ten disciplined components — not an enterprise Storybook pipeline. Scale the ceremony to the number of people who must agree.
|
|
9
|
+
|
|
10
|
+
Always communicate with the user in their own language.
|
|
11
|
+
|
|
12
|
+
## Phase 1 — Tokens before components
|
|
13
|
+
|
|
14
|
+
Components built before tokens hardcode chaos. Establish, in order:
|
|
15
|
+
|
|
16
|
+
- **Color, two layers**: a raw palette (gray-50…gray-950, brand scales) and a **semantic layer** the components actually use — `bg`, `surface`, `text`, `text-muted`, `border`, `accent`, plus state variants (hover/active/disabled) and intent colors (danger/warning/success/info). Components never touch raw hex or palette steps directly.
|
|
17
|
+
- **Spacing**: one scale, 4px base (4, 8, 12, 16, 24, 32, 48, 64). Off-scale one-off values are bugs.
|
|
18
|
+
- **Typography**: max 2 families; 4–6 sizes with paired line-heights; 2–3 weights. Name by role (body, caption, heading-1) not by pixel.
|
|
19
|
+
- **Radii, shadows, z-index**: small fixed scales; z-index especially must be a token ladder (dropdown < sticky < overlay < modal < toast) or stacking wars begin.
|
|
20
|
+
- **Motion tokens**: 2–3 durations + 2 easings (see the motion-craft skill).
|
|
21
|
+
|
|
22
|
+
Implementation: CSS custom properties for the semantic layer (theme-swappable at runtime), mapped into the framework's theme (Tailwind theme config, styled-system, vanilla-extract — whatever the project uses).
|
|
23
|
+
|
|
24
|
+
## Phase 2 — Theming
|
|
25
|
+
|
|
26
|
+
- Dark mode is a **semantic-token swap**, never per-component rewrites: `[data-theme="dark"]` redefines the semantic custom properties; components don't know themes exist.
|
|
27
|
+
- Default from `prefers-color-scheme`, allow explicit override, persist the choice.
|
|
28
|
+
- Re-verify contrast in *both* themes (4.5:1 body text, 3:1 large text/UI); dark mode fails contrast more often than light.
|
|
29
|
+
- Don't invert shadows in dark mode — use surface elevation (lighter surface = higher) instead.
|
|
30
|
+
|
|
31
|
+
## Phase 3 — Component architecture
|
|
32
|
+
|
|
33
|
+
- Build order: **primitives** (Button, Text, Input, Icon, Stack/Box) → **composites** (Field = Label+Input+Error, Card, Dialog) → **patterns** (forms, tables, page shells).
|
|
34
|
+
- Hard interaction/a11y components (Dialog, Menu, Combobox, Tabs, Tooltip) go on a **headless library** — Radix, React Aria, Headless UI. Hand-rolling focus traps and aria wiring is how systems ship broken modals.
|
|
35
|
+
- **Variant API discipline**: `variant` / `size` / `tone` enums (CVA or typed props) — never boolean explosions (`isPrimary isLarge isDanger` → impossible combinations). Same enum values across all components: `size="sm|md|lg"` everywhere.
|
|
36
|
+
|
|
37
|
+
## Phase 4 — Component API rules
|
|
38
|
+
|
|
39
|
+
- Composition over configuration: `children` and slots beat a 12-prop configuration object; compound components (`Card.Header`) for structured content.
|
|
40
|
+
- Forward refs; spread `...rest` onto the root element; merge incoming `className` (cn/tailwind-merge) so consumers can escape-hatch.
|
|
41
|
+
- Controlled *and* uncontrolled modes for inputs where it matters.
|
|
42
|
+
- Polymorphic `as` prop only where genuinely needed (Text, Button-as-link).
|
|
43
|
+
- A component that needs a bugfix in every consumer has the wrong API — fix the abstraction.
|
|
44
|
+
|
|
45
|
+
## Phase 5 — Quality gates (every component)
|
|
46
|
+
|
|
47
|
+
Keyboard operable; visible `:focus-visible` state; ARIA correct (via the headless layer); works in both themes; RTL-safe (logical properties — `margin-inline-start`, not `margin-left`); responsive by default; states covered: hover, focus, active, disabled, loading, error, empty.
|
|
48
|
+
|
|
49
|
+
## Phase 6 — Documentation and distribution
|
|
50
|
+
|
|
51
|
+
- Small project: a `/kitchen-sink` route rendering every component in every variant and both themes — cheap, always current, doubles as a visual regression page.
|
|
52
|
+
- Team/published: Storybook with usage do/don't notes per component; changesets + semver; deprecate before removing (`@deprecated` JSDoc + console warning one minor ahead).
|
|
53
|
+
|
|
54
|
+
## Anti-patterns
|
|
55
|
+
|
|
56
|
+
Wrapping a UI kit 1:1 with no added value (just use the kit); tokens nobody enforces (add a lint rule against raw hex/px); theming everything before one theme works; the God-Button with 25 props; building pattern-level components before the primitives are stable; snapshots-of-everything instead of a browsable kitchen sink.
|
|
57
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docs-sync
|
|
3
|
+
description: Analyze project documentation (README, docs/, architecture notes, API docs, CLAUDE.md, .env.example, changelogs) against the actual current state of the codebase, detect drift with evidence, update the docs to match reality, and report what was undocumented. Use when documentation is stale or suspect, after large changes or refactors, or when asked to synchronize, refresh or audit docs. Türkçe tetikleyiciler - "dokümanları güncelle", "dokümantasyonu senkronize et", "readme'yi güncelle", "dokümanlar güncel mi", "doküman taraması yap", "proje dokümanlarını projenin son haliyle eşitle".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Docs Sync
|
|
7
|
+
|
|
8
|
+
You bring documentation back in line with the code — with evidence, not guesses. Every doc claim is verified against reality before it is kept, corrected, or flagged.
|
|
9
|
+
|
|
10
|
+
Always communicate with the user in their own language.
|
|
11
|
+
|
|
12
|
+
## Phase 1 — Inventory the documentation surface
|
|
13
|
+
|
|
14
|
+
Collect: `README*`, `docs/**`, `CONTRIBUTING*`, `ARCHITECTURE*`, `CLAUDE.md`, `CHANGELOG*`, OpenAPI/Swagger files, `.env.example`, inline "How to run" sections in package manifests, wiki-style `*.md` anywhere in the repo. List what you found and note each file's apparent purpose and language (docs are updated in their own language).
|
|
15
|
+
|
|
16
|
+
## Phase 2 — Extract verifiable claims
|
|
17
|
+
|
|
18
|
+
From each doc, extract every claim that can be checked against the repo:
|
|
19
|
+
|
|
20
|
+
- Commands and scripts ("run `pnpm dev`") — script names, flags, tool names
|
|
21
|
+
- Paths and structure ("services live in `src/services`")
|
|
22
|
+
- Environment variables, ports, URLs, service names
|
|
23
|
+
- API endpoints, request/response shapes
|
|
24
|
+
- Version numbers, supported runtimes, dependency names
|
|
25
|
+
- Setup sequences and prerequisites
|
|
26
|
+
- Architecture statements ("X talks to Y via Z")
|
|
27
|
+
- Feature lists and behavior descriptions
|
|
28
|
+
|
|
29
|
+
Build a claim list; this is your checklist for Phase 3.
|
|
30
|
+
|
|
31
|
+
## Phase 3 — Verify every claim against reality
|
|
32
|
+
|
|
33
|
+
- Scripts: do they exist in the manifest, with the same name and behavior?
|
|
34
|
+
- Paths: do they exist? (`Glob`) Structure diagrams: match against the real tree.
|
|
35
|
+
- Env vars: cross-check docs ↔ `.env.example` ↔ actual usage in code (`grep` for `process.env`, `os.environ`, config loaders).
|
|
36
|
+
- Endpoints: `grep` route definitions; compare with documented method + path.
|
|
37
|
+
- Versions: read manifests/lockfiles — never trust a doc's version claim.
|
|
38
|
+
- Commands: run the harmless ones (`--help`, `--version`, lint, dry-run) to confirm they work as written.
|
|
39
|
+
|
|
40
|
+
Mark each claim: **accurate** / **stale** (says X, reality is Y — with `file:line` evidence) / **unverifiable** (needs a human or a live system).
|
|
41
|
+
|
|
42
|
+
## Phase 4 — Reverse pass: undocumented reality
|
|
43
|
+
|
|
44
|
+
Now walk the other direction — what exists in the repo that the docs never mention:
|
|
45
|
+
|
|
46
|
+
- New scripts, commands, env vars, endpoints, modules
|
|
47
|
+
- Changed defaults, renamed concepts, removed features still described
|
|
48
|
+
- Setup steps that exist only in CI config or in someone's head
|
|
49
|
+
|
|
50
|
+
## Phase 5 — Update the docs
|
|
51
|
+
|
|
52
|
+
- Preserve each document's language, voice, structure and formatting; make minimal diffs.
|
|
53
|
+
- Correct stale claims to verified reality; add missing sections for undocumented features where they naturally belong.
|
|
54
|
+
- Never silently delete a section. If content is obsolete, remove it and say so in the report; if it has historical value, mark it as historical.
|
|
55
|
+
- Anything you could not verify: leave it, flagged with `<!-- TODO(docs-sync): verify - ... -->` and a question for the user.
|
|
56
|
+
- Keep every example copy-paste runnable; test the ones that are safe to run.
|
|
57
|
+
- If a doc is generated (OpenAPI output, typedoc), fix the generator or source annotations — never the generated file.
|
|
58
|
+
|
|
59
|
+
## Phase 6 — Drift report
|
|
60
|
+
|
|
61
|
+
Deliver a table: **fixed** (was → now) / **added** (undocumented reality now covered) / **removed** (obsolete content) / **needs your decision** (ambiguities, unverifiable claims). Note the overall drift level so the user learns how often to re-run this.
|
|
62
|
+
|
|
63
|
+
## Rules
|
|
64
|
+
|
|
65
|
+
- Never document intentions as facts; the repo is the source of truth, the roadmap is not.
|
|
66
|
+
- Version numbers and dependency names come only from manifests.
|
|
67
|
+
- Do not invent features to make docs look complete.
|
|
68
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dotnet-backend
|
|
3
|
+
description: Modern .NET backend engineering, current as of September 2026 (.NET 10 LTS, C# 14, ASP.NET Core 10, EF Core 10) - Minimal API versus controllers and when each wins, request pipeline and middleware ordering, dependency injection lifetimes and the captive-dependency trap, typed configuration and options validation, EF Core done right (change tracking, AsNoTracking, split queries, compiled models, safe migrations), async/await and cancellation discipline, resilient HttpClient through IHttpClientFactory, structured logging and OpenTelemetry, plus the dotnet CLI commands and test strategy (xUnit, WebApplicationFactory, Testcontainers) that make the loop fast. Carries an existing-codebase protocol - detect the target framework and paradigm before writing code. Use when writing, reviewing, upgrading or debugging ASP.NET Core services or EF Core data access, structuring a .NET solution, or asking how to work efficiently in a C# backend. Türkçe tetikleyiciler - "dotnet projesinde çalış", "asp.net core api yaz", "entity framework sorunu", "ef core migration", "c# best practice", "dotnet komutları", "minimal api mi controller mı", "dependency injection hatası", "dotnet sürüm yükseltme", "async await sorunu".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# .NET Backend
|
|
7
|
+
|
|
8
|
+
You write ASP.NET Core the way it is in 2026: a small, explicit host, endpoints that validate and delegate, EF Core used as a mapper you actually control rather than a magic box, and async all the way down with cancellation honored.
|
|
9
|
+
|
|
10
|
+
Always communicate with the user in their own language.
|
|
11
|
+
|
|
12
|
+
## Freshness protocol
|
|
13
|
+
|
|
14
|
+
Current as of **September 2026**: .NET 10 (LTS, Nov 2025) with C# 14, ASP.NET Core 10 and EF Core 10; .NET 8 is the previous LTS and still widespread. Before locking a target framework or upgrade decision, verify at learn.microsoft.com/dotnet and the .NET release notes — if reality moved past this skill, reality wins and say so.
|
|
15
|
+
|
|
16
|
+
## Existing codebase protocol (read before touching an old project)
|
|
17
|
+
|
|
18
|
+
- **Detect reality first**: `TargetFramework` from the `.csproj`, `Nullable` and `ImplicitUsings` flags, whether the app uses `Program.cs` top-level statements or the old `Startup.cs`, controllers or Minimal API, and the EF Core major version from the package reference.
|
|
19
|
+
- **Match the repo's paradigm.** A Minimal API island in a controller-based solution, or a MediatR-free vertical slice inside a CQRS codebase, costs more than the style it saves.
|
|
20
|
+
- **Feature-gate by target framework**: no `required` members or raw string literals below C# 11, no primary constructors or collection expressions below C# 12, no `field` keyword or extension members below C# 14, no EF Core 10 APIs on an EF Core 8 package.
|
|
21
|
+
- **Framework upgrades are proposed, scoped work** — never a quiet side effect of a feature.
|
|
22
|
+
|
|
23
|
+
## Minimal API or controllers
|
|
24
|
+
|
|
25
|
+
| Situation | Pick |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Focused service, few dozen endpoints, performance-sensitive | **Minimal API** with endpoint groups (`MapGroup`) and one static class per feature |
|
|
28
|
+
| Large surface, heavy model binding, filters/conventions, OData-ish needs | **Controllers** — the convention machinery earns its weight |
|
|
29
|
+
| Existing solution | Whatever it already uses |
|
|
30
|
+
|
|
31
|
+
With Minimal API, do not let `Program.cs` become a thousand-line wall: one `MapXEndpoints()` extension per feature, registered from the host. Use `TypedResults` so the return type documents itself and tests can assert on it.
|
|
32
|
+
|
|
33
|
+
## Host and pipeline
|
|
34
|
+
|
|
35
|
+
- Middleware order is behavior, not style: exception handling → HSTS/HTTPS redirect → static files → routing → CORS → authentication → authorization → endpoints. Authorization before authentication is a security bug, not a warning.
|
|
36
|
+
- Use `IExceptionHandler` (or `UseExceptionHandler` with a problem-details writer) plus `AddProblemDetails` so every failure returns one RFC 9457 shape. Never let a stack trace reach a client.
|
|
37
|
+
- Health checks (`/health/live`, `/health/ready`) are part of the deliverable, not an extra.
|
|
38
|
+
- Bind configuration to records with `AddOptions<T>().Bind(...).ValidateDataAnnotations().ValidateOnStart()` — a bad config should fail at boot, not at 3 a.m. on the first request that reads it. Secrets come from user-secrets locally and the environment or a vault in production.
|
|
39
|
+
|
|
40
|
+
## Dependency injection
|
|
41
|
+
|
|
42
|
+
- **Lifetimes**: `Singleton` for stateless and thread-safe services, `Scoped` for anything per-request (a `DbContext` is always scoped), `Transient` for cheap stateless helpers.
|
|
43
|
+
- **The captive dependency trap**: injecting a scoped service into a singleton silently freezes one scope forever. A hosted service or singleton that needs a `DbContext` creates a scope per unit of work with `IServiceScopeFactory`.
|
|
44
|
+
- Register against interfaces the consumer needs; do not resolve from `IServiceProvider` inside business code — that is a service locator, and it hides dependencies from the constructor and from tests.
|
|
45
|
+
|
|
46
|
+
## EF Core, used deliberately
|
|
47
|
+
|
|
48
|
+
- **`AsNoTracking()` on every read-only query.** Change tracking on a list endpoint is pure waste, and it is the most common easy win in a .NET codebase.
|
|
49
|
+
- **Project, do not load.** `Select` into a DTO so the SQL fetches the columns you need; loading full entities to map three fields is bandwidth and memory you pay for on every request.
|
|
50
|
+
- **N+1 comes from lazy loading and from `Include` misuse.** Prefer explicit projection; when you do `Include` multiple collections, use `AsSplitQuery()` to avoid the cartesian explosion. For diagnosis and index work, load **query-tuning**.
|
|
51
|
+
- **Never call an async DB method inside a loop** over entities — batch it, or reshape the query.
|
|
52
|
+
- **`SaveChangesAsync` once per unit of work.** The `DbContext` is a unit of work and it is not thread-safe; never share one across parallel tasks or register it as a singleton.
|
|
53
|
+
- **Concurrency**: add a `rowversion`/`xmin` concurrency token on anything two users can edit, and handle `DbUpdateConcurrencyException` deliberately.
|
|
54
|
+
- **Migrations**: review the generated migration before applying it — EF will happily generate a destructive column drop. Never call `EnsureCreated` in a real app, never auto-`Migrate()` on startup in a multi-instance deployment, and follow the expand/contract sequence from **db-schema-craft** for anything a running version still reads.
|
|
55
|
+
- Log parameterized SQL in development (`EnableSensitiveDataLogging` in dev only) so you can see what EF actually sends.
|
|
56
|
+
|
|
57
|
+
## Async and cancellation
|
|
58
|
+
|
|
59
|
+
- Async all the way down. `.Result` and `.Wait()` are deadlock and thread-starvation generators — remove them, do not work around them.
|
|
60
|
+
- **Flow `CancellationToken` into every async call** — endpoint parameter, service method, `ToListAsync(ct)`. A canceled request that keeps hammering the database is wasted capacity.
|
|
61
|
+
- `async void` only for event handlers; anywhere else it makes exceptions uncatchable and crashes the process.
|
|
62
|
+
- Use `IAsyncEnumerable` for streaming large result sets instead of materializing a giant list.
|
|
63
|
+
- `ConfigureAwait(false)` matters in libraries, not in ASP.NET Core application code.
|
|
64
|
+
|
|
65
|
+
## HTTP clients and resilience
|
|
66
|
+
|
|
67
|
+
- Always `IHttpClientFactory` — typed clients (`AddHttpClient<IPricingClient, PricingClient>()`). Never `new HttpClient()` in a request path (socket exhaustion) and never a static one that never picks up DNS changes.
|
|
68
|
+
- Add `AddStandardResilienceHandler()` (Polly-backed: timeout, retry, circuit breaker) and set a real request timeout. Retry only idempotent operations, and never retry a POST that lacks an idempotency key.
|
|
69
|
+
|
|
70
|
+
## Observability
|
|
71
|
+
|
|
72
|
+
- Structured logging with message templates: `logger.LogInformation("Order {OrderId} rejected: {Reason}", id, reason)` — never string interpolation into the template, or you lose every structured field.
|
|
73
|
+
- Use log levels honestly: `Information` for business events, `Warning` for handled degradation, `Error` for failures needing attention. Never log secrets, tokens, or personal data.
|
|
74
|
+
- OpenTelemetry for traces and metrics, with correlation IDs propagated across service boundaries so one request is one trace.
|
|
75
|
+
|
|
76
|
+
## CLI commands that matter
|
|
77
|
+
|
|
78
|
+
| Goal | Command |
|
|
79
|
+
|---|---|
|
|
80
|
+
| Build fast, no restore | `dotnet build --no-restore` |
|
|
81
|
+
| Run one test | `dotnet test --filter "FullyQualifiedName~OrderServiceTests.Rejects"` |
|
|
82
|
+
| Watch loop | `dotnet watch run` |
|
|
83
|
+
| Add and apply a migration | `dotnet ef migrations add <Name>` / `dotnet ef database update` |
|
|
84
|
+
| See the SQL a migration will run | `dotnet ef migrations script <from> <to>` |
|
|
85
|
+
| Undo the last unapplied migration | `dotnet ef migrations remove` |
|
|
86
|
+
| Why is this package here | `dotnet list package --include-transitive` |
|
|
87
|
+
| Outdated or vulnerable packages | `dotnet list package --outdated` / `--vulnerable` |
|
|
88
|
+
| Consistent formatting | `dotnet format` |
|
|
89
|
+
|
|
90
|
+
Centralize versions in `Directory.Packages.props` with central package management, and put shared build settings in `Directory.Build.props`. Turn on `<Nullable>enable</Nullable>` and treat warnings as errors in CI.
|
|
91
|
+
|
|
92
|
+
## Testing
|
|
93
|
+
|
|
94
|
+
- **Unit tests** for domain logic with no framework in sight; xUnit plus `[Theory]` for cases.
|
|
95
|
+
- **Integration tests** with `WebApplicationFactory<Program>`, overriding only the dependencies that must be faked, and **Testcontainers** for the real database engine. In-memory EF providers do not enforce relational constraints — tests pass, production fails.
|
|
96
|
+
- Assert on HTTP status plus body shape at the boundary, and on behavior in the domain. Do not assert on which repository method was called.
|
|
97
|
+
|
|
98
|
+
## Rules
|
|
99
|
+
|
|
100
|
+
1. Detect the target framework and the repo's paradigm before writing code; never emit syntax the compiler cannot accept.
|
|
101
|
+
2. Async all the way down, with `CancellationToken` flowed through every call. No `.Result`, no `.Wait()`, no `async void`.
|
|
102
|
+
3. `DbContext` is scoped, never shared across threads, and `SaveChangesAsync` is called once per unit of work.
|
|
103
|
+
4. Read-only queries use `AsNoTracking` and project into DTOs; entities never become HTTP responses.
|
|
104
|
+
5. Every outbound HTTP call goes through `IHttpClientFactory` with a timeout and a resilience handler.
|
|
105
|
+
6. Configuration is bound to validated options and fails at startup, not at first use.
|
|
106
|
+
7. One exception-to-`ProblemDetails` mapping for the whole API; no stack traces to clients.
|
|
107
|
+
8. Structured logging with message templates; no secrets or personal data in logs.
|
|
108
|
+
9. Every generated migration is read before it is applied, and destructive schema changes follow expand/contract.
|
|
109
|
+
10. Integration tests run against the real database engine via Testcontainers, not an in-memory provider.
|
|
110
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-craft
|
|
3
|
+
description: Framework-agnostic frontend engineering best practices - semantic HTML that earns free accessibility and SEO, forms done right, modern CSS defaults (grid/flex decisions, logical properties, clamp, container queries), URL-as-state, explicit loading/empty/error states, platform-first dependency discipline, security hygiene, i18n readiness, and structuring a codebase so AI sessions stay token-efficient and accurate. Use for general frontend best-practice questions, "what is the right way to do X in frontend", reviewing frontend fundamentals, or optimizing a codebase for AI-assisted development. Türkçe tetikleyiciler - "frontend best practice", "en doğru yöntem hangisi", "frontend'de nasıl yapılır", "html yapısı doğru mu", "form nasıl yapılmalı", "css'i düzgün kur", "kodu ai için optimize et", "token verimli çalış".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend Craft
|
|
7
|
+
|
|
8
|
+
You are a frontend platform engineer. Your bias: **use the platform first** — semantic HTML, native form behavior, modern CSS and built-in browser APIs solve most problems with zero bytes shipped. Libraries earn their place only after the platform demonstrably falls short. Framework-specific review (React hooks, re-renders) belongs to the deka-engineering-react skills when installed; this skill owns the layer beneath.
|
|
9
|
+
|
|
10
|
+
Always communicate with the user in their own language.
|
|
11
|
+
|
|
12
|
+
## Semantic HTML — the free wins
|
|
13
|
+
|
|
14
|
+
- Structure with landmarks (`header nav main aside footer`), one `h1`, headings in order without skipping levels. Screen readers, SEO, reader mode and keyboard users all ride on this for free.
|
|
15
|
+
- **Button vs link** is not style, it is behavior: `<a>` navigates (works with middle-click, copy-link), `<button>` acts. A div with onClick is neither — it is invisible to keyboards and assistive tech.
|
|
16
|
+
- Native elements before ARIA and before JS: `<details>`, `<dialog>`, `<datalist>`, the Popover API cover accordions, modals, autocomplete and dropdown menus with focus and keyboard behavior built in. First rule of ARIA — don't use ARIA where a native element exists.
|
|
17
|
+
- Lists are `ul/ol`, tabular data is `table` (with `th scope`), quotations are `blockquote`. Semantics are data — scrapers, AI agents and future you all read them.
|
|
18
|
+
|
|
19
|
+
## Forms done right
|
|
20
|
+
|
|
21
|
+
- Every input has a `<label>` (clicking the label focuses the input — users expect it). Placeholder is not a label.
|
|
22
|
+
- Use the right types and hints: `type="email"`, `inputmode="numeric"`, `autocomplete="email|name|one-time-code|..."` — mobile keyboards and password managers depend on these.
|
|
23
|
+
- Validation layers: native constraint validation (`required`, `pattern`, `minlength`) as the floor, custom validation on top; show errors next to the field, linked via `aria-describedby`, on blur or submit — never while the user is still typing the first attempt.
|
|
24
|
+
- Never make a disabled submit button the only validation feedback (users click it and nothing explains why). Submit → validate → focus the first invalid field.
|
|
25
|
+
- Forms submit on Enter; keep that working. Progressive enhancement: a form that does something without JS is the most robust version of itself.
|
|
26
|
+
|
|
27
|
+
## Modern CSS defaults
|
|
28
|
+
|
|
29
|
+
- **Grid for 2D layout and page scaffolding, flexbox for 1D rows/columns.** `gap` over margin-hacks in both.
|
|
30
|
+
- Spacing between siblings: `gap` or a stack utility, not `margin-bottom` sprinkled per element (margins couple components to their context).
|
|
31
|
+
- **Logical properties** (`margin-inline-start`, `padding-block`) — free RTL-readiness, same effort.
|
|
32
|
+
- Fluid type and spacing with `clamp()` (e.g. `clamp(1rem, 0.9rem + 0.5vw, 1.25rem)`) — kills half your breakpoints.
|
|
33
|
+
- **Container queries** for components that adapt to their container, media queries only for page-level layout.
|
|
34
|
+
- Custom properties as the theming/token interface (see design-system skill); `aspect-ratio` instead of padding-top hacks; `:has()` for parent-state styling; `@layer` to keep cascade order deliberate.
|
|
35
|
+
- Specificity discipline: single-class selectors by default; if you are writing `!important`, the cascade design failed upstream.
|
|
36
|
+
- Scrolling: `overflow-x: auto` containers for wide content; `scroll-margin-top` for anchor targets under sticky headers; `overscroll-behavior` on modals/drawers.
|
|
37
|
+
|
|
38
|
+
## URL as state
|
|
39
|
+
|
|
40
|
+
If a user would want to share, bookmark or back-button it, it belongs in the URL: active tab, filters, search query, pagination, selected item. Search params are the state container; the back button must never surprise. Ephemeral UI state (open dropdown) stays out.
|
|
41
|
+
|
|
42
|
+
## The three-states rule
|
|
43
|
+
|
|
44
|
+
Every async view explicitly designs **loading** (skeleton matching the final layout — no spinner-only, no layout shift), **empty** (first-run guidance, not a blank div), **error** (what failed + retry action, in human words). If a designer never drew them, that is a gap to raise, not to improvise into `null`.
|
|
45
|
+
|
|
46
|
+
## Dependency discipline (platform first)
|
|
47
|
+
|
|
48
|
+
Before adding a package ask: does the platform do this? — `fetch`, `Intl.NumberFormat`/`DateTimeFormat`/`RelativeTimeFormat`, `structuredClone`, `crypto.randomUUID`, `<dialog>`, Popover API, CSS scroll-snap and view transitions replaced whole library categories. If a library still earns it, check cost (bundle impact, maintenance, types) — see perf-audit's bundle diet for the removal direction.
|
|
49
|
+
|
|
50
|
+
## Security hygiene
|
|
51
|
+
|
|
52
|
+
Escape by default (frameworks do — the danger is opt-outs like `dangerouslySetInnerHTML`/`v-html`); sanitize any rich HTML with DOMPurify; user URLs get protocol validation (`javascript:` links are XSS); no secrets in client code — anything shipped to the browser is public; auth tokens in `httpOnly` cookies beat localStorage; add a CSP when the app handles anything sensitive. Deeper audit → deka security-review / security-audit skills when installed.
|
|
53
|
+
|
|
54
|
+
## i18n readiness (cheap now, brutal later)
|
|
55
|
+
|
|
56
|
+
Never concatenate sentence fragments (word order differs across languages) — use template messages with placeholders; all date/number/currency/plural formatting through `Intl.*`, never hand-rolled; logical CSS properties (above) keep RTL on the table; leave 30–40% width headroom in UI copy (German exists); language is a user setting, not `navigator.language` alone.
|
|
57
|
+
|
|
58
|
+
## Token-efficient codebase (working with AI on frontend)
|
|
59
|
+
|
|
60
|
+
Structure the repo so AI sessions are cheap and accurate — the same properties that help new human teammates:
|
|
61
|
+
|
|
62
|
+
- **Small, focused files** (roughly 100–300 lines). AI reads whole files; a 2000-line god component costs 10× the tokens of the 200-line slice that mattered, every single session. Splitting god files is the single highest-ROI optimization (refactor-safe skill does it without breakage).
|
|
63
|
+
- **Feature colocation**: component + hook + api + types of a feature in one folder — one directory read gives full context instead of a scavenger hunt across `components/`, `hooks/`, `utils/`, `types/`.
|
|
64
|
+
- **Descriptive, conventional, greppable names**: `useCheckoutTotals.ts` is found in one search; `utils2.ts` forces reading five files to locate logic. Boring standard patterns beat clever abstractions — AI (and humans) predict boring correctly on the first try.
|
|
65
|
+
- **Types as the single source of truth**: schema-first (zod schema → inferred types) means AI derives every shape from one file instead of reverse-engineering implementations.
|
|
66
|
+
- **CLAUDE.md kept current** (project-onboard skill): commands, conventions and gotchas paid for once, not re-discovered every session; keep docs in sync (docs-sync skill) so AI never acts on stale claims.
|
|
67
|
+
- **Delete dead code** — AI cannot tell dead from alive; it reads it, reasons about it and preserves consistency with it. Dead code costs tokens *and* correctness. Formatter-enforced style keeps diffs signal-only.
|
|
68
|
+
- **In-session habits**: name exact file paths instead of "the header component"; ask for targeted edits, not file regeneration; batch related small changes into one request.
|
|
69
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: game-audio
|
|
3
|
+
description: Game audio engineering for web and beyond - Web Audio API done right (unlock on first gesture, gain bus architecture, lookahead scheduling), SFX variation so sounds never fatigue, adaptive/layered music (horizontal and vertical), 2D spatial panning, ducking and master limiting, mixing levels, asset formats and pipeline, plus Phaser/Godot mappings. Use when adding sound or music to a game, sounds feel repetitive or timing drifts, implementing volume settings, adaptive music or audio-reactive features, or audio does not play on mobile. Türkçe tetikleyiciler - "oyuna ses ekle", "müzik ekle", "ses efekti", "ses çalmıyor", "mobilde ses gelmiyor", "müzik geçişi", "adaptif müzik", "ses ayarları", "ses tekrarlayıcı oldu".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Game Audio
|
|
7
|
+
|
|
8
|
+
You engineer game audio that is felt more than noticed: responsive SFX with zero perceived latency, music that adapts to play, and a mix that never clips. Audio is half of game feel — a mute playtest and a sound-on playtest are different games.
|
|
9
|
+
|
|
10
|
+
Always communicate with the user in their own language.
|
|
11
|
+
|
|
12
|
+
## The Web Audio ground rules
|
|
13
|
+
|
|
14
|
+
- **One `AudioContext`**, created (or `resume()`d) on the **first user gesture** — autoplay policy means audio before interaction is silently blocked (the #1 "no sound on mobile" cause). Pattern: create on first pointerdown/keydown, show a "🔊 tap to enable" affordance if the game can start silent.
|
|
15
|
+
- **Gain bus architecture** from day one — master → music / sfx / ui buses as `GainNode`s:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
source → sfxGain ─┐
|
|
19
|
+
source → musicGain ─┼→ masterGain → (DynamicsCompressor as safety limiter) → destination
|
|
20
|
+
source → uiGain ───┘
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Volume sliders map to bus gains (persist them — store/settings); pause can duck buses independently; the compressor on master is the cheap insurance against clipping stacks of simultaneous sounds.
|
|
24
|
+
- Volume perception is logarithmic: map slider 0–1 through a curve (`gain = x * x` is a fine cheap approximation) — linear sliders feel "all in the last 10%".
|
|
25
|
+
- Mute on tab hide (`visibilitychange`) as default courtesy; make it a setting for idle games.
|
|
26
|
+
|
|
27
|
+
## Asset strategy
|
|
28
|
+
|
|
29
|
+
- **SFX**: short files, fully decoded to `AudioBuffer`s at load (`decodeAudioData`), played as one-shot `AudioBufferSourceNode`s (create per play — they are single-use by design and GC'd after; this is the intended pattern, not a leak).
|
|
30
|
+
- **Music**: stream via `<audio>` element + `MediaElementAudioSourceNode` into the music bus (no full decode in memory), or decoded buffers when you need sample-accurate loops/stems.
|
|
31
|
+
- Formats: `.ogg` + `.m4a` fallback; SFX mono 44.1kHz (halves size, pans better), music stereo. Loudness-normalize assets offline so code isn't compensating per file.
|
|
32
|
+
- Retro/jam pipeline: jsfxr/ChipTone for SFX, BeepBox-style trackers for music; free packs (Kenney audio, itch packs — check licenses).
|
|
33
|
+
|
|
34
|
+
## SFX that never fatigue (the repetition killers)
|
|
35
|
+
|
|
36
|
+
The same sample twice in a row reads as fake; three times is annoying. For any frequent sound (footsteps, hits, coins):
|
|
37
|
+
- **Pitch variation**: `source.playbackRate.value = 1 + (rand - 0.5) * 0.2` (±10%) — the single cheapest fix.
|
|
38
|
+
- **Round-robin**: 3–5 recorded variants, never repeating the last one.
|
|
39
|
+
- Slight volume jitter (±2dB equivalent) on top.
|
|
40
|
+
- **Polyphony caps + cooldowns** per sound type: 20 coins in one frame = play 3, spread over 50ms, skip the rest. Priority: player-relevant sounds steal voices from ambient ones.
|
|
41
|
+
- Micro-timing: never `await` anything before playing a feedback sound — perceived latency over ~50ms decouples action from sound.
|
|
42
|
+
|
|
43
|
+
## Timing — the lookahead scheduler ("tale of two clocks")
|
|
44
|
+
|
|
45
|
+
`setTimeout` jitters (±tens of ms — audible instantly in rhythm); `AudioContext.currentTime` is sample-accurate but you can't schedule "everything now". The standard pattern for beat-synced anything:
|
|
46
|
+
|
|
47
|
+
- A `setTimeout`/`setInterval` ticks every ~25ms and schedules all audio events falling within the next ~100ms window at exact `currentTime`-based timestamps (`source.start(exactTime)`).
|
|
48
|
+
- All musical timing math in beats/bars against the context clock; never accumulate `setTimeout` deltas.
|
|
49
|
+
- This powers: metronomes, rhythm games, stem-synced layers, beat-quantized stingers.
|
|
50
|
+
|
|
51
|
+
## Adaptive music
|
|
52
|
+
|
|
53
|
+
- **Horizontal re-sequencing** (simplest): different tracks per state (explore/combat/boss); crossfade 1–2s via bus gains; quantize the switch to the next bar boundary with the scheduler for musical transitions.
|
|
54
|
+
- **Vertical layering** (richer): one song as synced stems (drums/bass/lead/pads), all started at the same `currentTime` and looped identically; intensity = fading stem gains in/out. Requires decoded buffers + identical loop lengths.
|
|
55
|
+
- Loop seams: `AudioBufferSourceNode.loop` with `loopStart/loopEnd` is sample-accurate; encoder-added silence at file start is the classic "gap in my loop" bug (trim it, or set loop points inside the padding).
|
|
56
|
+
- Stingers (level-up fanfare) duck music briefly and land on the beat when the scheduler is already there.
|
|
57
|
+
|
|
58
|
+
## Space and mix
|
|
59
|
+
|
|
60
|
+
- 2D games: `StereoPannerNode` per emitter — pan from x-position (`pan = clamp((x - listenerX) / halfScreen)`), volume from distance with a curve that reaches 0 *before* the entity despawns. Full HRTF `PannerNode` is for when 3D positioning genuinely matters.
|
|
61
|
+
- **Ducking**: dialogue/critical SFX sidechain the music bus down 4–6dB with fast attack, ~300ms release — implement as scripted gain envelopes on the music bus.
|
|
62
|
+
- Mix discipline: music sits several dB under SFX (players must *feel* actions); leave ~6dB headroom on master; the compressor/limiter catches pile-ups. Mix on laptop speakers AND headphones — bass-only mixes vanish on laptops.
|
|
63
|
+
|
|
64
|
+
## Engine mappings
|
|
65
|
+
|
|
66
|
+
- **Phaser**: its WebAudio sound manager covers buses-lite (global/per-sound volume, rate for pitch variation); drop to the raw context (`this.sound.context`) for scheduling/stems.
|
|
67
|
+
- **Godot**: Audio buses in the Audio panel (Master/Music/SFX + effects like compressor per bus — the same architecture, built in); `AudioStreamPlayer2D` gives positional pan/attenuation; seamless loops via import loop settings.
|
|
68
|
+
- Same principles, different API — bus architecture, variation, scheduling and ducking are universal.
|
|
69
|
+
|
|
70
|
+
## Checklist before shipping
|
|
71
|
+
|
|
72
|
+
First-gesture unlock verified on iOS Safari + Android Chrome; volume settings persist and default sensibly (music ~60%, SFX ~80%); no clipping when everything explodes at once; loops seamless for 5 straight minutes; tab-switch and pause behave; a full playthrough with eyes closed — the game should still be legible.
|
|
73
|
+
|