my-idx-app/
├── sim.toml                       # App configuration
├── abis/                          # JSON ABIs for the contracts you want to index
├── apis/                          # TypeScript/Edge runtime APIs (Node.js project)
│   ├── drizzle.config.ts          # Drizzle ORM configuration
│   └── src/                       # API source code
│       ├── index.ts               # Main API entry point
│       └── db/                    # Database schema and utilities
│           └── schema/            # Auto-generated database schema
│               └── Listener.ts    # Schema generated from listener events
└── listeners/                     # Foundry project for indexing logic
    ├── src/
    │   └── Main.sol               # Triggers contract and main listener logic
    ├── test/
    │   └── Main.t.sol             # Unit tests for your listener
    └── lib/
        ├── sim-idx-sol/           # Core Sim IDX framework (DSL, context, helpers)
        └── sim-idx-generated/     # Code generated from the ABIs you add

Running sim init creates a new Sim IDX app with the folder structure shown above. The following sections explain each folder’s purpose and contents in detail.

App Folder Structure

sim.toml

The sim.toml file is your app’s main configuration file. It contains your app’s name and a [listeners] table for configuring code generation.

[app]
name = "my-test"

The name field is used internally by Sim IDX for resource naming and deployment.

[listeners]
codegen_naming_convention = "plain"

The codegen_naming_convention field in the [listeners] table controls how function and type names are generated from your ABIs. This manages potential name conflicts when you index multiple contracts. It supports two values:

  • "plain" (Default): Generates clean names without any prefixes (e.g., onSwapFunction). This is the most common setting, especially when you split logic for different ABIs into separate listener contracts.
  • "abi_prefix": Prefixes generated names with the ABI’s name (e.g., ABI1$onSwapFunction). Use this option to prevent compilation errors when a single listener contract must handle functions with the same name from two different ABIs.

abis/

The abis/ folder contains JSON ABI files of smart contracts you want to index. The sample app includes abis/UniswapV3Factory.json for the Uniswap V3 Factory contract.

When you add a new ABI with the sim abi add CLI command, it automatically generates Solidity bindings in listeners/lib/sim-idx-generated/.

apis/

The apis/ folder is a complete Node.js project that provides TypeScript API endpoints running on the Cloudflare Workers Edge runtime.

The src/index.ts file defines your HTTP routes, while src/db/schema/Listener.ts is produced by sim build and exposes your listener-generated tables through Drizzle ORM for type-safe queries.

listeners/

The listeners/ folder is a Foundry project that contains everything related to on-chain indexing. The Triggers contract must be defined in src/Main.sol, but handler logic can be implemented in one or more listener contracts, which can have any name and be defined across multiple .sol files in the src/ directory. Unit tests live under the test/ directory. Foundry will discover any file ending in .t.sol, so you can add as many unit-test files as you need (e.g., Main.t.sol, SwapHandlers.t.sol, etc.).

During sim build, the framework inserts core helpers into lib/sim-idx-sol/ and writes ABI-specific bindings into lib/sim-idx-generated/. These generated files should not be edited directly.

Development Workflow

Here’s how these folders work together:

  1. Add Contract ABIabis/YourContract.json
  2. Generate Bindingssim abi add creates Solidity bindings
  3. Extend Listener → Implement handlers in listeners/src/
  4. Test Logic → Write tests in listeners/test/ (e.g., any *.t.sol files)
  5. Build APIs → Use generated schema in apis/src/ to query your data
  6. Deploy → Push your changes to a branch (or main) and follow the steps in the deployment guide to promote them to a live environment