towns-protocol/towns/design-philosophy
Claude Code and agent skill by towns-protocol/towns
- community
Checking that the SKILL.md file is still in the repository.
Deep design principles for Towns Protocol smart contracts. Use when creating new facets, major refactoring, reviewing architecture decisions, or designing new abstractions.
Install
npx vskill@latest install towns-protocol/towns/design-philosophySKILL.md
Design Philosophy for Towns Protocol
When to Use This Skill
- Creating new facets or contracts
- Major refactoring work
- Reviewing architectural decisions
- Designing new abstractions or APIs
- Evaluating trade-offs between approaches
- Identifying and fixing design smells
Reference Examples
| Pattern | Example Location | |
|---|---|---|
| Modern Mod + Facet | src/account/facets/hub/ | |
| Domain registration | src/domains/facets/registrar/ |
Foundational Philosophy: Designing for Simplicity
The primary objective in Towns Protocol development is to minimize complexity—anything related to the software structure that makes it hard to understand or modify. In a system as sophisticated as this (with Diamond Pattern upgrades, cross-chain validation, and role-based permissions), managing complexity is critical.
Core Principles
- Strategic Programming: Invest time in design upfront rather than quick tactical fixes. The long-term structure matters more than short-term convenience. Before adding a new facet or feature, design the abstraction carefully.
- Goal: Obviousness: Code should be obvious. Developers should quickly understand existing code and confidently make changes. If understanding a facet requires reading multiple files and tracing dependencies, the abstraction is leaking.
- Eliminate Dependencies: Minimize coupling between modules. A change in one facet should rarely require changes in others. Use events and interfaces to decouple components.
- Eliminate Obscurity: Name entities precisely. Document non-obvious behavior. If a function's purpose isn't clear from its signature and name, the design needs improvement.
- Avoid Change Amplification: Small logical changes should not require modifying many files. If adding a permission type requires touching 10+ contracts, the architecture has high coupling.
- Reduce Cognitive Load: Developers should not need extensive context to complete tasks. A facet's interface should be self-documenting. Storage layouts should be isolated.
- No Unknown Unknowns: It should be obvious which code must be modified for a given change. Clear module boundaries and interfaces prevent hidden dependencies.
Design Philosophy for Solidity Modules
In this codebase, "modules" refers to contracts, facets, libraries, and functions. Apply these principles at all levels.
Module Design: Building Deep, Encapsulated Contracts
1. Strive for Deep Modules
Contracts and facets should be deep: they provide powerful functionality through a simple interface.
✅ Deep Module Example (Good):
❌ Shallow Module Example (Bad):
Guidelines for Deep Modules:
- Simple Interface, Complex Implementation: External functions should be minimal and clear. Internal complexity should be hidden in the Mod library.
- General Purpose Design: Design facets to be somewhat general-purpose. Separate specialized logic from general mechanisms.
- Powerful Abstractions: A single function like
register()can hide validation, fee charging, registry interaction, and resolver setup.
2. Information Hiding and Encapsulation
Information hiding is the most crucial technique for deep facets. In the Diamond Pattern, this is especially important because facets share a proxy but should minimize shared knowledge.
Prevent Information Leakage:
- ❌ Leakage: If the storage layout details of one facet must be known by another facet, that's leakage.
- ✅ Solution: Each facet has its own isolated storage slot via the Mod library. Facets communicate through well-defined interfaces.
Example of Information Hiding (Good):
Example of Information Leakage (Bad):
3. Avoid Temporal Decomposition
Do not structure code solely based on the order of operations. This often creates information leakage and tight coupling.
❌ Temporal Decomposition (Bad):
✅ Knowledge-Based Organization (Good):
4. Different Layers, Different Abstractions
When tracing an operation through layers, the abstraction should change at each boundary.
Example of Proper Layering:
Each layer has a distinct vocabulary and level of abstraction. External API uses business terms (register, label). Mod uses domain terms (subdomain, registry). Low-level uses ENS terms (namehash, resolver).
5. Pull Complexity Downward
When encountering unavoidable complexity, resolve it within the module rather than pushing it onto callers.
❌ Pushing Complexity Up (Bad):
✅ Pulling Complexity Down (Good):
Code Clarity: Naming, Comments, and Error Handling
1. Naming Conventions
Names are a form of abstraction and documentation. They create a mental model.
Precision and Image:
- Names must be precise, unambiguous, and intuitive
- The name should convey what the entity is and is not
- Avoid vague names like
manager,handler,helper,utils
Examples:
❌ Vague Names:
manager→ UseL2RegistrarMod(handles domain registration logic)check()→ UseonlySmartAccount()(validates caller is smart account)process()→ UsechargeFee()(charges registration fee)data→ UseLayout(storage layout for the facet)
Consistency:
- Use consistent terminology across the codebase
- If you call it a "label" in one place, don't call it a "subdomain" in the interface
- Follow the pattern:
FeatureMod.sol,FeatureFacet.sol,IFeature.sol
Red Flag: If you struggle to find a simple, precise name, the entity likely has an unclear purpose or poor design.
2. Strategic Use of Comments
Comments capture knowledge that cannot be represented in code. They are fundamental to abstraction.
What to Comment:
- The What (Abstraction): What does this function/contract provide at a high level?
- The Why (Rationale): Why was this design chosen? What problem does it solve?
- The Non-Obvious: What cannot be inferred from the code itself?
What NOT to Comment:
- The How (Implementation): The code already shows how it works
- Redundant Information: Don't repeat what's in the function name
Interface Documentation (NatSpec):
Every public/external function must have NatSpec that defines the abstraction:
Implementation Comments:
Use implementation comments sparingly for non-obvious logic:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingpackages/contracts/.cursor/skills/design-philosophy/SKILL.md
Popularity
- Repository stars
- 66
- Repository forks
- 62
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 18 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/towns-protocol/towns/design-philosophy)