ECOSYSTEM.md: Your Project's Single Source of Truth

Introduction

If you've worked on any project with multiple platforms or multiple developers, you've experienced the chaos of inconsistent data models. One developer calls it userId, another writes user_id, and the iOS app uses userID. Three names for the same field. Three opportunities for bugs.

Claude Code makes this worse if left unchecked. Without a specification to follow, Claude will confidently generate code using whatever field name seems reasonable in the moment. It might use userId in one file and user_id in another, creating drift that compounds over time until your codebase becomes a minefield of subtle inconsistencies.

ECOSYSTEM.md is the solution. It's a single source of truth that defines your data models, API contracts, and naming conventions. When Claude reads ECOSYSTEM.md before writing code, it follows your exact specifications instead of guessing. The field is userId everywhere, on every platform, in every file, because that's what the spec says.

The Problem It Solves

Schema drift is the silent killer of multi-platform projects. It doesn't announce itself with error messages or test failures. It hides in the gaps between platforms, waiting to break production.

Field Naming Inconsistency

The classic example: userId vs user_id vs userID. Same data, different names. Your iOS app sends userId, your web app expects user_id, and suddenly user profiles don't load. You spend hours debugging what turns out to be a single character difference.

Type Mismatches

iOS stores a count as an integer. The web app treats it as a string. Firebase stores it as a number. When data flows between platforms, JavaScript's type coercion might save you, or it might not. "5" + 1 equals "51", not 6.

Enum Inconsistencies

One platform uses 'active' and 'inactive'. Another uses 'enabled' and 'disabled'. A third uses 0 and 1. They all mean the same thing, but good luck writing code that handles all three.

No Single Reference

When a developer needs to know the correct field name, where do they look? The iOS models? The web services? The Firebase schema? Each platform has its own truth, and they don't always agree.

Claude Inventing Field Names

Ask Claude to add a "last login" field without a spec, and you might get lastLogin, last_login, lastLoginAt, or lastLoggedIn. All reasonable. All different. All creating future bugs.

The Real Cost: These inconsistencies don't break development. They break production. Platform A sends data that Platform B can't read. Users see blank screens. Data gets lost. And the bug is invisible in testing because each platform works fine in isolation.

What to Include in ECOSYSTEM.md

A well-structured ECOSYSTEM.md contains everything a developer (or Claude) needs to work with your data correctly.

Data Models

Define your models using TypeScript interfaces as a universal notation. Even if you're not using TypeScript, the interface syntax is clear and unambiguous.

TypeScript
interface User {
  userId: string;           // Firebase Auth UID
  email: string;
  displayName: string;
  createdAt: Timestamp;     // Firebase Timestamp
  updatedAt: Timestamp;
  isActive: boolean;
  role: UserRole;
}

Enum Definitions

String unions are clearer than numeric enums and survive serialization.

TypeScript
type UserRole = 'admin' | 'member' | 'guest';
type TaskStatus = 'draft' | 'active' | 'completed' | 'archived';
type Priority = 'low' | 'medium' | 'high' | 'urgent';

API Contracts

Document what goes in and what comes out of every endpoint.

TypeScript
// POST /api/users
Request: { email: string, displayName: string }
Response: { success: boolean, data?: User, error?: string }

// GET /api/users/:userId
Response: { success: boolean, data?: User, error?: string }

// PATCH /api/users/:userId
Request: Partial<User>
Response: { success: boolean, data?: User, error?: string }

Naming Conventions

Explicit rules eliminate ambiguity.

  • camelCase for all field names (userId, not user_id)
  • Boolean fields prefixed with is or has (isActive, hasAccess)
  • Timestamps end with At (createdAt, updatedAt, deletedAt)
  • IDs end with Id (userId, taskId, commentId)
  • Counts end with Count (taskCount, memberCount)

Tip: Platform-specific variations are acceptable for truly platform-specific fields. iOS might have deviceToken that web doesn't need. But any shared data must use identical names.

Example ECOSYSTEM.md

Here's a realistic example for a task management application. Use this as a template for your own projects.

ECOSYSTEM.md
# TaskFlow - Data Ecosystem

## Naming Conventions
- All fields: camelCase
- Booleans: prefix with `is` or `has`
- Timestamps: suffix with `At`
- IDs: suffix with `Id`

## Data Models

### User
interface User {
  userId: string;           // Firebase Auth UID
  email: string;
  displayName: string;
  avatarUrl: string | null;
  createdAt: Timestamp;
  updatedAt: Timestamp;
  isActive: boolean;
  role: UserRole;
}

type UserRole = 'admin' | 'member' | 'guest';

### Task
interface Task {
  taskId: string;
  title: string;
  description: string;
  status: TaskStatus;
  priority: Priority;
  assigneeId: string | null;  // References User.userId
  creatorId: string;          // References User.userId
  dueAt: Timestamp | null;
  createdAt: Timestamp;
  updatedAt: Timestamp;
  isArchived: boolean;
  tagIds: string[];           // References Tag.tagId
}

type TaskStatus = 'draft' | 'active' | 'completed' | 'archived';
type Priority = 'low' | 'medium' | 'high' | 'urgent';

### Comment
interface Comment {
  commentId: string;
  taskId: string;             // References Task.taskId
  authorId: string;           // References User.userId
  content: string;
  createdAt: Timestamp;
  updatedAt: Timestamp;
  isEdited: boolean;
}

## API Contracts

### Users
POST   /api/users          - Create user
GET    /api/users/:userId  - Get user by ID
PATCH  /api/users/:userId  - Update user

### Tasks
POST   /api/tasks          - Create task
GET    /api/tasks          - List tasks (with filters)
GET    /api/tasks/:taskId  - Get task by ID
PATCH  /api/tasks/:taskId  - Update task
DELETE /api/tasks/:taskId  - Archive task (soft delete)

### Standard Response Format
All endpoints return:
{ success: boolean, data?: T, error?: string }

How Claude Uses It

When Claude Code starts a session in your project, it reads ECOSYSTEM.md along with CLAUDE.md. This gives Claude a complete picture of your data structures before it writes a single line of code.

Reference Before Generating

When you ask Claude to add a feature involving data models, it checks ECOSYSTEM.md first. If you say "add a completed date to tasks," Claude sees that timestamps end with At and creates completedAt, not completedDate or dateCompleted.

Asking Instead of Guessing

If a field isn't defined in ECOSYSTEM.md, Claude knows to ask. "I don't see a field for tracking task priority in ECOSYSTEM.md. Should I add it, or is this handled differently?" This catches specification gaps before they become code problems.

Validation

Claude can flag code that violates the spec. If existing code uses user_id but ECOSYSTEM.md specifies userId, Claude will point out the inconsistency and offer to fix it.

Example Workflow: You ask Claude to add a "completed" field to tasks. Claude checks ECOSYSTEM.md, sees TaskStatus already includes 'completed' as a valid status, and suggests using that instead of adding a boolean. The spec prevents redundant fields.

Keeping It Updated

An outdated ECOSYSTEM.md is worse than no ECOSYSTEM.md. It actively misleads both developers and Claude. Here's how to keep it current.

Spec-First Development

Update ECOSYSTEM.md before implementing features. If you're adding a new model or field, add it to the spec first. This forces you to think through the data structure before writing code, and ensures Claude has the right information from the start.

Include in Code Review

Any PR that changes data models should include corresponding ECOSYSTEM.md updates. Make this a checklist item in your PR template.

Version Your Specs

If you have external API consumers, add version numbers to your spec. Document breaking changes and migration paths.

Markdown
## Version History
- v2.1.0 (2025-01-15): Added Comment model
- v2.0.0 (2025-01-01): Changed userId from number to string (BREAKING)
- v1.5.0 (2024-12-01): Added priority field to Task

Quarterly Reviews

Schedule time to review ECOSYSTEM.md every quarter. Remove deprecated fields, update outdated descriptions, and ensure the spec matches your actual codebase.

Multi-Platform Benefits

ECOSYSTEM.md shines brightest in multi-platform projects. When iOS, Web, and Firebase all read the same specification, entire categories of bugs disappear.

One Truth, All Platforms

No more asking "which codebase has the correct field name?" The answer is always ECOSYSTEM.md. iOS developers, web developers, and backend developers all reference the same document.

Faster Onboarding

New team members can understand your entire data model by reading one file. They don't need to reverse-engineer schemas from multiple codebases or ask colleagues which naming convention is correct.

Consistent Claude Output

Whether you're working on iOS, Web, or Firebase, Claude generates code that uses the same field names. A task created on iOS can be read on Web without any translation layer.

Reduced Integration Bugs

Teams report 80% fewer integration bugs after adopting ECOSYSTEM.md. The bugs that used to appear when Platform A talked to Platform B simply don't happen when both platforms follow the same spec.

Real Impact: One team spent two days debugging why user avatars showed on iOS but not Web. The iOS app sent avatarUrl, Web expected avatar_url. With ECOSYSTEM.md, this bug would have been impossible.

Conclusion

ECOSYSTEM.md transforms Claude from a creative writer into a disciplined team member who follows specifications exactly. Instead of guessing field names and data structures, Claude references your documented standards and produces consistent code every time.

The thirty minutes you spend defining your data models upfront saves hours of debugging integration issues later. Every field name decision you make once in ECOSYSTEM.md is a decision you never have to make again.

Start simple. Define your core models: User, your main domain object, and any shared types. Add naming conventions and API contracts. Expand the spec as your project grows. Review it regularly to keep it current.

Your future self, your team members, and Claude will all thank you for taking the time to establish a single source of truth.

Want Production-Ready Templates?

Claude Architect includes battle-tested ECOSYSTEM.md templates for common project types, plus validation scripts that verify your code matches your specs.

Join the Waitlist