Purpose: This document defines the overall strategy, principles, structure, and workflow for the implementation sprints. It explains the "what", "why", and "how" of the implementation approach.
This document outlines the strategy for building a consistent, high-quality federated ActivityPub application through 10 implementation sprints. Each sprint delivers working functionality that builds incrementally toward a complete "Open Pace" application - a federated Strava alternative using Quarkus + Vert.x.
Each sprint builds on the previous, adding one major feature at a time:
- Sprint 1: Basic federation (foundation)
- Sprint 2: Custom types (extension)
- Sprint 3: Rich features (enhancement - comments, likes, attachments)
- Sprint 4: Sports features (specialization)
- Sprint 5: Privacy & polish (production-ready)
- Sprint 6: Security integration (authentication & authorization)
- Sprint 7: Mapping integration (geospatial data, OSM tiles)
- Sprint 8: Activity analytics & personal records (data analysis)
- Sprint 9: Social interactions & feed (social features)
- Sprint 10: Gear & equipment tracking (equipment management)
Each sprint should result in a working, testable feature that can be demonstrated independently.
Each sprint has:
- Goal: What feature will be implemented
- Prerequisites: What functionality from previous sprints is needed
- Deliverables: What working feature you'll have at the end
- Testing: How to verify it works
This project uses a single, evolving codebase where each sprint builds incrementally on the previous one. Git tags provide access to the state of the codebase at each sprint completion.
open-pace/ # Repository root
├── README.md # Main project overview
├── IMPLEMENTATION_STRATEGY.md # This file
├── pom.xml # Quarkus project (single project)
├── src/
│ ├── main/
│ │ ├── java/org/openpace/
│ │ │ ├── core/ # Core ActivityPub logic (Sprint 1+)
│ │ │ ├── activities/ # Custom activity types (Sprint 2+)
│ │ │ ├── rendering/ # Activity rendering (Sprint 3+)
│ │ │ ├── sports/ # Sports features (Sprint 4+)
│ │ │ ├── privacy/ # Privacy features (Sprint 5+)
│ │ │ ├── security/ # Security integration (Sprint 6+)
│ │ │ ├── mapping/ # Mapping integration (Sprint 7+)
│ │ │ ├── analytics/ # Analytics (Sprint 8+)
│ │ │ ├── social/ # Social features (Sprint 9+)
│ │ │ └── gear/ # Gear tracking (Sprint 10+)
│ │ └── resources/
│ │ ├── application.properties
│ │ └── db/migration/ # Flyway migrations
│ └── test/
│ └── java/org/openpace/ # Tests organized by package
│
├── docs/ # Shared documentation
│ ├── part-1-basic-activitypub.md
│ ├── part-2-custom-activities.md
│ ├── part-3-rich-interop.md
│ ├── part-4-sports-features.md
│ ├── part-5-privacy-data.md
│ ├── ACTIVITYPUB_REFERENCE.md
│ └── PROJECT_SETUP.md
│
└── LICENSE # Apache 2.0 License
Git tags provide access to each sprint's state:
# View Sprint 1 code (Basic ActivityPub)
git checkout v0.1.0-sprint1
# View Sprint 2 code (Custom Activities)
git checkout v0.2.0-sprint2
# View Sprint 3 code (Rich Data & Interop)
git checkout v0.3.0-sprint3
# Return to latest development
git checkout developKey Benefits of This Structure:
- ✅ Single codebase: No code duplication, natural evolution
- ✅ Version history: Git tags show progression through sprints
- ✅ Realistic workflow: Matches real-world development practices
- ✅ Easy maintenance: One project to maintain, not ten
- ✅ Clear progression: Git history shows how features evolved
- ✅ Accessible checkpoints: Checkout any sprint tag to see that state
- ✅ Incremental building: Each sprint adds to existing codebase
This repository follows a Git Flow-inspired branching model optimized for incremental sprint development:
main: Production-ready code. Contains stable, tested sprints. Each sprint completion is tagged and merged here.develop: Integration branch for active development. Feature branches merge here before going tomain.
main (stable releases, tagged)
│
├── v0.1.0-sprint1 (tag)
├── v0.2.0-sprint2 (tag)
└── ...
│
develop (integration branch)
│
├── feature/sprint-3 (feature branch)
└── feature/sprint-4 (feature branch)
-
Start a new sprint: Create feature branch from
developgit checkout develop git pull origin develop git checkout -b feature/sprint-X
-
Implement sprint features: Work in the feature branch
- Add new packages/classes to existing codebase
- Extend existing functionality
- Commit frequently with clear messages
-
Merge to develop: When sprint is complete and tested
git checkout develop git merge --no-ff feature/sprint-X git push origin develop
-
Release to main: Tag and merge to
mainfor stable releasegit checkout main git merge --no-ff develop git tag -a v0.X.0-sprintX -m "Release Sprint X: [Description]" git push origin main git push origin --tags
We use Semantic Versioning (SemVer) with sprint-based increments:
- MAJOR: Breaking changes to API or architecture (rare, only for major redesigns)
- MINOR: New features, new sprints (increments with each sprint)
- PATCH: Bug fixes, patches to existing sprints
- Sprint identifier:
-sprintNsuffix for clarity
v0.1.0-sprint1 # Sprint 1: Basic ActivityPub
v0.2.0-sprint2 # Sprint 2: Custom Activity Types
v0.2.1-sprint2 # Patch: Bug fix in Sprint 2
v0.3.0-sprint3 # Sprint 3: Rich Data & Interop
v0.4.0-sprint4 # Sprint 4: Sports Features
...
v1.0.0-sprint10 # Sprint 10: Complete application (first stable release)
- New Sprint: Increment MINOR, reset PATCH to 0
- Bug Fix: Increment PATCH for the current sprint
- Breaking Change: Increment MAJOR (only if API/architecture changes)
- Pre-release: Use
-alpha,-beta,-rcsuffixes if needed (e.g.,v0.3.0-alpha-sprint3)
- Release tags:
v0.X.0-sprintX(e.g.,v0.1.0-sprint1) - Patch tags:
v0.X.Y-sprintX(e.g.,v0.2.1-sprint2) - Pre-release tags:
v0.X.0-alpha-sprintX,v0.X.0-beta-sprintX,v0.X.0-rc-sprintX
-
Create annotated tag with descriptive message:
git tag -a v0.1.0-sprint1 -m "Release Sprint 1: Basic ActivityPub Server Features: - WebFinger discovery - Actor profiles - Inbox/Outbox - Basic federation with Mastodon"
-
Push tags to remote:
git push origin --tags
-
Verify tags:
git tag -l "v0.*" git show v0.1.0-sprint1
- ✅ Always use annotated tags (
-aflag) for releases - ✅ Include changelog summary in tag message
- ✅ Tag only on
mainbranch after merge - ✅ Tag after all tests pass and sprint is verified
- ✅ Use consistent naming (follow SemVer format)
Before tagging a release:
- All sprint features implemented and tested
- All tests pass (unit, integration, federation)
- Documentation updated (README, sprint docs)
- Code reviewed (if applicable)
- Federation tested with Mastodon/test server
- Sprint folder is complete and runnable
- Version number updated in
pom.xml(if applicable) - CHANGELOG.md updated (if maintained)
-
Finalize sprint:
# Ensure all changes committed git status # Run tests ./mvnw test
-
Merge to develop (if not already done):
git checkout develop git merge --no-ff feature/sprint-X
-
Merge to main and tag:
git checkout main git pull origin main git merge --no-ff develop git tag -a v0.X.0-sprintX -m "Release Sprint X: [Description]" git push origin main git push origin --tags -
Create release notes (optional, if using GitHub/GitLab releases):
- Summarize features
- List breaking changes (if any)
- Include testing instructions
When building Sprint 2+:
- Copy relevant code from
open-pace-p1/toopen-pace-p2/ - Refine and extend it
- Pros: Shows progression, readers can see evolution
- Cons: More code to maintain
- Build Sprint 2 from scratch
- Reference Sprint 1 concepts in documentation
- Pros: Cleaner, focused code
- Cons: Less continuity, more duplication
Recommendation: Use Option A for Sprints 1-3 (shows clear progression), Option B for Sprints 4-10 (more specialized features).
When building on previous sprint code:
-
Checkout the tagged version to reference:
git checkout v0.1.0-sprint1 # Browse code, then return to your branch git checkout feature/sprint-2 -
Or view specific files from a tag:
git show v0.1.0-sprint1:src/main/java/org/openpace/core/Actor.java
-
Code evolves in place: Previous sprint code is already in the codebase, just extend it
- Sprint 1 code is in
src/main/java/org/openpace/core/ - Sprint 2 adds
src/main/java/org/openpace/activities/ - Each sprint builds on what's already there
- Sprint 1 code is in
-
Document evolution in code comments:
// Enhanced in Sprint 2: Added custom activity types // Original implementation from Sprint 1 (v0.1.0-sprint1)
Follow Conventional Commits format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentationrefactor: Code refactoringtest: Testschore: Maintenance
Examples:
feat(sprint1): implement WebFinger discovery endpoint
Adds /.well-known/webfinger endpoint for ActivityPub
actor discovery. Supports resource parameter query.
Closes #123
fix(sprint2): correct JSON-LD context for RunActivity
Fixes incorrect @context URL in RunActivity serialization.
Now uses correct FediRun namespace.
Fixes #456
- ✅ Keep branches focused: One sprint per feature branch
- ✅ Regular merges: Merge to
developfrequently - ✅ Clean history: Use
--no-ffto preserve branch context - ✅ Delete merged branches: Clean up after merge to
maingit branch -d feature/sprint-X git push origin --delete feature/sprint-X
- ✅ List tags:
git tag -l "v0.*" - ✅ View tag details:
git show v0.1.0-sprint1 - ✅ Checkout tag:
git checkout v0.1.0-sprint1(creates detached HEAD) - ✅ Delete tag (if needed):
git tag -d v0.1.0-sprint1(local),git push origin :refs/tags/v0.1.0-sprint1(remote)
Maintain a CHANGELOG.md at repository root:
# Changelog
## [0.2.0-sprint2] - 2024-01-15
### Added
- Custom Activity types (RunActivity, CycleActivity)
- JSON-LD context for sports activities
- Schema validation
### Changed
- Enhanced Actor profile with sports metadata
## [0.1.0-sprint1] - 2024-01-01
### Added
- Basic ActivityPub server
- WebFinger discovery
- Actor profiles
- Inbox/Outbox endpointsUpdate version in pom.xml for each sprint:
<groupId>org.openpace</groupId>
<artifactId>open-pace</artifactId>
<version>0.2.0-sprint2</version>Key Workflow Points:
- ✅ Use feature branches for each sprint (
feature/sprint-X) - ✅ Merge to
developfor integration - ✅ Tag releases on
mainwith semantic versions - ✅ Follow Semantic Versioning (MAJOR.MINOR.PATCH-sprintN)
- ✅ Use annotated tags with descriptive messages
- ✅ Maintain clean commit history with conventional commits
- ✅ Reference previous sprints via git tags when copying code
Each implementation sprint should follow this structure:
# Part X: [Title]
## Learning Objectives
- [ ] Objective 1
- [ ] Objective 2
## Prerequisites
- Completed Sprint X-1
- Understanding of [concepts]
## What You'll Implement
[Clear description of the working feature]
## Implementation Steps
### Step 1: [Title]
[Detailed instructions]
### Step 2: [Title]
[Detailed instructions]
## Testing Your Implementation
### Manual Testing
1. [Test step 1]
2. [Test step 2]
### Automated Tests
[How to run tests]
## Key Concepts Explained
[Deep dive into important concepts]
## Common Issues & Solutions
[FAQ for this part]
## Next Steps
[Link to Sprint X+1]Packages evolve incrementally as sprints progress:
Sprint 1 (v0.1.0-sprint1):
org.openpace.core.*
Sprint 2 (v0.2.0-sprint2):
org.openpace.core.* (existing)
+ org.openpace.activities.* (new)
Sprint 3 (v0.3.0-sprint3):
org.openpace.core.* (existing)
org.openpace.activities.* (existing)
+ org.openpace.rendering.* (new)
Sprint 4 (v0.4.0-sprint4):
+ org.openpace.sports.* (new)
Sprint 5 (v0.5.0-sprint5):
+ org.openpace.privacy.* (new)
Sprint 6 (v0.6.0-sprint6):
+ org.openpace.security.* (new)
Sprint 7 (v0.7.0-sprint7):
+ org.openpace.mapping.* (new)
Sprint 8 (v0.8.0-sprint8):
+ org.openpace.analytics.* (new)
Sprint 9 (v0.9.0-sprint9):
+ org.openpace.social.* (new)
Sprint 10 (v1.0.0-sprint10):
+ org.openpace.gear.* (new)
Note: Each sprint builds on the previous codebase. Code from earlier sprints remains in the codebase and is extended/refined. Use git tags to access the state at any sprint.
ActivityPub Endpoints (Root level - required by spec):
/.well-known/webfinger/users/{username}/users/{username}/inbox/users/{username}/outbox/users/{username}/followers/users/{username}/following/activities/{activityId}
Application Endpoints (/api/* prefix - for UI/internal):
/api/auth/*- Authentication/api/activities/*- Activities (UI format)/api/users/*- User management/api/feed/*- Feeds/api/settings/*- Settings
See: API Design for detailed endpoint organization strategy.
- Each sprint has its own
application.properties - Quarkus Dev Services automatically configures database connections in dev/test mode
- For production, use environment variables or explicit configuration
- Keep configuration simple and documented
- Use Flyway or Liquibase
- Each sprint has its own migration set
- Sprint 1:
V1__initial.sql,V2__actors.sql, etc. - Sprint 2: Can start fresh or build on Sprint 1's schema (document the choice)
- Quarkus Dev Services automatically runs migrations when starting the dev database
Each sprint should have:
- Unit tests for new logic
- Integration tests for federation (using test ActivityPub servers)
- Manual test scripts (curl commands, Postman collections)
- Provide seed data for each part
- Include example activities, users, followers
For each implementation sprint, ensure:
- Clear entry point: Where does the code start?
- Working example: Can it be run and tested immediately?
- Federation test: Can it interact with Mastodon/test server?
- Code comments: Explain ActivityPub-specific concepts
- Error handling: Consistent error responses, no exceptions exposed
- Validation: Input validation using Hibernate Validator
- Performance notes: Where Vert.x async helps
- Visual examples: Screenshots or example JSON responses
See: Error Handling Strategy for error handling requirements.
Focus: Get federation working end-to-end
- Minimal code, maximum clarity
- Test with Mastodon following
- Show WebFinger, Actor, Inbox/Outbox
- Important: Implement C2S pattern (POST to outbox, process by activity type)
Deliverable: Can post text, Mastodon users can follow and see posts
Note: See ActivityPub C2S Pattern for correct implementation approach.
Focus: Extend ActivityPub with sports data
- Schema definition
- JSON-LD context
- Object storage
Deliverable: Can post runs with metrics, FediRun clients can parse them
Focus: Make it beautiful and interoperable
- Comment/Like Handling: Accept from any ActivityPub server
- Activity Rendering: Full activity viewer for FediRun clients
- Attachments: Support for images and previews
- Activity Viewing: Endpoints to view activities with comments and likes
Deliverable: Mastodon users can comment and like, FediRun users see full activity details
Focus: Strava-like features
- Leaderboards
- Segments
- Groups
Deliverable: Competitive features work across instances
Focus: Production-ready privacy
- Access control
- Data export
- Federation policies
Deliverable: Users control their data, can export, can set privacy
Focus: Authentication and authorization
- User registration and authentication
- Password hashing (BCrypt)
- Secure C2S endpoints (actor ownership)
- Verified field for email verification
- Actor-User relationship
Deliverable: Secure application with user accounts and proper authorization
Note: See Security Integration for detailed strategy.
Focus: Geospatial data and map visualization
- GPX Processing: Parse GPX files, extract tracks, simplify paths
- PostGIS Storage: Store tracks as LineString, start/end points
- Map Image Generation: Generate static maps with tracks overlaid on OSM tiles
- OSM Integration: Use OpenStreetMap tiles with proper attribution
- ActivityPub Integration: Display maps in activity attachments
Deliverable: Activities with GPX data display beautiful map images with tracks
Note: See Mapping Integration for detailed strategy.
For detailed versions and technology choices, see Quarkus Tech Stack.
- Quarkus: Java framework
- Vert.x: Async processing
- Jackson: JSON/ActivityPub serialization
- PostgreSQL: Data storage
- Flyway: Migrations
- Hibernate Validator: Input validation and error handling
- REST Assured: API testing
- Quarkus Dev Services: Automatic test database (uses Testcontainers under the hood)
- Mock ActivityPub server: For federation testing
- Quarkus Dev Mode: Hot reload
- Quarkus Dev Services: Automatic PostgreSQL container in dev mode
- OpenAPI/Swagger: API documentation for application endpoints (see API Design)
- Hibernate Validator: Input validation
- Exception Mappers: Consistent error responses
- Error Response Format:
{"error": "...", "message": "..."}
See: Error Handling Strategy for detailed approach.
- Read the strategy (this document)
- Create detailed outline using
docs/SPRINT_OUTLINE_TEMPLATE.md - Review ActivityPub reference (
docs/ACTIVITYPUB_REFERENCE.md) to ensure correct terminology - Plan code structure (packages, classes, endpoints)
- Create feature branch:
git checkout -b feature/sprint-X - Set up Quarkus project (if first sprint) or work in existing codebase
- Implement the sprint following your outline
- Add new packages/classes as needed
- Extend existing functionality
- Write tests as you go
- Test with Mastodon to verify federation works
- Commit frequently with clear, conventional commit messages
Starting Sprint 1 - Quick Setup:
# Create feature branch
git checkout develop
git pull origin develop
git checkout -b feature/sprint-1
# Initialize Quarkus project (if not already done)
# Ensure pom.xml has:
# - Quarkus REST
# - Quarkus Vert.x
# - PostgreSQL driver
# - Flyway (for migrations)
# Start implementing Sprint 1 features
# Code goes in src/main/java/org/openpace/core/Starting Sprint 2+ - Building on Previous:
# Create feature branch
git checkout develop
git pull origin develop
git checkout -b feature/sprint-2
# Previous sprint code is already in the codebase
# Add new packages/classes for Sprint 2
# Code goes in src/main/java/org/openpace/activities/- Write implementation guide using
docs/SPRINT_TEMPLATE.md - Add code examples (complete, runnable)
- Create test scenarios (manual and automated)
- Add troubleshooting section
- Run consistency checklist (
CONSISTENCY_CHECKLIST.md) - Test as a beginner (follow your own instructions)
- Verify federation (test with Mastodon)
- Get feedback (if possible)
- Document patterns established in this part
- Note lessons learned and trade-offs
- Update relevant strategy documents with new patterns:
- Database patterns →
docs/DATABASE_DESIGN.md - API patterns →
docs/API_DESIGN.md - Error handling →
docs/ERROR_HANDLING_STRATEGY.md - Federation patterns →
docs/FEDERATION_DELIVERY_STRATEGY.md - ActivityPub patterns →
docs/ACTIVITYPUB_REFERENCE.md
- Database patterns →
Important: Document key implementation decisions and lessons learned in the relevant strategy documents. This helps maintain consistency and guides future parts.
- Ensure sprint is complete and codebase is runnable
- Update main README with sprint status
- Update sprint documentation in
docs/folder - Merge to develop:
git checkout develop && git merge --no-ff feature/sprint-X - Tag release: Merge to
mainand tag withv0.X.0-sprintX - Prepare for next sprint (create feature branch for next sprint)
-
Test Early, Test Often
- Test with Mastodon after each major feature
- Don't assume federation works - verify it
- Keep a test Mastodon account handy
-
Keep It Simple
- Each part should be minimal but working
- Don't add features from later parts
- Focus on getting federation working
-
Explain the "Why"
- Not just "what" the code does
- Explain ActivityPub concepts
- Show how it fits into federation
-
Provide Working Examples
- Every code example should run
- Include complete, not partial, examples
- Test all examples before publishing
-
Be Consistent
- Use terminology from ActivityPub reference
- Follow the template structure
- Maintain code style throughout
❌ Don't: Jump Ahead
- Don't add Part 2 features in Part 1
- Each part should be complete but focused
- Readers need working checkpoints
❌ Don't: Assume Knowledge
- Explain ActivityPub concepts
- Don't assume readers know federation
- Provide context for each step
❌ Don't: Skip Testing
- Federation is complex - test everything
- Manual testing is as important as automated
- Test with real Mastodon instances
❌ Don't: Ignore Errors
- Document common issues
- Provide solutions, not just problems
- Include troubleshooting in each part
❌ Don't: Forget the Reader
- Write for someone new to ActivityPub
- Use clear, simple language
- Provide visual aids (diagrams, screenshots)
Before marking a sprint as complete:
- Code compiles and runs in the codebase
- All tests pass
- Can follow from Mastodon
- Tutorial is clear to a beginner
- Examples work out-of-the-box
- No broken links or references
- Sprint documentation updated in
docs/folder - Implementation decisions documented in relevant strategy documents
- Git tag created for this sprint release
- Quick start guide in main README
- Prerequisites clearly listed
- Development environment setup
- Each part has a completion checklist
- Visual indicators of progress
- "What you've built so far" summary
- Common issues section in each part
- Debug tips
- Community support links
Before marking a part complete:
- ✅ Can a beginner follow this?
- ✅ Does it work with Mastodon?
- ✅ Are all examples complete and runnable?
- ✅ Is the code structure clear?
- ✅ Are ActivityPub concepts explained?
- ✅ Would I understand this if I were new to federation?
- Initialize repository (if not done): Set up
mainanddevelopbranches - Set up Quarkus project at repository root (single
pom.xml) - Create feature branch:
git checkout -b feature/sprint-1 - Implement Sprint 1 (establish pattern)
- Document decisions in relevant strategy documents
- Review Sprint 1 (refine approach)
- Tag release: Merge to
mainand tagv0.1.0-sprint1 - Start Sprint 2: Create feature branch and build on Sprint 1 code
- Continue for Sprints 3-10 with proper versioning
- Cross-sprint review (consistency check)
- Final polish (examples, screenshots, etc.)
When building Sprint 2+:
- Previous sprint code is already in the codebase
- Add new packages/classes for new features
- Extend and refine existing code as needed
- Pros: Natural evolution, no duplication, realistic workflow
- Cons: None - this is the standard approach
To see how code looked at a previous sprint:
# Checkout Sprint 1 state
git checkout v0.1.0-sprint1
# Browse code, see what was implemented
# Return to development
git checkout develop- Sprint 1: Creates
org.openpace.core.*package - Sprint 2: Adds
org.openpace.activities.*package, may refine core - Sprint 3: Adds
org.openpace.rendering.*package, builds on previous - Each sprint adds new functionality while maintaining existing code
Critical: Each tutorial part must document its key implementation decisions in the relevant strategy documents (Database Design, API Design, Error Handling, etc.).
For each part, document:
- Design decisions: Why certain approaches were chosen
- Patterns established: Reusable patterns for future parts
- Lessons learned: What worked, what didn't, what to avoid
- Code patterns: Example code patterns that should be reused
- Trade-offs: What was considered and why decisions were made
- Future considerations: What might change in later parts
## Part X: [Title]
### [Decision Name]
**Decision**: [What was decided]
**Rationale**: [Why this decision was made]
**Implementation**: [How it's implemented]
**Code Pattern**: [Example code if applicable]
**Future Considerations**: [What might change]- ✅ Consistency: Future parts follow established patterns
- ✅ Learning: Readers understand why, not just what
- ✅ Reference: Quick lookup for implementation details
- ✅ Evolution: Shows how decisions evolved across parts
See: Relevant strategy documents (Database Design, API Design, Error Handling, etc.) for patterns and examples from completed parts.