···5050{"id":"01KGGK6V4WMC3X67E72JTE27A7","title":"Fix 'failed to convert record to feed item' warning for likes","description":"The firehose index logs a warning 'failed to convert record to feed item' when processing like records. This is expected behavior since likes are not displayed as standalone feed items - they're indexed for like counts but shouldn't appear in the feed.\n\nThe warning appears in internal/firehose/index.go:433 when recordToFeedItem returns an error for NSIDLike records (line 582-584).\n\nFix: Handle the like case silently without logging a warning, since this is expected behavior. Either:\n1. Skip like records before calling recordToFeedItem\n2. Return a special sentinel error from recordToFeedItem that indicates 'skip without warning'\n3. Check the collection type at the call site and skip likes there\n\nThis applies to both authenticated and unauthenticated users.","status":"completed","priority":"normal","labels":["bug"],"created_at":"2026-02-03T01:52:24.220349056Z","updated_at":"2026-02-03T01:54:54.698106017Z","completed_at":"2026-02-03T01:54:54.686934901Z"}
5151{"id":"01KGGNPG25M2AJ619P65FPMEH4","title":"Add OpenGraph metadata to brew pages","description":"Add dynamic OpenGraph metadata support for brew pages to enable rich social sharing previews.\n\n## Background\n\nCurrently, the site uses static OpenGraph tags in layout.templ:\n- og:title: \"Arabica - Coffee Brew Tracker\" (static)\n- og:description: \"Track your coffee brewing journey...\" (static) \n- og:type: \"website\" (static)\n- og:image: NOT PRESENT\n\nWhen users share brew links on social media, all previews look identical and provide no context about the specific brew.\n\n## Requirements\n\n### 1. Extend LayoutData struct\n\nAdd optional OpenGraph fields to `internal/web/components/layout.templ`:\n\n```go\ntype LayoutData struct {\n Title string\n IsAuthenticated bool\n UserDID string\n UserProfile *bff.UserProfile\n CSPNonce string\n \n // OpenGraph metadata (optional, falls back to defaults)\n OGTitle string\n OGDescription string\n OGImage string\n OGType string // \"website\", \"article\"\n OGUrl string // Canonical URL\n}\n```\n\n### 2. Update layout.templ head section\n\nModify meta tag rendering to use dynamic values with fallbacks:\n- If OGTitle set, use it; otherwise use site default\n- If OGDescription set, use it; otherwise use site default\n- If OGImage set, render og:image tag (currently missing entirely)\n- If OGUrl set, render og:url tag\n- Support og:type (default \"website\", brew pages use \"article\")\n\n### 3. Update buildLayoutData helper\n\nExtend `handlers.go` buildLayoutData() to accept optional OG parameters, or create a new helper `buildLayoutDataWithOG()`.\n\n### 4. Update HandleBrewView handler\n\nConstruct descriptive OG metadata from brew data:\n- **og:title**: \"{Bean Name} from {Origin} - Arabica\" or similar\n- **og:description**: \"{Rating}/10 - {Tasting Notes preview}\" or brew summary\n- **og:type**: \"article\"\n- **og:url**: The share URL (already computed as `shareURL`)\n- **og:image**: Static default for now (e.g., /static/og-brew-default.png)\n\nAvailable data for description construction:\n- brew.Rating, brew.TastingNotes\n- brew.Bean.Name, brew.Bean.Origin, brew.Bean.RoastLevel\n- brew.Bean.Roaster.Name\n- brew.CoffeeAmount, brew.WaterAmount, brew.Temperature\n\n### 5. Add Twitter Card support\n\nAdd Twitter-specific meta tags:\n- twitter:card = \"summary\" (or \"summary_large_image\" if we have images)\n- twitter:title, twitter:description (same as OG values)\n\n### 6. Static fallback image\n\nCreate or source a default OG image for brews:\n- Location: /static/og-brew-default.png or similar\n- Size: 1200x630px (recommended OG image size)\n- Design: Coffee-themed, includes Arabica branding\n\n## Acceptance Criteria\n\n- [ ] LayoutData extended with optional OG fields\n- [ ] layout.templ renders dynamic OG tags with fallbacks\n- [ ] Brew view pages include descriptive OG metadata\n- [ ] Twitter Card tags included\n- [ ] Static default OG image created and served\n- [ ] Existing pages (home, about, etc.) continue working with defaults\n- [ ] templ generate runs successfully\n- [ ] Manual testing: share brew URL to social platform preview tool\n\n## Implementation Notes\n\n- Follow existing patterns in handlers.go for data flow\n- Keep backwards compatible - pages not setting OG fields should use defaults\n- Consider creating a helper function to build OG description from brew data\n- The shareURL is already constructed in HandleBrewView (lines 695-701)\n\n## Future Enhancements (out of scope)\n\n- Dynamic image generation showing brew stats\n- Profile page OG metadata\n- Feed page OG metadata with recent brew preview","status":"completed","priority":"normal","assignee":"patrick","labels":["frontend","social"],"created_at":"2026-02-03T02:35:54.309356038Z","updated_at":"2026-02-03T02:53:43.170537883Z","completed_at":"2026-02-03T02:53:43.15817599Z","notes":[{"timestamp":"2026-02-03T02:53:36.100130152Z","author":"patrick","message":"Implementation complete:\n- Extended LayoutData with OG fields (OGTitle, OGDescription, OGImage, OGType, OGUrl)\n- Added helper methods ogTitle(), ogDescription(), ogType() with fallbacks\n- Updated layout.templ to render dynamic OG and Twitter Card meta tags\n- Added populateBrewOGMetadata() helper in handlers.go\n- Updated HandleBrewView to populate OG metadata from brew data\n- Added PublicURL to handler Config for absolute URLs\n- Added comprehensive tests for OG metadata generation\n- All tests pass"}]}
5252{"id":"01KGM9QB86N5RX50042DT1YN1N","title":"Consolidate Tailwind CSS usage","description":"Reduce Tailwind class duplication by leveraging existing CSS abstractions and adding missing utility classes.\n\n## Changes Required\n\n### 1. Add new utility classes to app.css\n- `.page-container` variants (sm, md, lg, xl) for max-width containers\n- `.avatar-sm`, `.avatar-md`, `.avatar-lg` size classes\n- `.section-box` for bg-brown-50 rounded sections\n\n### 2. Update templ components to use existing abstractions\n- WelcomeCard (shared.templ) - use `.card` instead of inline gradient\n- ProfileHeader, ProfileStat, ProfileTabs (profile.templ) - use `.card`\n- Header dropdown (header.templ) - use `.action-menu`\n- Login/CTA buttons (shared.templ) - use `.btn-primary`\n- Avatar component (shared.templ) - use new CSS classes instead of templ.KV\n\n### 3. Replace inline page containers\n- Replace `max-w-4xl mx-auto` etc. with `.page-container-*` classes across all pages\n\n## Acceptance Criteria\n- No visual changes to the site\n- Reduced class verbosity in templ files\n- Avatar component simplified\n- Consistent use of existing abstractions","status":"completed","priority":"normal","assignee":"patrick","labels":["css","refactor"],"created_at":"2026-02-04T12:23:36.966151046Z","updated_at":"2026-02-04T12:27:59.86186814Z","completed_at":"2026-02-04T12:27:59.850499942Z"}
5353+{"id":"01KHABKRB6RHR2AVE8PR28R66D","title":"Account request page (/join)","description":"Create a /join page where prospective users can request an arabica.systems PDS account.\n\n## Requirements\n- Simple form collecting: email address, preferred handle (optional), brief reason/message (optional)\n- On submit, sends an email notification to the admin (arabica.systems address TBD) with the request details\n- Stores the request in BoltDB for record-keeping\n- Shows a confirmation page after submission (\"Thanks, we'll review your request and email you an invite code\")\n- Rate limiting / basic spam prevention (e.g. honeypot field)\n- Matches the existing arabica.social design system (templ components, Tailwind, brown color palette)\n\n## Technical Details\n- Add SMTP support to the application (Go stdlib net/smtp or similar)\n- New env vars: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM, ADMIN_EMAIL\n- New BoltDB bucket for account requests\n- New handler + templ page + route\n- No authentication required (public page)\n\n## Acceptance Criteria\n- Form renders correctly and matches site design\n- Email is sent to admin on submission\n- Request is persisted in BoltDB\n- Confirmation shown to user\n- Basic input validation (valid email format)","status":"in_progress","priority":"normal","assignee":"patrick","labels":["frontend","backend"],"created_at":"2026-02-13T01:59:53.958852961Z","updated_at":"2026-02-13T02:05:46.199584438Z","notes":[{"timestamp":"2026-02-13T02:03:54.190326645Z","author":"patrick","message":"SMTP approach decided: use Go stdlib net/smtp. Support both implicit TLS (port 465 via tls.Dial + smtp.NewClient) and STARTTLS (port 587/2525). VPS may block ports 25/587, so port 465 and 2525 must work. No external email SaaS dependency needed."}]}
5454+{"id":"01KHABM3J6XPXFTCPW6JX378W7","title":"Account creation page (/join/create)","description":"Create a /join/create page where users with an invite code can create their arabica.systems PDS account.\n\n## Requirements\n- Form collecting: invite code, desired handle (with @arabica.systems suffix shown), email, password (with confirmation)\n- Calls describeServer on arabica.systems PDS first to get available domains and requirements\n- Calls com.atproto.server.createAccount on the PDS (arabica.systems) via XRPC\n- Shows success page with next steps (e.g. log in to arabica.social, set up your profile)\n- Proper error handling for: invalid invite code, handle taken, invalid password, etc.\n- Password strength indicator or requirements display\n- Matches existing arabica.social design system\n\n## Technical Details\n- The PDS is at arabica.systems - XRPC calls go to https://arabica.systems/xrpc/...\n- createAccount params: handle, email, password, inviteCode\n- describeServer tells us available handle domains and whether invites are required\n- New env var: PDS_SERVICE_URL (e.g. https://arabica.systems)\n- New handler + templ page + route\n- No arabica.social authentication required (public page)\n- Do NOT store the user's password - it goes directly to the PDS\n\n## Security Considerations \n- Password goes directly to PDS via server-side XRPC call (not client-side JS)\n- HTTPS only for the XRPC call\n- No password logging\n\n## Acceptance Criteria\n- Form renders with all required fields\n- Valid invite code + details creates account on PDS\n- Appropriate error messages for each failure mode (InvalidInviteCode, HandleNotAvailable, etc.)\n- Success page with clear next steps\n- Matches site design system","status":"open","priority":"normal","labels":["frontend","backend"],"created_at":"2026-02-13T02:00:05.446933524Z","updated_at":"2026-02-13T02:43:36.680372523Z"}