Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 64 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ Skip the hard choice between fronting API costs, high-friction BYOK flows, or bu

Building AI apps forces you to pick your poison:

| Approach | Developer Cost | User Experience | Revenue Model |
|----------|---------------|-----------------|---------------|
| **BYOK** | None (but no revenue) | Complex key management | None |
| **Dev API Key** | Unpredictable burn rate | Simple | Need metering + billing |
| **Bill End Users** | Weeks building infra | Simple | Auth + Stripe + metering |
| Approach | Developer Cost | User Experience | Revenue Model |
| ------------------ | ----------------------- | ---------------------- | ------------------------ |
| **BYOK** | None (but no revenue) | Complex key management | None |
| **Dev API Key** | Unpredictable burn rate | Simple | Need metering + billing |
| **Bill End Users** | Weeks building infra | Simple | Auth + Stripe + metering |

Echo eliminates all three problems.

Expand All @@ -38,6 +38,7 @@ Echo eliminates all three problems.
Replace your AI SDK imports with Echo. Users authenticate once, get a balance, and pay for their own usage. You set a markup and earn revenue automatically.

**Before:**

```typescript
// Option 1: Front costs yourself
import { openai } from '@ai-sdk/openai';
Expand All @@ -51,15 +52,16 @@ const response = await generateText({
```

**After:**

```typescript
// Users pay, you earn markup, zero infrastructure
import { useEchoModelProviders } from '@merit-systems/echo-react-sdk';
import { generateText } from 'ai';

const { openai } = useEchoModelProviders();
const response = await generateText({
model: openai('gpt-5'),
prompt: '...'
const response = await generateText({
model: openai('gpt-5'),
prompt: '...',
});
```

Expand Down Expand Up @@ -116,7 +118,58 @@ Or run `npx echo-start my-app` to choose interactively.

# Development

Fill out `packages/app/control/.env` and `packages/app/server/.env`. Then...
## Prerequisites

Before running Echo locally, make sure you have:

- **Node.js 18+** - [Download here](https://nodejs.org/)
- **pnpm** - Will be installed automatically by the setup script
- **Docker Desktop** - [Download here](https://www.docker.com/products/docker-desktop/)

## Quick Setup

```bash
git clone https://github.com/Merit-Systems/echo.git
cd echo
./setup.sh
pnpm dev
```

The setup script handles environment configuration and dependency installation.

## Manual Setup

1. Install dependencies:

- `pnpm i`
- `pnpm dev`
```bash
npm install -g pnpm
pnpm install
```

2. Start Docker Desktop

3. Create `.env` files with required variables (see `packages/app/control/src/env.ts` for full list)

4. Run `pnpm dev`

## Services

- Echo Control: http://localhost:3000
- Echo Server: http://localhost:3070
- PostgreSQL: localhost:5469

## Troubleshooting

**Docker not running**: Start Docker Desktop

**Port conflicts**: Change ports in `.env` files

**Database issues**: Reset with `docker-compose -f packages/app/control/docker-local-db.yml down -v`

## Development Commands

```bash
pnpm dev # Start all services
pnpm test:unit # Run unit tests
pnpm format # Format all code
```
90 changes: 12 additions & 78 deletions packages/app/control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,53 +41,21 @@ A comprehensive Next.js application for managing Echo applications, API keys, an
- **Payments**: Stripe (mocked)
- **TypeScript**: Full type safety

## Setup Instructions
## Quick Setup

### Prerequisites
From the root directory:

- Node.js 18+
- PostgreSQL database
- pnpm

### Installation

1. **Clone and navigate to the project**:

```bash
cd echo-control
```

2. **Install dependencies**:

```bash
pnpm install
```

3. **Set up the database**:

```bash
# Copy the example environment file
cp .env.example .env

# Update DATABASE_URL in .env with your PostgreSQL connection string
# Example: DATABASE_URL="postgresql://username:password@localhost:5469/echo_control"
```

4. **Run database migrations**:

```bash
npx prisma generate
npx prisma db push
```

5. **Start the development server**:
```bash
./setup.sh
pnpm dev
```

```bash
pnpm run dev
```
## Manual Setup

6. **Open the application**:
Visit [http://localhost:3000](http://localhost:3000)
1. Install dependencies: `pnpm install`
2. Start Docker Desktop
3. Create `.env` file with required variables (see `src/env.ts`)
4. Run `pnpm dev`

## Environment Variables

Expand All @@ -107,30 +75,6 @@ NEXTAUTH_URL="http://localhost:3000"
API_KEY_PREFIX="echo_"
```

## Features Overview

### Dashboard

- View all Echo applications
- Quick balance overview
- Create new applications
- Generate payment links

### App Details

- Comprehensive usage analytics
- API key management
- Transaction history
- Model-specific usage breakdown
- Direct Stripe integration

### Balance Management

- Real-time balance calculation
- Payment history
- Admin controls for balance adjustments
- Stripe payment integration

## Development

### Running Tests
Expand Down Expand Up @@ -159,14 +103,4 @@ pnpm run build
pnpm start
```

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Test thoroughly
5. Submit a pull request

## License

This project is licensed under the MIT License.
Visit [http://localhost:3000](http://localhost:3000)
122 changes: 122 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/bin/bash

echo "Setting up Echo for local development..."

# Check for pnpm
if ! command -v pnpm &> /dev/null; then
echo "Installing pnpm..."
npm install -g pnpm
if [ $? -ne 0 ]; then
echo "Failed to install pnpm. Please install manually: npm install -g pnpm"
exit 1
fi
fi

# Check for Docker
if ! command -v docker &> /dev/null; then
echo "Docker not found. Please install Docker Desktop: https://www.docker.com/products/docker-desktop/"
exit 1
fi

if ! docker info &> /dev/null; then
echo "Docker not running. Please start Docker Desktop."
exit 1
fi

echo "Installing dependencies..."
pnpm install
if [ $? -ne 0 ]; then
echo "Failed to install dependencies."
exit 1
fi

echo "Setting up environment files..."

# Control .env
if [ ! -f "packages/app/control/.env" ]; then
echo "Creating control .env file..."
touch packages/app/control/.env

# Generate AUTH_SECRET and add required variables
AUTH_SECRET=$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")
cat > packages/app/control/.env << EOF
# ----------
# Application
# ----------

ECHO_CONTROL_APP_BASE_URL="http://localhost:3000"
API_KEY_PREFIX="echo_"

# ----------
# Database
# ----------

DATABASE_URL="postgresql://echo_user:echo_password@localhost:5469/echo_control_v2?schema=public"

# ----------
# AUTH
# ----------

AUTH_SECRET=$AUTH_SECRET
AUTH_GOOGLE_ID=placeholder_google_id
AUTH_GOOGLE_SECRET=placeholder_google_secret
AUTH_GITHUB_ID=placeholder_github_id
AUTH_GITHUB_SECRET=placeholder_github_secret
AUTH_RESEND_KEY=placeholder_resend_key
[email protected]

# ----------
# STRIPE
# ----------

STRIPE_SECRET_KEY=placeholder_stripe_secret_key
STRIPE_PUBLISHABLE_KEY=placeholder_stripe_publishable_key
STRIPE_WEBHOOK_SECRET=placeholder_stripe_webhook_secret
WEBHOOK_URL=http://localhost:3000/api/webhooks/stripe

# ----------
# OAuth Tokens
# ----------

OAUTH_JWT_SECRET=$AUTH_SECRET
OAUTH_REFRESH_TOKEN_EXPIRY_SECONDS=2592000
OAUTH_ACCESS_TOKEN_EXPIRY_SECONDS=15

# ----------
# Telemetry
# ----------

OTEL_EXPORTER_OTLP_ENDPOINT=
SIGNOZ_INGESTION_KEY=
SIGNOZ_SERVICE_NAME=

# ----------
# Blob Storage
# ----------

BLOB_READ_WRITE_TOKEN=
EOF
fi

# Server .env
if [ ! -f "packages/app/server/.env" ]; then
echo "Creating server .env file..."
touch packages/app/server/.env

AUTH_SECRET=$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")
cat > packages/app/server/.env << EOF
PORT=3070
DATABASE_URL="postgresql://echo_user:echo_password@localhost:5469/echo_control_v2?schema=public"
ECHO_CONTROL_BASE_URL=http://localhost:3000
ECHO_API_KEY=placeholder_api_key
OAUTH_JWT_SECRET=$AUTH_SECRET
EOF
fi

echo ""
echo "Setup complete. Run 'pnpm dev' to start development servers."
echo ""
echo "Services will be available at:"
echo "- Echo Control: http://localhost:3000"
echo "- Echo Server: http://localhost:3070"
echo "- PostgreSQL: localhost:5469"