Skip to content

Latest commit

Β 

History

427 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SessioFlow

A Call-for-Papers (CfP) platform built with Next.js, designed to help organizers manage conferences, proposals, and speaker scheduling.


πŸ“š Documentation

Documentation Generation Workflow

When creating documentation for SessioFlow, follow this recommended order:

Step 1: Inception (Product Discovery)
         ↓
Step 2: Flow Documentation (Reveals Entities)
         ↓
Step 3: Entity Lifecycle (Define Entities)
         ↓
Step 4: More Flows (Reference Existing Entities)

Step-by-Step Process

1. Inception Phase (docs/inception/)

  • Complete Inception Steps 1-8 (Product Vision β†’ MVP Canvas)
  • Step 6: User Journey Mapping identifies all journeys (J1-J5)
  • Step 7: Features & Sequencing defines MVP scope

2. Flow Documentation (docs/product/bounded-contexts/{context}/flows/)

  • Start with Journey 1 (e.g., Setup Conference)
  • Use create-flow-documentation skill to generate flow specs
  • Flow reveals which entities are needed (Conference, CfpConfig, etc.)
  • Extract Business Rules (BR-XXX) and Invariants (INV-XXX)

3. Entity Lifecycle Documentation (docs/product/bounded-contexts/{context}/entities/)

  • Create entity docs based on entities revealed in flows
  • Use create-entity-lifecycle skill to generate entity specs
  • Define state machines, transitions, and domain methods
  • Extract additional BRs and INVs if needed

4. Additional Flows (docs/product/bounded-contexts/{context}/flows/)

  • Document remaining journeys (J2-J4)
  • Reference existing entity lifecycle docs
  • Extract BRs and INVs as needed

Documentation Structure

docs/
β”œβ”€β”€ inception/                    # Inception workshop outputs
β”‚   β”œβ”€β”€ 1-product-vision-and-boundaries.md
β”‚   β”œβ”€β”€ 2-tradeoffs.md
β”‚   β”œβ”€β”€ 3-personas/
β”‚   β”œβ”€β”€ 4-empathy-map.md
β”‚   β”œβ”€β”€ 5-brainstorming.md
β”‚   β”œβ”€β”€ 6-user-journeys/           ← START HERE
β”‚   β”œβ”€β”€ 7-features-and-sequencing.md
β”‚   └── 8-mvp-canvas-definition.md
β”‚
└── product/                      # DDD documentation
    β”œβ”€β”€ bounded-contexts/
    β”‚   └── conference/
    β”‚       β”œβ”€β”€ flows/             ← Create flows first (reveals entities)
    β”‚       β”‚   └── journey-01-setup-conference.md
    β”‚       β”œβ”€β”€ entities/          ← Then create entities
    β”‚       β”‚   β”œβ”€β”€ conference.md
    β”‚       β”‚   └── cfp-config.md
    β”‚       β”œβ”€β”€ business-rules/    ← Extracted from flows/entities
    β”‚       β”‚   └── BR-001-*.md
    β”‚       └── invariants/        ← Extracted from flows/entities
    β”‚           └── INV-001-*.md
    └── flows/                    # Flow catalog
        └── README.md

AI Skills for Documentation

SessioFlow provides two AI skills to help generate documentation:

Skill Purpose Triggers When You Say
create-flow-documentation Generate user journey flows "Create flow for Journey 2", "Generate flow specification"
create-entity-lifecycle Generate entity specs "Create entity lifecycle for Conference", "Document the Submission entity"

Both skills are self-contained with all templates and guidelines bundled.

Documentation Workflow Diagram

flowchart TB
    subgraph Inception["Inception Phase"]
        A["Inception Steps 1-8"] --> B["Step 6: User Journey Mapping"]
        B --> C["Step 7: Features & Sequencing"]
    end

    subgraph FlowDocs["Flow Documentation"]
        D["Create Flow 1<br/>(Journey 01: Setup Conference)"] --> E["Extract BRs & INVs<br/>from flow steps"]
        E --> F["journey-01-setup-conference.md"]
    end

    subgraph EntityDocs["Entity Lifecycle Documentation"]
        G["Create Entity Lifecycle<br/>(Conference, CfpConfig)"] --> H["Extract BRs & INVs<br/>from entity constraints"]
        H --> I["conference.md, cfp-config.md"]
    end

    subgraph BRINV["Business Rules & Invariants"]
        J["business-rules/BR-XXX-*.md"]
        K["invariants/INV-XXX-*.md"]
    end

    subgraph AdditionalFlows["Additional Flows"]
        L["Create Flow 2-4<br/>(Reference Existing Entities)"] --> M["journey-02-04.md"]
    end

    %% Connections
    C --> D
    F -.-> G
    G -.-> L
    E -.-> J
    E -.-> K
    H -.-> J
    H -.-> K
    M -.-> J
    M -.-> K

    %% Styling
    style Inception fill:#e3f2fd
    style FlowDocs fill:#c8e6c9
    style EntityDocs fill:#fff9c4
    style BRINV fill:#f3e5f5
    style AdditionalFlows fill:#ffe0b2
Loading

Legend:

  • πŸ”΅ Inception - User journey identification
  • 🟒 Flow Docs - Journey specifications with diagrams
  • 🟑 Entity Docs - Entity state machines and constraints
  • 🟣 BR/INV - Extracted business rules and invariants
  • 🟠 Additional Flows - Reference existing entities

What Feeds Entity Lifecycle Creation?

Entity lifecycle documentation is created from multiple input sources:

Document What It Provides Example
Flow Documentation (Primary) Entity behaviors, state transitions, domain methods Flow shows Conference.publishCfp() β†’ Entity needs publishCfp() method
Journey Mapping (Step 6) Entity requirements from user needs "Create conference" β†’ Need Conference entity
Features & Sequencing (Step 7) Feature scope and entity relationships "CfP Management" β†’ Need Conference + CfpConfig entities
MVP Canvas (Step 8) Entity constraints and priorities MVP scope limits Conference to 5 states

Extraction Process:

Flow: Journey 01 - Setup Conference
    ↓
Identifies: Conference entity with states DRAFT β†’ CFP_OPEN
    ↓
Reveals: Methods create(), publishCfp(), closeCfp()
    ↓
Creates: conference.md with state machine and domain methods
    ↓
Extracts: INV-001 (state machine), BR-001 (date validation)

Why Flow First?

  • Flows reveal what entities are actually needed
  • Flows show how entities behave in real scenarios
  • Flows identify which state transitions matter
  • Flows expose edge cases that become invariants

Entity Lifecycle Template Uses:

  • State Machine from flow transitions
  • Domain Methods from flow steps
  • Constraints from flow validations
  • Business Rules from flow edge cases

Business Rules & Invariants Extraction

Both flows and entities automatically extract Business Rules (BR) and Invariants (INV) during creation.

Source What It Extracts Example
Flow Creation Rules governing flow steps, validations, edge cases BR-001: Cfp Dates Must Be Valid (from flow validation step)
Entity Lifecycle Rules governing state transitions, domain methods, constraints INV-001: Conference State Must Follow State Machine (from entity state machine)

Process:

Flow Creation:
  Journey Steps β†’ Identify validations/edge cases β†’ Extract BRs/INVs β†’ Link in flow

Entity Lifecycle:
  Entity Definition β†’ Identify constraints/methods β†’ Extract BRs/INVs β†’ Link in entity

Output Structure:

docs/product/bounded-contexts/conference/
β”œβ”€β”€ flows/
β”‚   └── journey-01-setup-conference.md  β†’ Links to: BR-001, INV-002
β”œβ”€β”€ entities/
β”‚   β”œβ”€β”€ conference.md                   β†’ Links to: INV-001, BR-004
β”‚   └── cfp-config.md              β†’ Links to: INV-002, BR-001
β”œβ”€β”€ business-rules/
β”‚   β”œβ”€β”€ BR-001-cfp-dates-validation.md
β”‚   └── BR-004-free-tier-conference-limit.md
└── invariants/
    β”œβ”€β”€ INV-001-state-transition-validity.md
    └── INV-002-cfp-date-order.md

Note: You don't create BRs/INVs separately - they're automatically extracted during flow and entity creation.


Architecture Decision Records (ADRs)

Key decisions that shape the SessioFlow architecture:

ADR Status Description
ADR-002-00 Superseded Use Supabase for Backend and Database
ADR-002-01 βœ… Approved Amendment: DDD Abstraction Layer
ADR-002-02 βœ… Accepted Vendor Lock-in Alternatives Analysis
ADR-002-03 βœ… Accepted Authentication Strategy with DDD
ADR-004-00 Superseded Implement Magic Link Authentication
ADR-004-01 βœ… Approved Amendment: Auth with DDD Abstraction
ADR-005-00 Superseded Use Supabase Storage for Files
ADR-005-01 βœ… Approved Amendment: Storage with DDD Abstraction
ADR-009 βœ… Approved Adopt Domain-Driven Design (DDD) Structure
ADR-011-00 Superseded Use Resend for Email Communications
ADR-011-01 βœ… Approved (Optional) Amendment: Optional Email Abstraction

Latest Decisions:

  • Authentication Strategy (ADR-004-01): Implement DDD ports & adapters pattern for vendor-agnostic authentication
  • Storage Strategy (ADR-005-01): Supabase Storage with DDD abstraction (swappable to Cloudflare R2)
  • DDD Architecture (ADR-009): Adopt Domain-Driven Design structure for long-term maintainability
  • Hybrid Approach (ADR-002-01): Consider Supabase Database + Auth0 + DDD abstraction for MVP

πŸ—οΈ Project Structure

SessioFlow follows Domain-Driven Design (DDD) principles with a split monorepo structure that enables independent deployment and backend stack swapping:

sessioflow/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ backend/                  # Backend service (Node/Go/Kotlin)
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”‚   β”œβ”€β”€ modules/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ conference/   # Bounded context
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ domain/   # Domain layer (immutable)
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ application/  # Application layer
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ infrastructure/ # Infrastructure layer (swappable)
β”‚   β”‚   β”‚   β”‚   β”‚   └── interfaces/
β”‚   β”‚   β”‚   β”‚   β”‚       └── api/    # API contracts (backend-specific)
β”‚   β”‚   β”‚   └── shared/           # Shared backend utilities
β”‚   └── frontend/                 # Next.js frontend
β”‚       └── src/
β”‚           β”œβ”€β”€ app/              # Next.js pages
β”‚           β”œβ”€β”€ components/       # UI components
β”‚           └── modules/          # Frontend modules
β”‚               └── conference/
β”‚                   └── interfaces/web/  # React components
β”‚
β”œβ”€β”€ packages/                     # Shared packages (utils, etc.)
β”‚   └── utils/                    # Frontend & backend utilities
└── docs/                         # Documentation

Monorepo Structure Benefits:

  • βœ… Backend stack independence - Swap Node β†’ Go/Kotlin without touching frontend
  • βœ… Independent deployment - Backend and frontend can be deployed separately
  • βœ… DDD purity - Domain/application layers are encapsulated in backend
  • βœ… Clear ownership - Frontend and backend teams work independently
  • βœ… Reduced migration cost - 8-14 hours for backend swap (vs 52-336 hours)

Module-Based Architecture Benefits:

  • βœ… High cohesion - All code for a feature is together
  • βœ… Independent modules - Change one feature without affecting others
  • βœ… Easier navigation - Find all conference code in backend/modules/conference/
  • βœ… Better scaling - Add features without touching existing code
  • βœ… Clear boundaries - No accidental dependencies between features

πŸ› οΈ Tech Stack

Core Technologies

  • Frontend: Next.js 14+ (App Router)
  • Language: TypeScript (strict mode)
  • Database: PostgreSQL (Supabase or swappable alternative)
  • Authentication: Auth0 / NextAuth / Supabase (swappable via DDD abstraction)
  • Storage: Supabase Storage / Cloudflare R2 (swappable via DDD abstraction)
  • Email: Resend (with optional abstraction)
  • Testing: Vitest (unit), Playwright (E2E)
  • Architecture: Domain-Driven Design (DDD) with Ports & Adapters

Vendor Abstraction Pattern

All external dependencies use DDD abstraction to enable vendor independence:

// Domain layer defines the interface
interface AuthProvider {
  login(credentials): Promise<User>;
  logout(token): Promise<void>;
  getCurrentUser(token): Promise<User | null>;
}

interface StorageProvider {
  upload(file): Promise<UploadResult>;
  download(path): Promise<Buffer>;
  getUrl(path): Promise<string>;
  delete(path): Promise<void>;
}

// Infrastructure layer implements the interface
class Auth0Provider implements AuthProvider { ... }
class NextAuthProvider implements AuthProvider { ... }
class SupabaseStorageAdapter implements StorageProvider { ... }
class CloudflareR2Adapter implements StorageProvider { ... }

// Application layer uses only the interface
class LoginUseCase {
  constructor(private provider: AuthProvider) {}
}

Benefits:

  • βœ… Swap providers with 8-14 hours effort (vs 52-336 hours)
  • βœ… Vendor lock-in reduced by 85%
  • βœ… Easy testing with mock implementations
  • βœ… Can optimize costs by switching providers

CQRS Pattern

SessioFlow uses the Command Query Responsibility Segregation (CQRS) pattern for the application layer:

// Command (Write Operation)
export class CreateConferenceCommand {
  constructor(
    public readonly name: string,
    public readonly slug: string,
    public readonly cfpStartDate: Date,
    public readonly cfpEndDate: Date
  ) {}
}

export class CreateConferenceHandler {
  constructor(
    private conferenceRepository: ConferenceRepository,
    private uuidGenerator: UuidGenerator
  ) {}

  async handle(command: CreateConferenceCommand): Promise<Result<CreateConferenceDto>> {
    // 1. Validate command
    // 2. Create domain entity
    // 3. Persist to repository
    // 4. Return response DTO
  }
}

// Query (Read Operation)
export class GetConferenceQuery {
  constructor(public readonly id: string) {}
}

export class GetConferenceHandler {
  constructor(private conferenceRepository: ConferenceRepository) {}

  async handle(query: GetConferenceQuery): Promise<Result<GetConferenceDto>> {
    // 1. Query repository
    // 2. Map to response DTO
    // 3. Return data (no side effects)
  }
}

Benefits:

  • βœ… Clear separation between read and write operations
  • βœ… Response DTOs provide stable API contracts
  • βœ… Independent optimization of reads and writes
  • βœ… Improved testability with single-responsibility handlers
  • βœ… Better alignment with DDD application layer

πŸš€ Getting Started

Prerequisites

  • Node.js 18+ or Bun
  • PostgreSQL database (Supabase or self-hosted)
  • Auth provider (Auth0, NextAuth, or custom)
  • Storage provider (Supabase Storage, Cloudflare R2, or MinIO)

Installation

# Install dependencies
npm install
# or
bun install

# Set up environment variables
cp .env.example .env.local
# Edit .env.local with your configuration

# Run development server
npm run dev
# or
bun run dev

Environment Variables

# Database
DATABASE_URL=postgresql://user:password@host:5432/database

# Authentication (Auth0 example)
AUTH0_DOMAIN=your-domain.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret

# Alternative: NextAuth
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-secret

# Alternative: Supabase Auth
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key

# Storage (Supabase example)
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_KEY=your-service-key

# Alternative: Cloudflare R2
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_BUCKET_NAME=your-bucket

# Email (Resend example)
RESEND_API_KEY=re_your-api-key

Database Setup

The project uses Drizzle Kit for database migrations. Local PostgreSQL is managed via Docker Compose.

# Start local PostgreSQL (Docker) β€” the compose file lives with the backend app
docker compose -f apps/backend/docker-compose.yml up -d

# Generate migration from schema (after schema changes)
npm run db:generate

# Apply migrations to database
npm run db:migrate

# Push schema directly (no migration file)
npm run db:push

# Open Drizzle Studio (database GUI)
npm run db:studio

Migration files are stored in: drizzle/

Schema is defined in: src/modules/conference/infrastructure/database/drizzle-schema.ts


πŸ“– Development

Running the Development Server

npm run dev

Running Tests

# Unit tests (Vitest)
npm test

# E2E tests (Playwright)
npm run test:e2e

# Single test file
npx vitest run tests/unit/auth.test.ts
npx playwright test tests/e2e/auth.spec.ts

Type Checking

npm run typecheck

Linting

npm run lint
npm run lint:fix
npm run format

Building for Production

npm run build
npm run start

πŸ“‹ Key Features

MVP Features (Wave 1)

  • βœ… Conference creation and management
  • βœ… Call-for-Papers (CFP) configuration
  • βœ… Proposal submission by speakers
  • βœ… Speaker profiles with profile photos
  • βœ… Admin dashboard for organizers
  • βœ… Row-Level Security (RLS) for data protection

Planned Features (Wave 2+)

  • πŸ“‹ Review and scoring system
  • πŸ“‹ Session scheduling and conflict detection
  • πŸ“‹ Email notifications
  • πŸ“‹ Export proposals to CSV/PDF
  • πŸ“‹ Multi-language support

πŸ›οΈ Architecture Principles

Domain-Driven Design (DDD)

SessioFlow follows DDD principles to ensure long-term maintainability:

  1. Domain Layer: Pure business logic, vendor-agnostic
  2. Application Layer: Use cases and orchestration
  3. Infrastructure Layer: External service implementations (swappable)
  4. Interface Layer: UI and API entry points

Benefits:

  • βœ… Clear separation of concerns
  • βœ… Easy to test (domain logic has no dependencies)
  • βœ… Swappable infrastructure (database, auth, storage)
  • βœ… Scales well for complex domain features

Vendor Abstraction

All external dependencies are accessed through repository interfaces:

// Domain defines the contract
interface AuthProvider {
  login(credentials): Promise<User>;
  logout(token): Promise<void>;
  getCurrentUser(token): Promise<User | null>;
}

interface StorageProvider {
  upload(file): Promise<UploadResult>;
  download(path): Promise<Buffer>;
  getUrl(path): Promise<string>;
  delete(path): Promise<void>;
}

// Infrastructure implements the contract
class Auth0Provider implements AuthProvider { ... }
class NextAuthProvider implements AuthProvider { ... }
class SupabaseStorageAdapter implements StorageProvider { ... }
class CloudflareR2Adapter implements StorageProvider { ... }

// Application uses only the interface
class LoginUseCase {
  constructor(private provider: AuthProvider) {}
}

Benefits:

  • βœ… Swap Auth0 for NextAuth with 1-line change
  • βœ… Swap Supabase Storage for Cloudflare R2 with 1-line change
  • βœ… Swap database provider with minimal changes
  • βœ… Migration cost reduced by 85% (from 156-336 hours to 24-42 hours)

πŸ› οΈ Development & Architecture Quality Commands

# Fast Standalone Architecture Check (< 2s) for AI Agents & Developers
npm run check:arch                                # Check all domain modules
npm run check:arch packages/modules/conference   # Check target module/file

# Testing & Type Safety
npm run test                                      # Run unit test suite (Vitest)
npm run test:changed                              # Run tests for Git modified files
npm run test:architecture                         # Run full Vitest architecture test suite
npm run typecheck                                 # TypeScript type checking
npm run lint                                      # Run ESLint checks

πŸ›οΈ Automated Architecture Invariants

SessioFlow enforces strict Domain-Driven Design (DDD) rules via ts-archunit automated checks:

  • Domain Isolation: Domain modules (packages/modules/*/src/domain/) cannot depend on application, infrastructure, ORMs, or external UI frameworks.
  • Value Objects: Must have private constructor, static factory (create/fromString), get value(), and equals(other) method. Raw primitives (string, number, boolean) are forbidden in domain entity properties and factory parameters.
  • Domain Events: Must reside in domain/events/, end with Event, define type + timestamp, and implement toJSON() serialization for Outbox persistence.
  • Domain Exceptions: Must reside in domain/exceptions/, end with Error, and extend base DomainError / EntityNotFoundError.
  • Repositories: Repository interfaces reside in domain/, implementations reside in infrastructure/ and reconstitute entities via static .fromData(...) factory methods.

🀝 Contributing

  1. Read the ADR documentation to understand architectural decisions
  2. Follow DDD patterns when adding new features
  3. Write tests for new functionality
  4. Submit a pull request with a clear description

πŸ“„ License

MIT License - see LICENSE file for details


πŸ”— Resources

Architecture Documentation

External References


πŸ“ž Support

For questions or issues:

  • Open an issue on GitHub
  • Review existing ADRs for architectural context
  • Check the docs for detailed information

🎯 Quick Start Guide

For New Developers

  1. Read ADR-009: Understand the DDD architecture
  2. Read ADR-002b: Understand authentication strategy
  3. Set up environment: Follow installation instructions above
  4. Run tests: npm test to verify setup
  5. Start coding: Follow DDD patterns in existing code

For Technical Decision Makers

  1. Review ADR-002 Amendment: Understand vendor abstraction benefits
  2. Review ADR-004 Amendment: Auth implementation details
  3. Review ADR-005 Amendment: Storage implementation details
  4. Consider trade-offs: Speed vs. flexibility, vendor lock-in vs. development time

Last Updated: 2026-06-11 Maintained By: Technical Team

About

Software to manage C4P

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages