gurixandClaude 5bb27bdadf chore: archive add-graphql-member-api proposal and create capability specs
Archive completed GraphQL API implementation proposal:
- Move proposal to openspec/changes/archive/2025-11-20-add-graphql-member-api/
- Create capability specs in openspec/specs/:
  - database-layer: SQLAlchemy async with Alembic migrations
  - graphql-api: Strawberry GraphQL with FastAPI integration
  - member-crud: Member management with conditional validation
  - project-setup: Python 3.11+ with uv package manager

All 73 tasks completed and validated.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 13:26:43 +01:00
2025-11-19 22:13:05 +01:00
2025-11-19 22:13:05 +01:00
2025-11-19 22:13:05 +01:00

Clubber

A toolset for managing members of non-profit societies (Vereine) with AI-powered administration.

Overview

Clubber provides a GraphQL API for member management combined with an MCP (Model Context Protocol) server that enables AI assistants to help with society administration tasks.

Current Status: Early development - OpenSpec documentation and project structure in place.

Architecture

The system consists of two main components:

  1. GraphQL API - Core backend for member data management

    • Built with FastAPI and Strawberry GraphQL
    • Database-agnostic design (SQLite for development, PostgreSQL for production)
    • SQLAlchemy 2.0 ORM with async support
  2. MCP Server - AI assistant integration layer

    • Connects to the GraphQL API
    • Provides tools for AI agents to manage society operations
    • Service account authentication

Tech Stack

  • Python 3.11+ - Primary language
  • uv - Fast package and project manager
  • FastAPI - Async web framework
  • Strawberry GraphQL - Type-safe GraphQL with Python type hints
  • SQLAlchemy 2.0 - Database ORM
  • Alembic - Database migrations

Project Structure

clubber/
├── openspec/           # Specification-driven development
│   ├── project.md      # Project conventions and context
│   ├── specs/          # Current specifications
│   └── changes/        # Change proposals
├── CLAUDE.md           # AI assistant instructions
└── README.md           # This file

Getting Started

Prerequisites

  • Python 3.11 or higher
  • uv package manager

Setup

# Clone the repository
git clone ssh://git@codeberg.org/gurix/clubber.git
cd clubber

# Install uv if not already installed
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install dependencies
uv sync

# Run database migrations
uv run alembic upgrade head

# (Optional) Seed the database with sample data
PYTHONPATH=. uv run python scripts/seed.py

Running the Server

Start the development server:

uv run uvicorn src.main:app --host 127.0.0.1 --port 8000 --reload

The --reload flag enables auto-restart when code changes are detected.

Access the API:

API Usage Examples

Member Data Model

Members have the following fields:

  • firstName (required) - Member's first name
  • lastName (optional) - Member's last name
  • street (optional) - Street address
  • apartmentNumber (optional) - Apartment or unit number
  • zip (optional) - Postal code
  • city (optional) - City
  • country (optional) - Country
  • email (optional) - Email address (validated when provided)
  • phone (optional) - Phone number in E.164 format (validated when provided)

Key Feature: Only firstName is required. All other fields are optional and can be populated later. Email and phone are validated only when provided (not when null/empty).

GraphQL Queries

List all members:

{
  members {
    id
    firstName
    lastName
    email
    phone
    city
  }
}

Get a single member:

{
  member(id: 1) {
    id
    firstName
    lastName
    email
    street
    city
    country
  }
}

GraphQL Mutations

Create a member (minimal - only firstName):

mutation {
  createMember(input: {
    firstName: "Alice"
  }) {
    id
    firstName
    email
  }
}

Create a member with all fields:

mutation {
  createMember(input: {
    firstName: "Bob"
    lastName: "Johnson"
    street: "123 Main St"
    apartmentNumber: "4B"
    zip: "12345"
    city: "Springfield"
    country: "USA"
    email: "bob.johnson@example.com"
    phone: "+14155551234"
  }) {
    id
    firstName
    lastName
    email
    phone
  }
}

Update a member:

mutation {
  updateMember(input: {
    id: 1
    email: "updated@example.com"
    phone: "+14155559999"
  }) {
    id
    firstName
    email
    phone
  }
}

Delete a member:

mutation {
  deleteMember(id: 2)
}

Using curl

Query members:

curl -X POST http://127.0.0.1:8000/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "{ members { id firstName lastName email } }"}'

Create a member:

curl -X POST http://127.0.0.1:8000/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "mutation { createMember(input: { firstName: \"Charlie\" }) { id firstName } }"}'

Development Workflow

This project uses OpenSpec for specification-driven development:

  1. Review existing specs in openspec/specs/
  2. Create change proposals in openspec/changes/ before implementing features
  3. Validate proposals with openspec validate --strict
  4. Implement changes following the proposal
  5. Archive completed changes after deployment

See openspec/AGENTS.md for detailed workflow instructions.

Working with Git Worktrees

We use git worktrees for parallel development:

# Create a worktree for a feature branch
git worktree add ../clubber-feature-name feature/feature-name

# Work in the worktree
cd ../clubber-feature-name

# Remove worktree after merge
git worktree remove ../clubber-feature-name

Contributing

  1. Read openspec/project.md for project conventions
  2. For new features, create an OpenSpec proposal first
  3. Follow the coding style (Black, isort, ruff)
  4. Write tests for new functionality
  5. Use conventional commits (feat:, fix:, docs:, etc.)

License

The MIT License

Contact

Markus Graf - info@markusgraf.ch

Acknowledgments

Built with support from:

S
Description
No description provided
Readme
247 KiB
Languages
Python 70.2%
JavaScript 29%
Mako 0.8%