Metadata-Version: 2.4
Name: weirdfingers-boards
Version: 0.11.0
Summary: Backend API server for Boards - AI creative toolkit with GraphQL, auth adapters, and generation workers
Author-email: Boards Contributors <ai.overlord@weirdfingers.com>
License: MIT
Project-URL: Homepage, https://github.com/weirdfingers/boards
Project-URL: Documentation, https://docs.boards.io
Project-URL: Repository, https://github.com/weirdfingers/boards
Project-URL: Issues, https://github.com/weirdfingers/boards/issues
Project-URL: Changelog, https://github.com/weirdfingers/boards/blob/main/CHANGELOG.md
Keywords: ai,creative,toolkit,graphql,fastapi,strawberry,auth,generation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Framework :: FastAPI
Classifier: Framework :: AsyncIO
Requires-Python: >=3.12
Description-Content-Type: text/markdown
Requires-Dist: sqlalchemy>=2.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: httpx[http2]>=0.24.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: strawberry-graphql[fastapi,opentelemetry]>=0.200.0
Requires-Dist: fastapi>=0.100.0
Requires-Dist: uvicorn[standard]>=0.23.0
Requires-Dist: dramatiq[redis,watch]>=1.15.0
Requires-Dist: pillow>=10.0.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: psycopg[binary]>=3.1.0
Requires-Dist: structlog>=23.0.0
Requires-Dist: asyncpg>=0.29.0
Requires-Dist: alembic>=1.13.2
Requires-Dist: aiofiles>=23.0.0
Requires-Dist: pyyaml>=6.0.0
Requires-Dist: click>=8.0.0
Requires-Dist: redis>=5.0.0
Requires-Dist: pyjwt[crypto]>=2.8.0
Requires-Dist: psutil>=7.0.0
Requires-Dist: opentelemetry-api>=1.20.0
Requires-Dist: opentelemetry-sdk>=1.20.0
Requires-Dist: opentelemetry-exporter-gcp-trace>=1.6.0
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.40.0
Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.40.0
Requires-Dist: opentelemetry-instrumentation-asyncpg>=0.40.0
Provides-Extra: generators-replicate
Requires-Dist: replicate>=1.0.4; extra == "generators-replicate"
Provides-Extra: generators-openai
Requires-Dist: openai>=1.60.1; extra == "generators-openai"
Provides-Extra: generators-fal
Requires-Dist: fal-client>=0.5.0; extra == "generators-fal"
Provides-Extra: generators-anthropic
Requires-Dist: anthropic>=0.25.0; extra == "generators-anthropic"
Provides-Extra: generators-together
Requires-Dist: together>=1.0.0; extra == "generators-together"
Provides-Extra: generators-all
Requires-Dist: replicate>=1.0.4; extra == "generators-all"
Requires-Dist: openai>=1.60.1; extra == "generators-all"
Requires-Dist: fal-client>=0.5.0; extra == "generators-all"
Requires-Dist: anthropic>=0.25.0; extra == "generators-all"
Requires-Dist: together>=1.0.0; extra == "generators-all"
Provides-Extra: storage-supabase
Requires-Dist: supabase>=2.0.0; extra == "storage-supabase"
Provides-Extra: storage-s3
Requires-Dist: boto3>=1.34.0; extra == "storage-s3"
Requires-Dist: aioboto3>=12.0.0; extra == "storage-s3"
Provides-Extra: storage-gcs
Requires-Dist: google-cloud-storage>=2.10.0; extra == "storage-gcs"
Provides-Extra: storage-all
Requires-Dist: supabase>=2.0.0; extra == "storage-all"
Requires-Dist: boto3>=1.34.0; extra == "storage-all"
Requires-Dist: aioboto3>=12.0.0; extra == "storage-all"
Requires-Dist: google-cloud-storage>=2.10.0; extra == "storage-all"
Provides-Extra: auth-supabase
Requires-Dist: supabase>=2.0.0; extra == "auth-supabase"
Provides-Extra: all
Requires-Dist: replicate>=1.0.4; extra == "all"
Requires-Dist: openai>=1.60.1; extra == "all"
Requires-Dist: fal-client>=0.5.0; extra == "all"
Requires-Dist: anthropic>=0.25.0; extra == "all"
Requires-Dist: together>=1.0.0; extra == "all"
Requires-Dist: supabase>=2.0.0; extra == "all"
Requires-Dist: boto3>=1.34.0; extra == "all"
Requires-Dist: aioboto3>=12.0.0; extra == "all"
Requires-Dist: google-cloud-storage>=2.10.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-postgresql>=6.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: pyright>=1.1.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
Requires-Dist: openai>=1.60.1; extra == "dev"
Requires-Dist: anthropic>=0.25.0; extra == "dev"
Requires-Dist: replicate>=1.0.4; extra == "dev"
Requires-Dist: together>=1.0.0; extra == "dev"
Requires-Dist: fal-client>=0.5.0; extra == "dev"
Requires-Dist: supabase>=2.0.0; extra == "dev"
Requires-Dist: boto3>=1.34.0; extra == "dev"
Requires-Dist: aioboto3>=12.0.0; extra == "dev"
Requires-Dist: google-cloud-storage>=2.10.0; extra == "dev"
Requires-Dist: types-redis>=4.6.0; extra == "dev"

# Boards Backend

Backend for the Boards open-source creative toolkit for AI-generated content.

## Features

- 🎨 Multi-provider support (Replicate, Fal.ai, OpenAI, etc.)
- 🔌 Pluggable architecture for generators and providers
- 📊 GraphQL API with Strawberry
- 🗄️ PostgreSQL with SQLAlchemy 2.0
- 🔄 Migrations with Alembic (async) and timestamped filenames
- 👥 Multi-tenant support with tenant isolation
- 🔐 Pluggable authentication (Supabase, Clerk, Auth0, JWT)
- 📦 Flexible storage backends (Local, S3, GCS, Supabase)

## Installation

### Minimal Install

The minimal installation includes core functionality with local filesystem storage only:

```bash
pip install weirdfingers-boards
```

### Install with Specific Generators

Install only the generator providers you need:

```bash
# OpenAI generators (DALL-E 3, Whisper)
pip install weirdfingers-boards[generators-openai]

# Replicate generators (Flux Pro, Lipsync)
pip install weirdfingers-boards[generators-replicate]

# fal.ai generators (nano-banana)
pip install weirdfingers-boards[generators-fal]

# Multiple generators
pip install weirdfingers-boards[generators-openai,generators-replicate]

# All generators
pip install weirdfingers-boards[generators-all]
```

### Install with Storage Backends

Add cloud storage providers as needed:

```bash
# S3 storage (AWS, MinIO, DigitalOcean Spaces)
pip install weirdfingers-boards[storage-s3]

# Supabase storage
pip install weirdfingers-boards[storage-supabase]

# Google Cloud Storage
pip install weirdfingers-boards[storage-gcs]

# All storage backends
pip install weirdfingers-boards[storage-all]
```

### Full Installation

Install everything (all generators and storage backends):

```bash
pip install weirdfingers-boards[all]
```

### Development Installation

For local development with all providers for type checking and testing:

```bash
# Clone the repository
git clone https://github.com/weirdfingers/boards.git
cd boards/packages/backend

# Install with dev dependencies (includes all providers)
uv sync
```

## Configuration

Copy `.env.example` to `.env` and configure your settings:

```bash
cp .env.example .env
```

Key configuration options:

- `BOARDS_DATABASE_URL`: PostgreSQL connection string (e.g. postgresql://user:pass@localhost:5433/db)
- `BOARDS_REDIS_URL`: Redis connection for job queue
- `BOARDS_STORAGE_PROVIDER`: Storage backend (local, s3, gcs, supabase)
- `BOARDS_AUTH_PROVIDER`: Authentication provider

## Database Setup

### 1. Create the database

```bash
createdb boards_dev
```

### 2. Apply initial schema via Alembic

```bash
# Use Alembic to create all tables
uv run alembic upgrade head
```

## Development

### Quick Start

```bash
# Start the API server (after installation and configuration)
boards-server

# Run database migrations
boards-migrate upgrade head

# Start background workers
boards-worker
```

### Development Server

```bash
# Using uvicorn directly
uvicorn boards.api.app:app --reload --port 8088

# Or using the module
python -m boards.api.app
```

### Access the GraphQL playground

Open http://localhost:8088/graphql in your browser.

### Database migrations

When you need to change the database schema, use Alembic.

```bash
# Create a new migration (autogenerate from models in boards.dbmodels)
uv run alembic revision -m "add feature" --autogenerate

# Apply latest migrations
uv run alembic upgrade head

# Roll back one revision
uv run alembic downgrade -1
```

📖 For detailed migration workflow, see docs and examples under `apps/docs`.

## Project Structure

```
packages/backend/
├── alembic/                 # Alembic migration scripts
│   └── versions/            # Timestamped revision files
├── alembic.ini              # Alembic config
├── src/boards/
│   ├── api/                 # FastAPI application
│   ├── dbmodels/            # SQLAlchemy ORM models (authoritative)
│   ├── database/            # Connection helpers and compatibility shim
│   ├── graphql/             # GraphQL schema and resolvers
│   ├── providers/           # Provider implementations
│   ├── generators/          # Generator implementations
│   ├── storage/             # Storage backends
│   └── config.py            # Configuration management
└── tests/
```

## Community & Social

Join the Weirdfingers community:

- **TikTok**: [https://www.tiktok.com/@weirdfingers](https://www.tiktok.com/@weirdfingers)
- **X (Twitter)**: [https://x.com/_Weirdfingers_](https://x.com/_Weirdfingers_)
- **YouTube**: [https://www.youtube.com/@Weirdfingers](https://www.youtube.com/@Weirdfingers)
- **Discord**: [https://discord.gg/rvVuHyuPEx](https://discord.gg/rvVuHyuPEx)
- **Instagram**: [https://www.instagram.com/_weirdfingers_/](https://www.instagram.com/_weirdfingers_/)
## Testing

Boards uses pytest for testing with both unit tests (mocked) and optional live API tests.

### Running Tests

```bash
# Run all unit tests (excludes live API tests)
make test-backend

# Or using pytest directly
cd packages/backend
uv run pytest tests/

# Run with coverage
uv run pytest tests/ --cov=src/boards --cov-report=html

# Run specific test file
uv run pytest tests/generators/implementations/test_flux_pro.py -v
```

### Unit Tests vs Live API Tests

**Unit tests** (default):
- Use mocked provider SDKs
- Fast and free
- Run automatically in CI/CD
- Located: `tests/**/test_*.py`

**Live API tests** (opt-in only):
- Make real API calls to providers
- Consume API credits
- **Never run by default**
- Located: `tests/**/test_*_live.py`

### Running Live API Tests

Live tests verify real connectivity with provider APIs but cost money. They are **excluded from default test runs**.

```bash
# Set up API key
export BOARDS_GENERATOR_API_KEYS='{"REPLICATE_API_TOKEN": "r8_..."}'

# Run a specific generator's live test
uv run pytest tests/generators/implementations/test_flux_pro_live.py -v -m live_api

# Run all live tests for one provider
uv run pytest -m live_replicate -v

# Run all live tests (not recommended - expensive!)
uv run pytest -m live_api -v
```

For detailed information on live API testing, see:
- [Live API Testing Guide](docs/TESTING_LIVE_APIS.md)
- [Generator Testing Documentation](../../apps/docs/docs/generators/testing.md)

### Test Organization

```
tests/
├── conftest.py                              # Shared fixtures (database, etc.)
├── generators/
│   └── implementations/
│       ├── conftest.py                      # Generator-specific fixtures
│       ├── test_flux_pro.py                 # Unit tests (mocked)
│       ├── test_flux_pro_live.py           # Live API tests (opt-in)
│       └── ...
├── graphql/                                 # GraphQL API tests
└── storage/                                 # Storage backend tests
```

## License

MIT
