Skip to content

feat: add configurable user count badge for Klyne - #27

Merged
psincraian merged 4 commits into
mainfrom
claude/add-user-count-badge-019HnqapVtSZv1HbrgHdzAYA
Nov 19, 2025
Merged

psincraian merged 4 commits into
mainfrom
claude/add-user-count-badge-019HnqapVtSZv1HbrgHdzAYA

Conversation

@psincraian

Copy link
Copy Markdown
Owner

No description provided.

This commit implements a badge system that displays unique total users for packages. Key features:

- Added badge_public field to APIKey model (default: False)
- Added is_active and description fields to APIKey model (previously referenced but missing)
- Created /api/badge/{api_key}.svg endpoint for public badge display
- Badge only shows data if maintainer has marked it as public
- Added toggle control in dashboard UI to make badges public/private
- Badge displays unique user count using shields.io-style SVG
- Added badge markdown copy-to-clipboard functionality in dashboard

Database migration included to add new fields to api_keys table.

The badge allows maintainers to showcase their package adoption while maintaining
privacy by default. Maintainers must explicitly opt-in to make their badge public.
Enhanced badge security and privacy by using unique UUIDs for badge URLs:

- Added badge_uuid field to APIKey model (UUID type with unique index)
- UUID is automatically generated when badge is first made public
- Updated badge endpoints to use /api/badge/{uuid}.svg instead of API key
- Modified service methods to query by badge_uuid
- Updated dashboard UI to display UUID-based badge URLs
- Added repository method get_by_badge_uuid()

Benefits:
- API keys are no longer exposed in public badge URLs
- Each badge has a unique, non-guessable identifier
- Better separation of concerns (API key vs badge access)
- Maintains backward compatibility (old badges get UUID on first enable)

Migration updated to include badge_uuid column with unique constraint.
Simplified badge URLs by removing the /api prefix for cleaner, more user-friendly URLs:

- Changed router prefix from /api/badge to /badge
- Updated all badge URLs in dashboard template
- Badge URLs now follow pattern: /badge/{uuid}.svg
- Updated visibility toggle endpoint path
- Updated documentation to reflect new URLs

This provides shorter, cleaner badge URLs that are more typical for badge services.
Major refactoring to separate badge concerns from API keys table into dedicated badges table.

Database Changes:
- Created new badges table with columns: id, api_key_id, badge_uuid, is_public, created_at, updated_at
- Added foreign key constraint from badges.api_key_id to api_keys.id with CASCADE delete
- Added unique constraints on badge_uuid and api_key_id
- Removed badge_public and badge_uuid columns from api_keys table (were never in prod)
- Kept is_active and description columns on api_keys table

Model Changes:
- Created Badge model with relationship to APIKey
- Updated APIKey model to remove badge fields and add one-to-one relationship to Badge
- Badge model has generate_uuid() class method for UUID generation

Schema Changes:
- Created badge schemas (BadgeBase, BadgeCreate, BadgeUpdate, BadgeResponse, BadgePublicResponse)
- Updated APIKeyResponse to remove badge_public and badge_uuid fields
- Removed BadgeResponse from api_key schemas (moved to badge schemas)

Repository & Service:
- Created BadgeRepository with methods: get_by_api_key_id, get_by_uuid, create_badge, update_visibility
- Updated UnitOfWork to include badges repository
- Refactored APIKeyService.update_badge_visibility to work with Badge table
- Refactored APIKeyService.get_badge_data_by_uuid to query Badge table

API Changes:
- Updated badge endpoints to use new Badge schemas
- Changed visibility endpoint to use is_public field (was badge_public)
- Badge API now returns badge_uuid in response when creating/updating

Template Changes:
- Updated dashboard template to access badge through api_key.badge relationship
- Changed all references from api_key.badge_public to api_key.badge.is_public
- Changed all references from api_key.badge_uuid to api_key.badge.badge_uuid

Benefits:
- Better database normalization
- Clearer separation of concerns
- Easier to extend badge functionality in the future
- Cascade delete ensures badges are removed when API keys are deleted
- Can add more badge-specific features without cluttering api_keys table
@psincraian
psincraian merged commit 9d32a01 into main Nov 19, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants