Architecture
Overview
Feel Your Protocol is a Vue 3 application built with Vite. The core idea is simple: each Ethereum protocol change gets its own interactive widget that runs real library code in the browser.
Tech Stack
- Vue 3 with Composition API and
<script setup> - Vite for development and production builds
- Tailwind CSS v4 for styling
- Vue Router with route-level code splitting
- VitePress for documentation
- Vitest + Vue Test Utils for unit testing
- Cypress for E2E testing
- Heroicons for icons (
@heroicons/vue)
Content Model
Content is organized around three taxonomies:
Explorations
The core content unit. Each exploration represents an interactive widget for a protocol change — EIPs, ERCs, or research topics. Explorations live in src/explorations/, one folder per exploration:
src/explorations/eip-7883/
├── info.ts # Metadata: id, title, path, topic, timeline, tags, poweredBy, …
├── MyC.vue # The interactive widget
└── examples.ts # Example presets for the widgetEach info.ts exports a const INFO object typed as Exploration. The REGISTRY.ts imports all INFO constants and assembles them into the EXPLORATIONS dictionary. The router reads from this dictionary to automatically create routes — no manual route registration needed.
Topics
Topics are the high-level strategic pillars that group explorations by theme. Each exploration belongs to exactly one topic via the topic field in its info.ts. Topics are defined in src/explorations/TOPICS.ts.
Topics are a static, curated set — they are not meant to be added as part of regular contributions. The current topics are:
| ID | Title | Description |
|---|---|---|
scaling | Scaling | Data availability, throughput, and L2 enablement |
privacy | Privacy | ZK-proofs, homomorphic encryption, private mempools |
ux | UX | Account abstraction, wallet infrastructure, signature schemes |
security | Security | Validator incentives, cryptographic agility, MEV mitigations |
robustness | Robustness | Gas cost accuracy, EVM semantics hardening, spec clarity |
interoperability | Interoperability | Cross-chain standards, bridge infrastructure, signature scheme support |
When adding an exploration, pick the topic that best reflects the primary concern of the protocol change.
Timeline
Timeline is a taxonomy that combines two dimensions: how settled an idea is (from early mention to finalized spec) and where it sits relative to mainnet Ethereum (specific hardfork vs. general readiness stage). Each exploration belongs to exactly one timeline entry via the timeline field in its info.ts. Timeline entries are defined in src/explorations/TIMELINE.ts.
Hardfork entries are named after their Ethereum community event city of origin (e.g. "Fusaka" from Osaka, "Glamsterdam" from Amsterdam). The non-hardfork categories (Ready, Research, Ideas) are static. New hardfork entries can be added as Ethereum's upgrade schedule evolves.
Tags
Tags enrich navigation by adding broader Ethereum technical concepts, protocol-relevant areas, or general technology topics from the blockchain space. Each exploration can have up to 3–4 tags. Tags are defined as a TypeScript enum in src/explorations/TAGS.ts.
Tags grow with contributions — unlike topics and timeline, new tags can be proposed when adding an exploration. They must follow these rules:
| Rule | Example |
|---|---|
| Must be reusable beyond a single exploration | EVM ✅ — EIP-7883 ❌ |
| Short form preferred | EVM ✅ — Ethereum Virtual Machine ❌ |
| No redundancy with existing tags | Gas Costs exists → don't add Gas |
| When in doubt, choose the more generic concept | Gas Costs ✅ — Gas Increases ❌ |
Format: Enum keys use CamelCase (GasCosts), all-caps for abbreviations (EVM). Members must be sorted alphabetically (enforced by lint).
E-Components
E-Components are reusable Ethereum-specific components that encapsulate common patterns across explorations. They live in src/eComponents/ and follow a naming convention: folder and component names are post-fixed with EC.
The first E-Component is precompileInterfaceEC, which provides a complete precompile exploration interface — input parsing, hardfork comparison, result display — as a single component backed by a composable:
src/eComponents/precompileInterfaceEC/
├── PrecompileInterfaceEC.vue # Full-featured precompile exploration template
├── PrecompileInterfaceResultEC.vue # Result display (pre/post hardfork comparison)
├── PrecompileValueInputEC.vue # Value input with byte length validation
├── usePrecompileState.ts # Composable: all state and logic
├── types.ts # PrecompileConfig and PrecompileValueDef interfaces
└── run.ts # EVM precompile execution utilityUsing the Precompile Interface E-Component, a precompile exploration widget can be as short as 30 lines — just a config object and a single component tag. See Using E-Components for details.
UI Components
Generic UI components live in src/eComponents/ui/ alongside the E-Components they serve. These are reusable building blocks available for any exploration or E-Component:
| Component | Purpose |
|---|---|
ExamplesUIC | Example selector dropdown |
HexDataInputUIC | Hex data input textarea |
ResultBoxUIC | Result display box with title, info text, and error text |
ActionButtonUIC | Async action button with loading state and tooltip |
ButtonUIC | Icon button with tooltip |
TooltipUIC | CSS tooltip wrapper |
Import them from @/eComponents/ui/:
import ResultBoxUIC from '@/eComponents/ui/resultBox/ResultBoxUIC.vue'
import ExamplesUIC from '@/eComponents/ui/ExamplesUIC.vue'Key Design Decisions
Folder-per-Exploration
Each exploration is fully self-contained in its own folder. This means:
- Contributors can focus on a single folder
- Adding a new exploration requires creating a folder and adding one import to
REGISTRY.ts - Each exploration's dependencies are isolated
Dynamic Views
There are no static per-exploration or per-topic view files. Instead:
ExplorationView.vuedynamically loads the correctMyC.vueusingimport.meta.glob()anddefineAsyncComponent()based on the route nameTopicView.vuedynamically lists all explorations belonging to a topic (or all explorations on the/allroute), with URL query parameter filtering bytimelineandtagHomeView.vuedynamically renders all active topics, a tag cloud, and a timeline navigation
Route-Level Code Splitting
Each exploration is a separate chunk that is loaded on demand. Users only download the libraries needed for the page they visit. This is achieved via import.meta.glob() for lazy loading:
const componentModules = import.meta.glob('../explorations/*/MyC.vue')
const ExplorationComponent = defineAsyncComponent(
componentModules[`../explorations/${explorationId}/MyC.vue`]
)Testing Strategy
The project uses a hybrid testing approach:
- Unit tests (Vitest + Vue Test Utils) for component rendering, content verification, and UI logic — fast and focused
- E2E tests (Cypress) as lean smoke tests for critical navigation flows and page-level integration
Unit tests live alongside their components in __tests__/ folders. E2E tests are consolidated in cypress/e2e/.