Files
StarPunk/docs/reports/2025-11-28-v1.2.0-phase1-custom-slugs.md
Phil Skentelbery dd822a35b5 feat: v1.2.0-rc.1 - IndieWeb Features Release Candidate
Complete implementation of v1.2.0 "IndieWeb Features" release.

## Phase 1: Custom Slugs
- Optional custom slug field in note creation form
- Auto-sanitization (lowercase, hyphens only)
- Uniqueness validation with auto-numbering
- Read-only after creation to preserve permalinks
- Matches Micropub mp-slug behavior

## Phase 2: Author Discovery + Microformats2
- Automatic h-card discovery from IndieAuth identity URL
- 24-hour caching with graceful fallback
- Never blocks login (per ADR-061)
- Complete h-entry, h-card, h-feed markup
- All required Microformats2 properties
- rel-me links for identity verification
- Passes IndieWeb validation

## Phase 3: Media Upload
- Upload up to 4 images per note (JPEG, PNG, GIF, WebP)
- Automatic optimization with Pillow
  - Auto-resize to 2048px
  - EXIF orientation correction
  - 95% quality compression
- Social media-style layout (media top, text below)
- Optional captions for accessibility
- Integration with all feed formats (RSS, ATOM, JSON Feed)
- Date-organized storage with UUID filenames
- Immutable caching (1 year)

## Database Changes
- migrations/006_add_author_profile.sql - Author discovery cache
- migrations/007_add_media_support.sql - Media storage

## New Modules
- starpunk/author_discovery.py - h-card discovery and caching
- starpunk/media.py - Image upload, validation, optimization

## Documentation
- 4 new ADRs (056, 057, 058, 061)
- Complete design specifications
- Developer Q&A with 40+ questions answered
- 3 implementation reports
- 3 architect reviews (all approved)

## Testing
- 56 new tests for v1.2.0 features
- 842 total tests in suite
- All v1.2.0 feature tests passing

## Dependencies
- Added: mf2py (Microformats2 parser)
- Added: Pillow (image processing)

Version: 1.2.0-rc.1

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:02:20 -07:00

238 lines
6.9 KiB
Markdown

# v1.2.0 Phase 1: Custom Slugs - Implementation Report
**Date**: 2025-11-28
**Developer**: StarPunk Fullstack Developer Subagent
**Phase**: v1.2.0 Phase 1 of 3
**Status**: Complete
## Summary
Implemented custom slug input field in the web UI note creation form, allowing users to specify custom slugs when creating notes. This brings the web UI to feature parity with the Micropub API's `mp-slug` property.
## Implementation Overview
### What Was Implemented
1. **Custom Slug Input Field** (templates/admin/new.html)
- Added optional text input field for custom slugs
- HTML5 pattern validation for client-side guidance
- Helpful placeholder and helper text
- Positioned between content field and publish checkbox
2. **Read-Only Slug Display** (templates/admin/edit.html)
- Shows current slug as disabled input field
- Includes explanation that slugs cannot be changed
- Preserves permalink integrity
3. **Route Handler Updates** (starpunk/routes/admin.py)
- Updated `create_note_submit()` to accept `custom_slug` form parameter
- Passes custom slug to `create_note()` function
- Uses existing slug validation from `slug_utils.py`
4. **Comprehensive Test Suite** (tests/test_custom_slugs.py)
- 30 tests covering all aspects of custom slug functionality
- Tests validation, sanitization, uniqueness, web UI, and edge cases
- Verifies consistency with Micropub behavior
## Technical Details
### Backend Integration
The implementation leverages existing infrastructure:
- **Slug validation**: Uses `slug_utils.validate_and_sanitize_custom_slug()`
- **Slug sanitization**: Auto-converts to lowercase, removes invalid characters
- **Uniqueness checking**: Handled by existing `make_slug_unique_with_suffix()`
- **Error handling**: Graceful fallbacks for reserved slugs, hierarchical paths, emoji
### Frontend Behavior
**New Note Form**:
```html
<input type="text"
id="custom_slug"
name="custom_slug"
pattern="[a-z0-9-]+"
placeholder="leave-blank-for-auto-generation">
```
**Edit Note Form**:
```html
<input type="text"
id="slug"
value="{{ note.slug }}"
readonly
disabled>
```
### Validation Rules
Per `slug_utils.py`:
- Lowercase letters only
- Numbers allowed
- Hyphens allowed (not consecutive, not leading/trailing)
- Max length: 200 characters
- Reserved slugs: api, admin, auth, feed, static, etc.
### Error Handling
- **Hierarchical paths** (e.g., "path/to/note"): Rejected with error message
- **Reserved slugs**: Auto-suffixed (e.g., "api" becomes "api-note")
- **Invalid characters**: Sanitized to valid format
- **Duplicates**: Auto-suffixed with sequential number (e.g., "slug-2")
- **Unicode/emoji**: Falls back to timestamp-based slug
## Test Results
All 30 tests passing:
```
tests/test_custom_slugs.py::TestCustomSlugValidation (15 tests)
tests/test_custom_slugs.py::TestCustomSlugWebUI (9 tests)
tests/test_custom_slugs.py::TestCustomSlugMatchesMicropub (2 tests)
tests/test_custom_slugs.py::TestCustomSlugEdgeCases (4 tests)
```
### Test Coverage
**Validation Tests**:
- Lowercase conversion
- Invalid character sanitization
- Consecutive hyphen removal
- Leading/trailing hyphen trimming
- Unicode normalization
- Reserved slug detection
- Hierarchical path rejection
**Web UI Tests**:
- Custom slug creation
- Auto-generation fallback
- Uppercase conversion
- Invalid character handling
- Duplicate slug handling
- Reserved slug handling
- Hierarchical path error
- Read-only display in edit form
- Field presence in new form
**Micropub Consistency Tests**:
- Same validation rules
- Same sanitization behavior
**Edge Case Tests**:
- Empty slug
- Whitespace-only slug
- Emoji slug (timestamp fallback)
- Unicode slug normalization
## Files Modified
### Modified Files
- `templates/admin/new.html` - Added custom slug input field
- `templates/admin/edit.html` - Added read-only slug display
- `starpunk/routes/admin.py` - Updated route handler
- `CHANGELOG.md` - Added entry for v1.2.0 Phase 1
### New Files
- `tests/test_custom_slugs.py` - Comprehensive test suite (30 tests)
- `docs/reports/2025-11-28-v1.2.0-phase1-custom-slugs.md` - This report
### Unchanged Files (Used)
- `starpunk/notes.py` - Already had `custom_slug` parameter
- `starpunk/slug_utils.py` - Already had validation functions
## Design Decisions
### Why Read-Only in Edit Form?
Per developer Q&A Q2 and Q7:
- Changing slugs breaks permalinks
- Users need to see current slug
- Using `readonly` + `disabled` prevents form submission
- Clear explanatory text prevents confusion
### Why Same Validation as Micropub?
Per developer Q&A Q39:
- Consistency across all note creation methods
- Users shouldn't get different results from web UI vs API
- Reusing existing validation reduces bugs
### Why Auto-Sanitize Instead of Reject?
Per developer Q&A Q3 and slug_utils design:
- Better user experience (helpful vs. frustrating)
- Follows "be liberal in what you accept" principle
- Timestamp fallback ensures notes are never rejected
- Matches Micropub behavior (Q8: never fail requests)
## User Experience
### Creating a Note with Custom Slug
1. User fills in content
2. (Optional) User enters custom slug
3. System auto-sanitizes slug (lowercase, remove invalid chars)
4. System checks uniqueness, adds suffix if needed
5. Note created with custom or auto-generated slug
6. Success message shows final slug
### Creating a Note Without Custom Slug
1. User fills in content
2. User leaves slug field blank
3. System auto-generates slug from first 5 words
4. System checks uniqueness, adds suffix if needed
5. Note created with auto-generated slug
### Editing a Note
1. User opens edit form
2. Slug shown as disabled field
3. User can see but not change slug
4. Helper text explains why
## Compliance with Requirements
✅ Custom slug field in note creation form
✅ Field is optional (auto-generate if empty)
✅ Field is read-only on edit (prevent permalink breaks)
✅ Validate slug format: `^[a-z0-9-]+$`
✅ Auto-sanitize input (convert to lowercase, replace invalid chars)
✅ Check uniqueness before saving
✅ Show helpful error messages
✅ Tests passing
✅ CHANGELOG updated
✅ Implementation report created
## Next Steps
This completes **Phase 1 of v1.2.0**. The remaining phases are:
**Phase 2: Author Discovery + Microformats2** (4 hours)
- Implement h-card discovery from IndieAuth profile
- Add author_profile database table
- Update templates with microformats2 markup
- Integrate discovery with auth flow
**Phase 3: Media Upload** (6 hours)
- Add media upload to note creation form
- Implement media handling and storage
- Add media database table and migration
- Update templates to display media
- Add media management in edit form
## Notes
- Implementation took approximately 2 hours as estimated
- No blockers encountered
- All existing tests continue to pass
- No breaking changes to existing functionality
- Ready for architect review
---
**Implementation Status**: ✅ Complete
**Tests Status**: ✅ All Passing (30/30)
**Documentation Status**: ✅ Complete