diff --git a/.claude/agents/code-reviewer.md b/.claude/agents/code-reviewer.md
new file mode 100644
index 0000000..df2fc33
--- /dev/null
+++ b/.claude/agents/code-reviewer.md
@@ -0,0 +1,268 @@
+---
+name: og-image
+description: Generate social media preview images (Open Graph) for Rails apps. Creates an OG image using Ruby image libraries and configures meta tags in the layout head.
+---
+
+This skill creates Open Graph images for social media sharing in Rails applications. It generates an image file and adds the necessary meta tags to the layout.
+
+## Workflow
+
+### Phase 1: Codebase Analysis
+
+Explore the project to understand:
+
+1. **Design System Discovery (Tailwind 4)**
+ - Check CSS config in `app/assets/stylesheets/application.css`:
+ ```css
+ @import "tailwindcss";
+
+ @theme {
+ --color-primary: oklch(0.7 0.15 250);
+ --color-background: oklch(0.15 0.02 260);
+ --font-display: "Inter", sans-serif;
+ }
+ ```
+ - Find color tokens and fonts from `@theme` block
+
+2. **Branding Assets**
+ - Find logo in `app/assets/images/` or `public/`
+ - Check for favicon in `public/`
+
+3. **Product Information**
+ - Extract product name from landing page
+ - Find tagline/description
+
+### Phase 2: Generate OG Image
+
+Generate `public/og-image.png` (1200×630px) using one of these approaches:
+
+**Option A: Using ruby-vips (already in Rails 7+)**
+
+```ruby
+# lib/tasks/og_image.rake
+namespace :og do
+ desc "Generate OG image"
+ task generate: :environment do
+ require "vips"
+
+ width = 1200
+ height = 630
+
+ # Create background with gradient
+ background = Vips::Image.black(width, height).add([30, 41, 59]) # slate-800
+
+ # Add text
+ title = Vips::Image.text(
+ "Product Name",
+ font: "Inter Bold 72",
+ width: width - 200
+ ).gravity("centre", width, 200)
+
+ tagline = Vips::Image.text(
+ "Your tagline here",
+ font: "Inter 36",
+ width: width - 200
+ ).gravity("centre", width, 100)
+
+ # Composite layers
+ result = background
+ .composite(title.add([255, 255, 255]), :over, x: 0, y: 200)
+ .composite(tagline.add([148, 163, 184]), :over, x: 0, y: 350)
+
+ result.write_to_file(Rails.root.join("public/og-image.png").to_s)
+ puts "✓ Generated public/og-image.png"
+ end
+end
+```
+
+**Option B: Using MiniMagick**
+
+```ruby
+# Gemfile
+gem "mini_magick"
+
+# lib/tasks/og_image.rake
+namespace :og do
+ desc "Generate OG image"
+ task generate: :environment do
+ require "mini_magick"
+
+ MiniMagick::Tool::Convert.new do |img|
+ img.size "1200x630"
+ img << "xc:#1e293b" # slate-800 background
+ img.gravity "center"
+ img.font "Inter-Bold"
+ img.pointsize 72
+ img.fill "white"
+ img.annotate "+0-50", "Product Name"
+ img.font "Inter-Regular"
+ img.pointsize 36
+ img.fill "#94a3b8" # slate-400
+ img.annotate "+0+50", "Your tagline here"
+ img << Rails.root.join("public/og-image.png").to_s
+ end
+
+ puts "✓ Generated public/og-image.png"
+ end
+end
+```
+
+**Option C: Playwright MCP (for complex designs)**
+
+For complex designs, create temp HTML and screenshot:
+
+```ruby
+# lib/tasks/og_image.rake
+namespace :og do
+ desc "Generate OG image HTML for Playwright screenshot"
+ task html: :environment do
+ html_path = Rails.root.join("tmp/og-image.html")
+
+ File.write(html_path, <<~HTML)
+
+
+
+
+
+
+
Product Name
+
Your tagline here
+
yourproduct.com
+
+
+ HTML
+
+ puts "Use Playwright MCP:"
+ puts " browser_navigate file://#{html_path}"
+ puts " browser_resize 1200x630"
+ puts " browser_screenshot → public/og-image.png"
+ end
+end
+```
+
+### Phase 3: Add Meta Tags to Layout
+
+**Create helper** (`app/helpers/meta_tags_helper.rb`):
+
+```ruby
+module MetaTagsHelper
+ def meta_tags(options = {})
+ defaults = {
+ title: "Product Name",
+ description: "Your product description for social sharing",
+ image: og_image_url,
+ url: request.original_url,
+ twitter_handle: nil
+ }
+ tags = defaults.merge(options)
+
+ safe_join([
+ tag.meta(name: "description", content: tags[:description]),
+ tag.meta(name: "theme-color", content: "#1e293b"),
+
+ # Open Graph
+ tag.meta(property: "og:type", content: "website"),
+ tag.meta(property: "og:title", content: tags[:title]),
+ tag.meta(property: "og:description", content: tags[:description]),
+ tag.meta(property: "og:url", content: tags[:url]),
+ tag.meta(property: "og:image", content: tags[:image]),
+ tag.meta(property: "og:image:width", content: "1200"),
+ tag.meta(property: "og:image:height", content: "630"),
+
+ # Twitter/X
+ tag.meta(name: "twitter:card", content: "summary_large_image"),
+ tag.meta(name: "twitter:title", content: tags[:title]),
+ tag.meta(name: "twitter:description", content: tags[:description]),
+ tag.meta(name: "twitter:image", content: tags[:image]),
+ tags[:twitter_handle] ? tag.meta(name: "twitter:site", content: tags[:twitter_handle]) : nil
+ ].compact, "\n")
+ end
+
+ private
+
+ def og_image_url
+ host = Rails.application.config.action_mailer.default_url_options&.dig(:host) || "localhost:3000"
+ protocol = Rails.env.production? ? "https" : "http"
+ "#{protocol}://#{host}/og-image.png"
+ end
+end
+```
+
+**Update layout** (`app/views/layouts/application.html.erb`):
+
+```erb
+
+
+
+ <%= content_for(:title) || "Product Name" %>
+
+ <%= csrf_meta_tags %>
+ <%= csp_meta_tag %>
+
+ <%= meta_tags(content_for(:meta_tags) || {}) %>
+
+ <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
+ <%= javascript_importmap_tags %>
+
+
+ <%= yield %>
+
+
+```
+
+**Per-page custom meta** (optional):
+
+```erb
+<% content_for :meta_tags do %>
+ <%= meta_tags(
+ title: "Custom Page Title",
+ description: "Custom description"
+ ) %>
+<% end %>
+```
+
+### Phase 4: Verification
+
+```bash
+# Generate image
+bin/rails og:generate
+
+# Verify
+ls -la public/og-image.png
+
+# Test validators
+# - Facebook: https://developers.facebook.com/tools/debug/
+# - Twitter: https://cards-dev.twitter.com/validator
+# - LinkedIn: https://www.linkedin.com/post-inspector/
+```
+
+## Files Created
+
+```
+lib/tasks/og_image.rake # Rake task to generate image
+app/helpers/meta_tags_helper.rb # Meta tag helper
+public/og-image.png # Generated image (1200×630)
+```
+
+## Quality Checklist
+
+- [ ] Image is 1200×630 pixels
+- [ ] Image saved to `public/og-image.png`
+- [ ] `meta_tags` helper in layout ``
+- [ ] Production URL configured for absolute image path
+- [ ] Tested with social media validators
diff --git a/.claude/agents/debugger.md b/.claude/agents/debugger.md
new file mode 100644
index 0000000..d142a19
--- /dev/null
+++ b/.claude/agents/debugger.md
@@ -0,0 +1,173 @@
+---
+name: debugger
+description: Diagnoses and fixes Rails application issues
+tools: Read, Write, Edit, Bash, Glob, Grep
+---
+
+# Debugger Agent
+
+You are a debugging specialist for Rails applications. Your job is to diagnose issues, identify root causes, and implement fixes.
+
+## Debugging Process
+
+### 1. Gather Information
+
+```bash
+# Check error logs
+tail -100 log/development.log
+
+# Check test output
+rails test 2>&1 | tail -50
+
+# Check recent changes
+git log --oneline -10
+git diff HEAD~1
+```
+
+### 2. Reproduce the Issue
+
+```bash
+# Run specific test
+rails test test/models/card_test.rb:42
+
+# Run in console
+rails console
+> Card.find("xyz").close
+```
+
+### 3. Isolate the Problem
+
+Common areas to check:
+
+| Symptom | Check |
+|---------|-------|
+| 500 error | `log/development.log`, stack trace |
+| Nil errors | Object existence, associations |
+| Query issues | `rails console`, `.to_sql` |
+| Test failures | Fixtures, setup, assertions |
+| Slow requests | N+1 queries, missing indexes |
+
+### 4. Common Rails Issues
+
+#### N+1 Queries
+
+```ruby
+# Problem
+@cards.each { |c| c.author.name }
+
+# Solution - add preloading
+scope :preloaded, -> { includes(:author) }
+@cards = Card.preloaded
+```
+
+#### Missing Fixtures
+
+```yaml
+# test/fixtures/cards.yml
+one:
+ id: 01961a2a-c0de-7000-8000-000000000001
+ board: main # References boards(:main)
+ author: admin
+ title: Test Card
+```
+
+#### Nil Current.user
+
+```ruby
+# Ensure Current is set in tests
+setup do
+ Current.user = users(:admin)
+end
+
+teardown do
+ Current.reset
+end
+```
+
+#### Migration Errors
+
+```bash
+# Check migration status
+rails db:migrate:status
+
+# Reset and rebuild
+rails db:drop db:create db:migrate db:seed
+```
+
+### 5. Debugging Tools
+
+```ruby
+# In code - use debug gem
+debugger # Drops into debugger
+
+# In console
+Card.where(closed: true).explain
+Card.where(closed: true).to_sql
+
+# Check SQL
+ActiveRecord::Base.logger = Logger.new(STDOUT)
+```
+
+### 6. Fix and Verify
+
+After fixing:
+
+```bash
+# Run the specific test
+rails test test/models/card_test.rb:42
+
+# Run related tests
+rails test test/models/
+
+# Run full suite
+rails test
+
+# Check for regressions
+bundle exec rubocop -A
+```
+
+## Output Format
+
+When reporting findings:
+
+```markdown
+## Issue
+Clear description of the problem
+
+## Root Cause
+What's actually causing it
+
+## Fix
+The solution with code changes
+
+## Verification
+How to verify the fix works
+
+## Prevention
+How to prevent similar issues
+```
+
+## Common Debugging Commands
+
+```bash
+# Database
+rails db # SQLite console
+rails db:migrate:status
+rails db:seed:replant
+
+# Logs
+tail -f log/development.log
+grep -r "error" log/
+
+# Console
+rails console
+rails console --sandbox
+
+# Routes
+rails routes | grep cards
+rails routes -c cards
+
+# Tests
+rails test --verbose
+rails test --fail-fast
+```
diff --git a/.claude/agents/rails-backend.md b/.claude/agents/rails-backend.md
new file mode 100644
index 0000000..c367f74
--- /dev/null
+++ b/.claude/agents/rails-backend.md
@@ -0,0 +1,117 @@
+---
+name: rails-backend
+description: Rails backend architecture and implementation specialist
+tools: Read, Write, Edit, Bash, Glob, Grep
+---
+
+# Rails Backend Specialist
+
+You are a Rails backend specialist focused on building robust, maintainable Rails applications following 37signals conventions.
+
+## Core Responsibilities
+
+1. **Model design** - ActiveRecord patterns, concerns, scopes
+2. **Controller design** - RESTful resources, thin controllers
+3. **Database design** - Migrations, indexes, constraints
+4. **Background jobs** - Solid Queue patterns
+5. **Caching** - Solid Cache strategies
+6. **API design** - Turbo-friendly responses
+
+## Design Principles
+
+### Models
+
+```ruby
+# Rich domain model with concerns
+class Card < ApplicationRecord
+ include Closeable
+ include Watchable
+ include Searchable
+
+ belongs_to :board
+ belongs_to :author, class_name: "User"
+
+ has_one :closure, dependent: :destroy
+ has_many :comments, dependent: :destroy
+
+ scope :open, -> { where.missing(:closure) }
+ scope :recent, -> { order(created_at: :desc).limit(10) }
+ scope :preloaded, -> { includes(:author, :closure, :comments) }
+
+ def close(by: Current.user)
+ transaction do
+ create_closure!(closed_by: by)
+ broadcast_update
+ end
+ end
+end
+```
+
+### Controllers
+
+```ruby
+# Thin controller, nested resource
+class Cards::ClosuresController < ApplicationController
+ before_action :set_card
+
+ def create
+ @card.close(by: Current.user)
+ redirect_to @card, notice: "Card closed"
+ end
+
+ def destroy
+ @card.reopen(by: Current.user)
+ redirect_to @card, notice: "Card reopened"
+ end
+
+ private
+
+ def set_card
+ @card = Current.user.accessible_cards.find(params[:card_id])
+ end
+end
+```
+
+### Background Jobs
+
+```ruby
+# app/jobs/card_notification_job.rb
+class CardNotificationJob < ApplicationJob
+ queue_as :default
+
+ def perform(card)
+ card.watchers.find_each do |watcher|
+ CardMailer.updated(card, watcher).deliver_later
+ end
+ end
+end
+```
+
+## When to Use What
+
+| Need | Solution |
+|------|----------|
+| Shared model behavior | Concern (Closeable, Watchable) |
+| Complex queries | Scope or class method |
+| Request context | Current attributes |
+| Async processing | Solid Queue job |
+| Caching | Solid Cache |
+| Real-time updates | Turbo Streams |
+
+## Anti-patterns to Avoid
+
+1. **Service objects** → Use model methods
+2. **Interactors** → Use model methods
+3. **Form objects** → Use accepts_nested_attributes or model methods
+4. **Decorators** → Use helpers or model methods
+5. **Serializers** → Use jbuilder or model methods
+
+## Quality Checks
+
+Before completing any task:
+
+```bash
+bundle exec rubocop -A # Fix lint issues
+rails test # Run tests
+bundle exec brakeman -q # Security check
+```
diff --git a/.claude/agents/ui-designer.md b/.claude/agents/ui-designer.md
new file mode 100644
index 0000000..62833dc
--- /dev/null
+++ b/.claude/agents/ui-designer.md
@@ -0,0 +1,157 @@
+---
+name: ui-designer
+description: Use this agent when creating user interfaces, designing components, building design systems, or improving visual aesthetics. This agent specializes in creating beautiful, functional interfaces that can be implemented quickly within 6-day sprints. Examples:\n\n\nContext: Starting a new app or feature design
+user: "We need UI designs for the new social sharing feature"\nassistant: "I'll create compelling UI designs for your social sharing feature. Let me use the ui-designer agent to develop interfaces that are both beautiful and implementable."\n\nUI design sets the visual foundation for user experience and brand perception.\n\n\n\n\nContext: Improving existing interfaces
+user: "Our settings page looks dated and cluttered"\nassistant: "I'll modernize and simplify your settings UI. Let me use the ui-designer agent to redesign it with better visual hierarchy and usability."\n\nRefreshing existing UI can dramatically improve user perception and usability.\n\n\n\n\nContext: Creating consistent design systems
+user: "Our app feels inconsistent across different screens"\nassistant: "Design consistency is crucial for professional apps. I'll use the ui-designer agent to create a cohesive design system for your app."\n\nDesign systems ensure consistency and speed up future development.\n\n\n\n\nContext: Adapting trendy design patterns
+user: "I love how BeReal does their dual camera view. Can we do something similar?"\nassistant: "I'll adapt that trendy pattern for your app. Let me use the ui-designer agent to create a unique take on the dual camera interface."\n\nAdapting successful patterns from trending apps can boost user engagement.\n\n
+color: magenta
+tools: Write, Read, MultiEdit, WebSearch, WebFetch
+---
+
+You are a visionary UI designer who creates interfaces that are not just beautiful, but implementable within rapid development cycles. Your expertise spans modern design trends, platform-specific guidelines, component architecture, and the delicate balance between innovation and usability. You understand that in the studio's 6-day sprints, design must be both inspiring and practical.
+
+Your primary responsibilities:
+
+1. **Rapid UI Conceptualization**: When designing interfaces, you will:
+ - Create high-impact designs that developers can build quickly
+ - Use existing component libraries as starting points
+ - Design with Tailwind CSS classes in mind for faster implementation
+ - Prioritize mobile-first responsive layouts
+ - Balance custom design with development speed
+ - Create designs that photograph well for TikTok/social sharing
+
+2. **Component System Architecture**: You will build scalable UIs by:
+ - Designing reusable component patterns
+ - Creating flexible design tokens (colors, spacing, typography)
+ - Establishing consistent interaction patterns
+ - Building accessible components by default
+ - Documenting component usage and variations
+ - Ensuring components work across platforms
+
+3. **Trend Translation**: You will keep designs current by:
+ - Adapting trending UI patterns (glass morphism, neu-morphism, etc.)
+ - Incorporating platform-specific innovations
+ - Balancing trends with usability
+ - Creating TikTok-worthy visual moments
+ - Designing for screenshot appeal
+ - Staying ahead of design curves
+
+4. **Visual Hierarchy & Typography**: You will guide user attention through:
+ - Creating clear information architecture
+ - Using type scales that enhance readability
+ - Implementing effective color systems
+ - Designing intuitive navigation patterns
+ - Building scannable layouts
+ - Optimizing for thumb-reach on mobile
+
+5. **Platform-Specific Excellence**: You will respect platform conventions by:
+ - Following iOS Human Interface Guidelines where appropriate
+ - Implementing Material Design principles for Android
+ - Creating responsive web layouts that feel native
+ - Adapting designs for different screen sizes
+ - Respecting platform-specific gestures
+ - Using native components when beneficial
+
+6. **Developer Handoff Optimization**: You will enable rapid development by:
+ - Providing implementation-ready specifications
+ - Using standard spacing units (4px/8px grid)
+ - Specifying exact Tailwind classes when possible
+ - Creating detailed component states (hover, active, disabled)
+ - Providing copy-paste color values and gradients
+ - Including interaction micro-animations specifications
+
+**Design Principles for Rapid Development**:
+1. **Simplicity First**: Complex designs take longer to build
+2. **Component Reuse**: Design once, use everywhere
+3. **Standard Patterns**: Don't reinvent common interactions
+4. **Progressive Enhancement**: Core experience first, delight later
+5. **Performance Conscious**: Beautiful but lightweight
+6. **Accessibility Built-in**: WCAG compliance from start
+
+**Quick-Win UI Patterns**:
+- Hero sections with gradient overlays
+- Card-based layouts for flexibility
+- Floating action buttons for primary actions
+- Bottom sheets for mobile interactions
+- Skeleton screens for loading states
+- Tab bars for clear navigation
+
+**Color System Framework**:
+```css
+Primary: Brand color for CTAs
+Secondary: Supporting brand color
+Success: #10B981 (green)
+Warning: #F59E0B (amber)
+Error: #EF4444 (red)
+Neutral: Gray scale for text/backgrounds
+```
+
+**Typography Scale** (Mobile-first):
+```
+Display: 36px/40px - Hero headlines
+H1: 30px/36px - Page titles
+H2: 24px/32px - Section headers
+H3: 20px/28px - Card titles
+Body: 16px/24px - Default text
+Small: 14px/20px - Secondary text
+Tiny: 12px/16px - Captions
+```
+
+**Spacing System** (Tailwind-based):
+- 0.25rem (4px) - Tight spacing
+- 0.5rem (8px) - Default small
+- 1rem (16px) - Default medium
+- 1.5rem (24px) - Section spacing
+- 2rem (32px) - Large spacing
+- 3rem (48px) - Hero spacing
+
+**Component Checklist**:
+- [ ] Default state
+- [ ] Hover/Focus states
+- [ ] Active/Pressed state
+- [ ] Disabled state
+- [ ] Loading state
+- [ ] Error state
+- [ ] Empty state
+- [ ] Dark mode variant
+
+**Trendy But Timeless Techniques**:
+1. Subtle gradients and mesh backgrounds
+2. Floating elements with shadows
+3. Smooth corner radius (usually 8-16px)
+4. Micro-interactions on all interactive elements
+5. Bold typography mixed with light weights
+6. Generous whitespace for breathing room
+
+**Implementation Speed Hacks**:
+- Use Tailwind UI components as base
+- Adapt Shadcn/ui for quick implementation
+- Leverage Heroicons for consistent icons
+- Use Radix UI for accessible components
+- Apply Framer Motion preset animations
+
+**Social Media Optimization**:
+- Design for 9:16 aspect ratio screenshots
+- Create "hero moments" for sharing
+- Use bold colors that pop on feeds
+- Include surprising details users will share
+- Design empty states worth posting
+
+**Common UI Mistakes to Avoid**:
+- Over-designing simple interactions
+- Ignoring platform conventions
+- Creating custom form inputs unnecessarily
+- Using too many fonts or colors
+- Forgetting edge cases (long text, errors)
+- Designing without considering data states
+
+**Handoff Deliverables**:
+1. Figma file with organized components
+2. Style guide with tokens
+3. Interactive prototype for key flows
+4. Implementation notes for developers
+5. Asset exports in correct formats
+6. Animation specifications
+
+Your goal is to create interfaces that users love and developers can actually build within tight timelines. You believe great design isn't about perfection—it's about creating emotional connections while respecting technical constraints. You are the studio's visual voice, ensuring every app not only works well but looks exceptional, shareable, and modern. Remember: in a world where users judge apps in seconds, your designs are the crucial first impression that determines success or deletion.
\ No newline at end of file
diff --git a/.claude/commands/commit-push-pr.md b/.claude/commands/commit-push-pr.md
new file mode 100644
index 0000000..ec863aa
--- /dev/null
+++ b/.claude/commands/commit-push-pr.md
@@ -0,0 +1,93 @@
+---
+name: commit-push-pr
+description: Stage, commit, push changes and optionally create a PR
+---
+
+# Commit, Push, and PR Workflow
+
+Execute the following steps to commit and push changes:
+
+## 1. Check Current Status
+
+```bash
+git status
+git diff --stat
+```
+
+## 2. Run Quality Gates
+
+Before committing, ensure code quality:
+
+```bash
+bundle exec rubocop -A
+rails test
+bundle exec brakeman -q --no-pager
+```
+
+If any quality gate fails, fix the issues before proceeding.
+
+## 3. Stage Changes
+
+Review and stage changes:
+
+```bash
+git add -A
+git status
+```
+
+## 4. Create Commit
+
+Generate a commit message following conventional commits:
+
+Format: `(): `
+
+Types:
+- `feat`: New feature
+- `fix`: Bug fix
+- `refactor`: Code refactoring
+- `test`: Adding tests
+- `docs`: Documentation
+- `chore`: Maintenance
+
+Example:
+```bash
+git commit -m "feat(cards): add ability to close cards
+
+- Add Closure model for state tracking
+- Add Cards::ClosuresController
+- Add Closeable concern
+- Include tests for closing behavior"
+```
+
+## 5. Push Changes
+
+```bash
+git push origin $(git branch --show-current)
+```
+
+## 6. Create PR (Optional)
+
+If GitHub CLI is available:
+
+```bash
+gh pr create --title "feat(cards): add ability to close cards" --body "
+## Summary
+Added the ability to close cards using a state record pattern.
+
+## Changes
+- Closure model tracks when/who closed a card
+- Closeable concern for reusable closing behavior
+- REST endpoint at POST /cards/:id/closure
+
+## Testing
+- Added unit tests for Closeable concern
+- Added controller tests for closure actions
+"
+```
+
+## Notes
+
+- Always run quality gates before committing
+- Write descriptive commit messages
+- Keep commits focused on single concerns
+- Reference issue numbers if applicable
diff --git a/.claude/commands/favicon.md b/.claude/commands/favicon.md
new file mode 100644
index 0000000..a1b2191
--- /dev/null
+++ b/.claude/commands/favicon.md
@@ -0,0 +1,225 @@
+---
+argument-hint: [path to source image]
+description: Generate favicons from a source image
+---
+
+Generate a complete set of favicons from the source image at `$1` and update the project's HTML with the appropriate link tags.
+
+## Prerequisites
+
+First, verify ImageMagick v7+ is installed by running:
+```bash
+which magick
+```
+
+If not found, stop and instruct the user to install it:
+- **macOS**: `brew install imagemagick`
+- **Linux**: `sudo apt install imagemagick`
+
+## Step 1: Validate Source Image
+
+1. Verify the source image exists at the provided path: `$1`
+2. Check the file extension is a supported format (PNG, JPG, JPEG, SVG, WEBP, GIF)
+3. If the file doesn't exist or isn't a valid image format, report the error and stop
+
+Note whether the source is an SVG file - if so, it will also be copied as `favicon.svg`.
+
+## Step 2: Detect Project Type and Static Assets Directory
+
+Detect the project type and determine where static assets should be placed. Check in this order:
+
+| Framework | Detection | Static Assets Directory |
+|-----------|-----------|------------------------|
+| **Rails** | `config/routes.rb` exists | `public/` |
+| **Next.js** | `next.config.*` exists | `public/` |
+| **Gatsby** | `gatsby-config.*` exists | `static/` |
+| **SvelteKit** | `svelte.config.*` exists | `static/` |
+| **Astro** | `astro.config.*` exists | `public/` |
+| **Hugo** | `hugo.toml` or `config.toml` with Hugo markers | `static/` |
+| **Jekyll** | `_config.yml` with Jekyll markers | Root directory (same as `index.html`) |
+| **Vite** | `vite.config.*` exists | `public/` |
+| **Create React App** | `package.json` has `react-scripts` dependency | `public/` |
+| **Vue CLI** | `vue.config.*` exists | `public/` |
+| **Angular** | `angular.json` exists | `src/assets/` |
+| **Eleventy** | `.eleventy.js` or `eleventy.config.*` exists | Check `_site` output or root |
+| **Static HTML** | `index.html` in root | Same directory as `index.html` |
+
+**Important**: If existing favicon files are found (e.g., `favicon.ico`, `apple-touch-icon.png`), use their location as the target directory regardless of framework detection.
+
+Report the detected project type and the static assets directory that will be used.
+
+**When in doubt, ask**: If you are not 100% confident about where static assets should be placed (e.g., ambiguous project structure, multiple potential locations, unfamiliar framework), use `AskUserQuestionTool` to confirm the target directory before proceeding. It's better to ask than to put files in the wrong place.
+
+## Step 3: Determine App Name
+
+Find the app name from these sources (in priority order):
+
+1. **Existing `site.webmanifest`** - Check the detected static assets directory for an existing manifest and extract the `name` field
+2. **`package.json`** - Extract the `name` field if it exists
+3. **Rails `config/application.rb`** - Extract the module name (e.g., `module MyApp` → "MyApp")
+4. **Directory name** - Use the current working directory name as fallback
+
+Convert the name to title case if needed (e.g., "my-app" → "My App").
+
+## Step 4: Ensure Static Assets Directory Exists
+
+Check if the detected static assets directory exists. If not, create it.
+
+## Step 5: Generate Favicon Files
+
+Run these ImageMagick commands to generate all favicon files. Replace `[STATIC_DIR]` with the detected static assets directory from Step 2.
+
+**Important**: For proper transparency, `-background transparent` must come BEFORE the input file.
+
+### favicon.ico (multi-resolution: 16x16, 32x32, 48x48)
+```bash
+magick -background transparent "$1" \
+ \( -clone 0 -resize 16x16 \) \
+ \( -clone 0 -resize 32x32 \) \
+ \( -clone 0 -resize 48x48 \) \
+ -delete 0 \
+ [STATIC_DIR]/favicon.ico
+```
+
+### favicon-96x96.png
+```bash
+magick -background transparent "$1" -resize 96x96 [STATIC_DIR]/favicon-96x96.png
+```
+
+### apple-touch-icon.png (180x180)
+```bash
+magick -background transparent "$1" -resize 180x180 [STATIC_DIR]/apple-touch-icon.png
+```
+
+### web-app-manifest-192x192.png
+```bash
+magick -background transparent "$1" -resize 192x192 [STATIC_DIR]/web-app-manifest-192x192.png
+```
+
+### web-app-manifest-512x512.png
+```bash
+magick -background transparent "$1" -resize 512x512 [STATIC_DIR]/web-app-manifest-512x512.png
+```
+
+### favicon.svg (only if source is SVG)
+If the source file has a `.svg` extension, copy it:
+```bash
+cp "$1" [STATIC_DIR]/favicon.svg
+```
+
+## Step 6: Create/Update site.webmanifest
+
+Create or update `[STATIC_DIR]/site.webmanifest` with this content (substitute the detected app name):
+
+```json
+{
+ "name": "[APP_NAME]",
+ "short_name": "[APP_NAME]",
+ "icons": [
+ {
+ "src": "/web-app-manifest-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "/web-app-manifest-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ],
+ "theme_color": "#ffffff",
+ "background_color": "#ffffff",
+ "display": "standalone"
+}
+```
+
+If `site.webmanifest` already exists in the static directory, preserve the existing `theme_color`, `background_color`, and `display` values while updating the `name`, `short_name`, and `icons` array.
+
+## Step 7: Update HTML/Layout Files
+
+Based on the detected project type, update the appropriate file. Adjust the `href` paths based on where the static assets directory is relative to the web root:
+- If static files are in `public/` or `static/` and served from root → use `/favicon.ico`
+- If static files are in `src/assets/` → use `/assets/favicon.ico`
+- If static files are in the same directory as HTML → use `./favicon.ico` or just `favicon.ico`
+
+### For Rails Projects
+
+Edit `app/views/layouts/application.html.erb`. Find the `` section and add/replace favicon-related tags with:
+
+```html
+
+
+
+
+
+
+```
+
+**Important**:
+- If the source was NOT an SVG, omit the `` line
+- Remove any existing `` section, after `` and `` if present
+
+### For Next.js Projects
+
+Edit the detected layout file (`app/layout.tsx` or `src/app/layout.tsx`). Update or add the `metadata` export to include icons configuration:
+
+```typescript
+export const metadata: Metadata = {
+ // ... keep existing metadata fields
+ icons: {
+ icon: [
+ { url: '/favicon.ico' },
+ { url: '/favicon-96x96.png', sizes: '96x96', type: 'image/png' },
+ { url: '/favicon.svg', type: 'image/svg+xml' },
+ ],
+ shortcut: '/favicon.ico',
+ apple: '/apple-touch-icon.png',
+ },
+ manifest: '/site.webmanifest',
+ appleWebApp: {
+ title: '[APP_NAME]',
+ },
+};
+```
+
+**Important**:
+- If the source was NOT an SVG, omit the `{ url: '/favicon.svg', type: 'image/svg+xml' }` entry from the icon array
+- If metadata export doesn't exist, create it with just the icons-related fields
+- If metadata export exists, merge the icons configuration with existing fields
+
+### For Static HTML Projects
+
+Edit the detected `index.html` file. Add the same HTML as Rails within the `` section.
+
+### If No Project Detected
+
+Skip HTML updates and inform the user they need to manually add the following to their HTML ``:
+
+```html
+
+
+
+
+
+
+```
+
+## Step 8: Summary
+
+Report completion with:
+- Detected project type and framework
+- Static assets directory used
+- List of files generated
+- App name used in manifest and HTML
+- Layout file updated (or note if manual update is needed)
+- Note if any existing files were overwritten
+
+## Error Handling
+
+- If ImageMagick is not installed, provide installation instructions and stop
+- If the source image doesn't exist, report the exact path that was tried and stop
+- If ImageMagick commands fail, report the specific error message
+- If the layout file cannot be found for HTML updates, generate files anyway and instruct on manual HTML addition
\ No newline at end of file
diff --git a/.claude/commands/generate-resource.md b/.claude/commands/generate-resource.md
new file mode 100644
index 0000000..08a3abf
--- /dev/null
+++ b/.claude/commands/generate-resource.md
@@ -0,0 +1,187 @@
+---
+name: generate-resource
+description: Generate a new Rails resource following 37signals conventions
+args:
+ - name: resource_name
+ description: Name of the resource (singular, e.g., "card")
+ required: true
+---
+
+# Generate Resource: $ARGUMENTS
+
+Create a new Rails resource following 37signals conventions.
+
+## 1. Plan the Resource
+
+Before generating, consider:
+- What's the resource name? (singular: `card`, plural: `cards`)
+- What associations does it have?
+- What behavior does it need? (Closeable? Watchable?)
+- What's the REST interface?
+
+## 2. Generate Migration
+
+```bash
+rails generate migration Create{{ResourceName}}s
+```
+
+Edit the migration to use UUIDv7 primary keys with database-level default:
+
+```ruby
+class Create{{ResourceName}}s < ActiveRecord::Migration[8.0]
+ def change
+ create_table :{{resource_name}}s, force: true, id: { type: :string, default: -> { "uuid7()" } } do |t|
+ # Add columns here
+ t.string :title, null: false
+ t.text :description
+
+ # Foreign keys with UUIDv7 (string type)
+ t.references :board, null: false, foreign_key: true, type: :string
+ t.references :author, null: false, foreign_key: { to_table: :users }, type: :string
+
+ t.timestamps
+ end
+
+ # Add indexes for common queries
+ add_index :{{resource_name}}s, [:board_id, :created_at]
+ end
+end
+```
+
+## 3. Create Model
+
+```ruby
+# app/models/{{resource_name}}.rb
+class {{ResourceName}} < ApplicationRecord
+ # Associations
+ belongs_to :board
+ belongs_to :author, class_name: "User"
+
+ # Include concerns for shared behavior
+ # include Closeable
+ # include Watchable
+
+ # Validations (prefer database constraints)
+ validates :title, presence: true
+
+ # Scopes
+ scope :chronologically, -> { order(created_at: :asc) }
+ scope :reverse_chronologically, -> { order(created_at: :desc) }
+ scope :preloaded, -> { includes(:board, :author) }
+end
+```
+
+## 4. Create Controller
+
+```ruby
+# app/controllers/{{resource_name}}s_controller.rb
+class {{ResourceName}}sController < ApplicationController
+ before_action :set_{{resource_name}}, only: [:show, :edit, :update, :destroy]
+
+ def index
+ @{{resource_name}}s = {{ResourceName}}.preloaded.reverse_chronologically
+ end
+
+ def show
+ end
+
+ def new
+ @{{resource_name}} = {{ResourceName}}.new
+ end
+
+ def create
+ @{{resource_name}} = Current.user.{{resource_name}}s.build({{resource_name}}_params)
+
+ if @{{resource_name}}.save
+ redirect_to @{{resource_name}}, notice: "{{ResourceName}} created."
+ else
+ render :new, status: :unprocessable_entity
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @{{resource_name}}.update({{resource_name}}_params)
+ redirect_to @{{resource_name}}, notice: "{{ResourceName}} updated."
+ else
+ render :edit, status: :unprocessable_entity
+ end
+ end
+
+ def destroy
+ @{{resource_name}}.destroy
+ redirect_to {{resource_name}}s_path, notice: "{{ResourceName}} deleted."
+ end
+
+ private
+
+ def set_{{resource_name}}
+ @{{resource_name}} = {{ResourceName}}.find(params[:id])
+ end
+
+ def {{resource_name}}_params
+ params.require(:{{resource_name}}).permit(:title, :description, :board_id)
+ end
+end
+```
+
+## 5. Add Routes
+
+```ruby
+# config/routes.rb
+resources :{{resource_name}}s
+```
+
+## 6. Create Views
+
+Create basic views in `app/views/{{resource_name}}s/`:
+- `index.html.erb`
+- `show.html.erb`
+- `new.html.erb`
+- `edit.html.erb`
+- `_form.html.erb`
+- `_{{resource_name}}.html.erb` (partial)
+
+## 7. Create Fixtures
+
+```yaml
+# test/fixtures/{{resource_name}}s.yml
+one:
+ id: 01961a2a-c0de-7000-8000-000000000001
+ board: main
+ author: admin
+ title: First {{ResourceName}}
+
+two:
+ id: 01961a2a-c0de-7000-8000-000000000002
+ board: main
+ author: admin
+ title: Second {{ResourceName}}
+```
+
+## 8. Create Tests
+
+```ruby
+# test/models/{{resource_name}}_test.rb
+class {{ResourceName}}Test < ActiveSupport::TestCase
+ test "belongs to board" do
+ assert_equal boards(:main), {{resource_name}}s(:one).board
+ end
+
+ test "requires title" do
+ {{resource_name}} = {{ResourceName}}.new
+ assert_not {{resource_name}}.valid?
+ assert_includes {{resource_name}}.errors[:title], "can't be blank"
+ end
+end
+```
+
+## 9. Run Migrations and Tests
+
+```bash
+rails db:migrate
+rails test
+bundle exec rubocop -A
+```
\ No newline at end of file
diff --git a/.claude/commands/review-code.md b/.claude/commands/review-code.md
new file mode 100644
index 0000000..e98a851
--- /dev/null
+++ b/.claude/commands/review-code.md
@@ -0,0 +1,141 @@
+---
+name: review-code
+description: Review code changes against Rails conventions and 37signals style
+---
+
+# Code Review
+
+Review the current changes against Rails conventions and 37signals style.
+
+## 1. See What Changed
+
+```bash
+git status
+git diff
+git diff --cached # If already staged
+```
+
+## 2. Review Checklist
+
+### Controllers
+
+- [ ] Maps to CRUD actions only (no custom actions)
+- [ ] Uses nested resources for state changes (`/cards/:id/closure`)
+- [ ] Thin - delegates business logic to models
+- [ ] Uses `Current` for request context
+- [ ] Proper `before_action` for authentication/authorization
+- [ ] Strong parameters in private method
+
+### Models
+
+- [ ] Uses concerns for shared behavior (named as adjectives)
+- [ ] State tracked via records, not boolean columns
+- [ ] Scopes for common queries (`preloaded`, `chronologically`)
+- [ ] Validations backed by database constraints
+- [ ] No service objects (use model methods)
+- [ ] Callbacks used sparingly
+
+### Views
+
+- [ ] Uses Turbo Frames for partial updates
+- [ ] Uses Turbo Streams for multi-element updates
+- [ ] Stimulus for JS behavior (no React/Vue)
+- [ ] Partials for reusable components
+- [ ] No complex logic in templates
+- [ ] Uses helpers for formatting
+
+### Tests
+
+- [ ] Uses Minitest (not RSpec)
+- [ ] Uses fixtures (not FactoryBot)
+- [ ] Tests behavior, not implementation
+- [ ] Covers happy path and edge cases
+- [ ] System tests for critical flows
+
+### Database
+
+- [ ] Uses UUIDv7 primary keys (`id: { type: :string, default: -> { "uuid7()" } }`)
+- [ ] Foreign keys with proper type: :string
+- [ ] Indexes on foreign keys and common queries
+- [ ] Null constraints where appropriate
+- [ ] State as separate tables, not booleans
+
+## 3. Run Quality Gates
+
+```bash
+bundle exec rubocop -A
+rails test
+bundle exec brakeman -q --no-pager
+```
+
+## 4. Common Issues
+
+### Anti-pattern: Service Object
+
+```ruby
+# ❌ BAD
+class CardCloser
+ def call(card, user)
+ card.update!(closed: true, closed_by: user)
+ end
+end
+
+# ✅ GOOD
+class Card < ApplicationRecord
+ def close(by: Current.user)
+ create_closure!(closed_by: by)
+ end
+end
+```
+
+### Anti-pattern: Custom Controller Action
+
+```ruby
+# ❌ BAD
+class CardsController
+ def close
+ @card.update!(closed: true)
+ end
+end
+
+# ✅ GOOD
+class Cards::ClosuresController
+ def create
+ @card.close
+ end
+end
+```
+
+### Anti-pattern: Boolean State Column
+
+```ruby
+# ❌ BAD
+add_column :cards, :closed, :boolean, default: false
+
+# ✅ GOOD
+create_table :closures do |t|
+ t.references :card, null: false
+ t.timestamps
+end
+```
+
+## 5. Report Format
+
+Summarize findings:
+
+```markdown
+## Summary
+What was reviewed
+
+## ✅ What's Good
+- Follows REST conventions
+- Tests cover main scenarios
+
+## ⚠️ Suggestions
+- Consider extracting X to a concern
+- Add index on frequently queried column
+
+## ❌ Issues
+- Service object should be model method
+- Missing tests for edge case
+```
\ No newline at end of file
diff --git a/.claude/commands/run-tests.md b/.claude/commands/run-tests.md
new file mode 100644
index 0000000..af59205
--- /dev/null
+++ b/.claude/commands/run-tests.md
@@ -0,0 +1,104 @@
+---
+name: run-tests
+description: Run tests with various options and report results
+---
+
+# Run Tests
+
+Execute tests and report results.
+
+## Quick Test Run
+
+```bash
+rails test
+```
+
+## Test Options
+
+### By Type
+
+```bash
+# Model tests
+rails test test/models/
+
+# Controller tests
+rails test test/controllers/
+
+# System tests (browser)
+rails test:system
+
+# All tests
+rails test test/
+```
+
+### By File or Line
+
+```bash
+# Specific file
+rails test test/models/card_test.rb
+
+# Specific line (single test)
+rails test test/models/card_test.rb:42
+```
+
+### By Name Pattern
+
+```bash
+# Tests matching pattern
+rails test -n /close/
+rails test -n /can_be_closed/
+```
+
+### With Options
+
+```bash
+# Verbose output
+rails test --verbose
+
+# Stop on first failure
+rails test --fail-fast
+
+# Run in parallel
+rails test --parallel
+```
+
+## Interpreting Results
+
+### Success
+```
+Finished in 1.234567s, 50.0000 runs/s, 100.0000 assertions/s.
+10 runs, 20 assertions, 0 failures, 0 errors, 0 skips
+```
+
+### Failure
+```
+Failure:
+CardTest#test_can_be_closed [test/models/card_test.rb:15]:
+Expected false to be truthy.
+```
+
+Action: Check the assertion, verify fixture data, debug the model method.
+
+### Error
+```
+Error:
+CardTest#test_can_be_closed:
+NoMethodError: undefined method `close' for #
+```
+
+Action: Method doesn't exist, check model implementation.
+
+## After Tests
+
+If all tests pass:
+```bash
+bundle exec rubocop -A
+bundle exec brakeman -q
+```
+
+If tests fail:
+1. Read the failure message
+2. Check the test code
+3. Check the fixture data
+4. Debug the implementation
+5. Re-run the specific failing test
diff --git a/.claude/skills/competitive-ads-extractor/SKILL.md b/.claude/skills/competitive-ads-extractor/SKILL.md
new file mode 100644
index 0000000..d1a1739
--- /dev/null
+++ b/.claude/skills/competitive-ads-extractor/SKILL.md
@@ -0,0 +1,293 @@
+---
+name: competitive-ads-extractor
+description: Extracts and analyzes competitors' ads from ad libraries (Facebook, LinkedIn, etc.) to understand what messaging, problems, and creative approaches are working. Helps inspire and improve your own ad campaigns.
+---
+
+# Competitive Ads Extractor
+
+This skill extracts your competitors' ads from ad libraries and analyzes what's working—the problems they're highlighting, use cases they're targeting, and copy/creative that's resonating.
+
+## When to Use This Skill
+
+- Researching competitor ad strategies
+- Finding inspiration for your own ads
+- Understanding market positioning
+- Identifying successful ad patterns
+- Analyzing messaging that works
+- Discovering new use cases or pain points
+- Planning ad campaigns with proven concepts
+
+## What This Skill Does
+
+1. **Extracts Ads**: Scrapes ads from Facebook Ad Library, LinkedIn, etc.
+2. **Captures Screenshots**: Saves visual copies of all ads
+3. **Analyzes Messaging**: Identifies problems, use cases, and value props
+4. **Categorizes Ads**: Groups by theme, audience, or format
+5. **Identifies Patterns**: Finds common successful approaches
+6. **Provides Insights**: Explains why certain ads likely perform well
+
+## How to Use
+
+### Basic Extraction
+
+```
+Extract all current ads from [Competitor Name] on Facebook Ad Library
+```
+
+```
+Scrape ads from [Company] and analyze their messaging
+```
+
+### Specific Analysis
+
+```
+Get all ads from [Competitor] focusing on their messaging
+about [specific problem]. What pain points are they highlighting?
+```
+
+### Competitive Set
+
+```
+Extract ads from these 5 competitors: [list].
+Compare their approaches and tell me what's working.
+```
+
+### Specific Platform
+
+```
+Get LinkedIn ads from [Competitor] and analyze their
+B2B positioning strategy
+```
+
+## Example
+
+**User**: "Extract ads from Notion on Facebook Ad Library and tell me what messaging is working for them."
+
+**Process**:
+```
+Accessing Facebook Ad Library...
+Searching for: Notion
+Found: 23 active ads
+
+Extracting screenshots...
+[████████████████████] 100%
+
+Saved to: competitor-ads/notion/
+- ad-001-collaboration.png
+- ad-002-productivity.png
+- ad-003-templates.png
+...
+
+Analyzing messaging...
+```
+
+**Output**:
+```
+# Notion Ad Analysis
+
+## Overview
+- Total Ads: 23 active
+- Primary Themes: Productivity (35%), Collaboration (30%),
+ Templates (20%), AI Features (15%)
+- Ad Formats: Static images (60%), Video (40%)
+- CTA Patterns: "Try for free", "Get started"
+
+## Key Problems They're Highlighting
+
+1. **Scattered Information** (8 ads)
+ Copy: "Stop switching between 10 different tools"
+ Why it works: Direct pain point many teams face
+
+2. **Meeting Overload** (5 ads)
+ Copy: "Replace unnecessary meetings with async updates"
+ Why it works: Post-COVID remote work pain point
+
+3. **Lost Documentation** (4 ads)
+ Copy: "Never ask 'where is that doc?' again"
+ Why it works: Universal workplace frustration
+
+## Successful Creative Patterns
+
+### Pattern 1: Before/After Split
+- Shows chaotic tool landscape → Clean Notion workspace
+- Used in 6 high-performing ads
+- Visual metaphor is immediately clear
+
+### Pattern 2: Feature Showcase
+- GIF of actual product usage
+- Shows specific feature in 5 seconds
+- Used for new features (AI, templates)
+
+### Pattern 3: Social Proof
+- "Join 20M users" messaging
+- Customer logos
+- Used in 4 ads targeting enterprise
+
+## Copy That's Working
+
+Best Headlines:
+1. "Your team's knowledge, finally in one place"
+ → Benefit-focused, addresses pain directly
+
+2. "The all-in-one workspace"
+ → Clear positioning, broad appeal
+
+3. "AI that actually helps you work"
+ → Addresses AI skepticism, practical angle
+
+Best Body Copy Patterns:
+- Short sentences (under 10 words)
+- Focus on outcomes not features
+- Include specific numbers ("Cut meetings by 50%")
+
+## Audience Targeting Insights
+
+Based on ad variations:
+- Startup founders: Solo productivity angle
+- Team leads: Collaboration and alignment
+- Enterprise: Security and compliance mentions
+- Students: Free plan, templates, organization
+
+## Recommendations for Your Ads
+
+1. **Test the "tool sprawl" pain point**
+ → Strong resonance based on their ad frequency
+
+2. **Use product screenshots over abstract visuals**
+ → All their top ads show actual UI
+
+3. **Lead with the problem, not the solution**
+ → "Tired of X?" performs better than "Introducing Y"
+
+4. **Keep copy under 100 characters**
+ → Their shortest ads seem most frequent
+
+5. **Test before/after visual formats**
+ → Proven pattern in their creative
+
+## Files Saved
+- All ads: ~/competitor-ads/notion/
+- Analysis: ~/competitor-ads/notion/analysis.md
+- Best performers: ~/competitor-ads/notion/top-10/
+```
+
+**Inspired by:** Sumant Subrahmanya's use case from Lenny's Newsletter
+
+## What You Can Learn
+
+### Messaging Analysis
+- What problems they emphasize
+- How they position against competition
+- Value propositions that resonate
+- Target audience segments
+
+### Creative Patterns
+- Visual styles that work
+- Video vs. static image performance
+- Color schemes and branding
+- Layout patterns
+
+### Copy Formulas
+- Headline structures
+- Call-to-action patterns
+- Length and tone
+- Emotional triggers
+
+### Campaign Strategy
+- Seasonal campaigns
+- Product launch approaches
+- Feature announcement tactics
+- Retargeting patterns
+
+## Best Practices
+
+### Legal & Ethical
+✓ Only use for research and inspiration
+✓ Don't copy ads directly
+✓ Respect intellectual property
+✓ Use insights to inform original creative
+✗ Don't plagiarize copy or steal designs
+
+### Analysis Tips
+1. **Look for patterns**: What themes repeat?
+2. **Track over time**: Save ads monthly to see evolution
+3. **Test hypotheses**: Adapt successful patterns for your brand
+4. **Segment by audience**: Different messages for different targets
+5. **Compare platforms**: LinkedIn vs Facebook messaging differs
+
+## Advanced Features
+
+### Trend Tracking
+```
+Compare [Competitor]'s ads from Q1 vs Q2.
+What messaging has changed?
+```
+
+### Multi-Competitor Analysis
+```
+Extract ads from [Company A], [Company B], [Company C].
+What are the common patterns? Where do they differ?
+```
+
+### Industry Benchmarks
+```
+Show me ad patterns across the top 10 project management
+tools. What problems do they all focus on?
+```
+
+### Format Analysis
+```
+Analyze video ads vs static image ads from [Competitor].
+Which gets more engagement? (if data available)
+```
+
+## Common Workflows
+
+### Ad Campaign Planning
+1. Extract competitor ads
+2. Identify successful patterns
+3. Note gaps in their messaging
+4. Brainstorm unique angles
+5. Draft test ad variations
+
+### Positioning Research
+1. Get ads from 5 competitors
+2. Map their positioning
+3. Find underserved angles
+4. Develop differentiated messaging
+5. Test against their approaches
+
+### Creative Inspiration
+1. Extract ads by theme
+2. Analyze visual patterns
+3. Note color and layout trends
+4. Adapt successful patterns
+5. Create original variations
+
+## Tips for Success
+
+1. **Regular Monitoring**: Check monthly for changes
+2. **Broad Research**: Look at adjacent competitors too
+3. **Save Everything**: Build a reference library
+4. **Test Insights**: Run your own experiments
+5. **Track Performance**: A/B test inspired concepts
+6. **Stay Original**: Use for inspiration, not copying
+7. **Multiple Platforms**: Compare Facebook, LinkedIn, TikTok, etc.
+
+## Output Formats
+
+- **Screenshots**: All ads saved as images
+- **Analysis Report**: Markdown summary of insights
+- **Spreadsheet**: CSV with ad copy, CTAs, themes
+- **Presentation**: Visual deck of top performers
+- **Pattern Library**: Categorized by approach
+
+## Related Use Cases
+
+- Writing better ad copy for your campaigns
+- Understanding market positioning
+- Finding content gaps in your messaging
+- Discovering new use cases for your product
+- Planning product marketing strategy
+- Inspiring social media content
+
diff --git a/.claude/skills/deep-research/SKILL.md b/.claude/skills/deep-research/SKILL.md
new file mode 100644
index 0000000..2e9f6f3
--- /dev/null
+++ b/.claude/skills/deep-research/SKILL.md
@@ -0,0 +1,296 @@
+---
+name: deep-research
+description: This skill should be used when users request comprehensive, in-depth research on a topic that requires detailed analysis similar to an academic journal or whitepaper. The skill conducts multi-phase research using web search and content analysis, employing high parallelism with multiple subagents, and produces a detailed markdown report with citations.
+license: MIT
+---
+
+# Deep Research
+
+This skill conducts comprehensive research on complex topics using a multi-agent architecture, producing detailed reports similar to academic journals or whitepapers.
+
+## Purpose
+
+The deep-research skill transforms broad research questions into thorough, well-cited reports using a three-agent system:
+
+1. **Lead Agent (You)**: Conducts interviews, plans research, orchestrates subagents
+2. **Researcher Agents**: Execute web searches and save findings to files
+3. **Report-Writer Agent**: Synthesizes research notes into final report
+
+## When to Use This Skill
+
+Use this skill when the user requests:
+- In-depth research on a complex topic
+- A comprehensive report or analysis
+- Research that requires multiple sources and synthesis
+- Deep investigation similar to academic or whitepaper standards
+- Detailed analysis with proper citations
+
+Do NOT use this skill for:
+- Simple fact-finding queries
+- Single-source information lookup
+- Code-only research within repositories
+- Quick exploratory searches
+
+## Agent Architecture
+
+### Lead Agent (You - the Orchestrator)
+
+**Role**: Interview user, plan research threads, spawn and coordinate subagents
+
+**Tools allowed**: Task (to spawn subagents), AskUserQuestion, Write (for research plan only)
+
+**Responsibilities**:
+- Conduct user interview to scope research
+- Perform initial reconnaissance
+- Decompose topic into 10+ research threads
+- Spawn researcher agents in parallel
+- Spawn report-writer agent after research completes
+
+### Researcher Agents
+
+**Role**: Execute focused research on assigned subtopic
+
+**Tools allowed**: WebSearch, WebFetch, Write
+
+**Responsibilities**:
+- Search the web for information on assigned topic
+- Fetch and analyze relevant pages
+- Save structured research notes to `research_notes/` directory
+
+**Output format**: Each researcher saves a markdown file to `research_notes/[subtopic-slug].md` with:
+- Summary of findings
+- Key facts and data points
+- Source URLs with brief descriptions
+- Notable quotes or excerpts
+- Conflicts or gaps identified
+
+### Report-Writer Agent
+
+**Role**: Synthesize all research notes into final report
+
+**Tools allowed**: Read, Glob, Write
+
+**Responsibilities**:
+- Read all files from `research_notes/` directory
+- Identify themes, patterns, and conflicts across sources
+- Structure and write the final report
+- Create the sources bibliography
+
+## Research Process
+
+### Phase 1: Interview and Scope Definition
+
+Start by interviewing the user to understand their research needs. Ask questions about:
+
+1. **Research objectives**: What are they trying to understand or decide?
+2. **Depth and breadth**: How comprehensive should the research be?
+3. **Target audience**: Who will read this report?
+4. **Key questions**: What specific questions need answering?
+5. **Time constraints**: Is this time-sensitive information?
+6. **Scope boundaries**: What should be explicitly included or excluded?
+
+The interview should be thorough but efficient. Use the AskUserQuestion tool to gather this information in 2-3 rounds of questions maximum.
+
+### Phase 2: Initial Reconnaissance
+
+After the interview, perform initial reconnaissance to identify the research landscape:
+
+1. Conduct 3-5 broad web searches to map the topic space
+2. Identify key subtopics, domains, and areas of focus
+3. Note promising sources, authoritative voices, and research gaps
+4. Create a research plan outlining 10+ specific research threads
+
+Save the research plan to `research_plan.md` documenting:
+- The research threads identified
+- Which researcher will handle each thread
+- Expected output from each researcher
+
+### Phase 3: Parallel Research (Researcher Agents)
+
+Launch 10+ researcher agents in parallel using the Task tool. Each agent receives a focused research assignment.
+
+**Spawning researcher agents:**
+
+```
+Task tool with:
+- subagent_type: "general-purpose"
+- prompt: Include these elements:
+ 1. Clear statement: "You are a RESEARCHER agent"
+ 2. Specific subtopic assignment
+ 3. Tool restrictions: "Only use WebSearch, WebFetch, and Write tools"
+ 4. Output instructions: "Save your findings to research_notes/[subtopic].md"
+ 5. Format requirements for the research notes file
+```
+
+**Example researcher prompt:**
+```
+You are a RESEARCHER agent investigating: "Technical implementation of quantum error correction"
+
+YOUR TOOLS: Only use WebSearch, WebFetch, and Write.
+
+TASK:
+1. Use WebSearch to find authoritative sources on quantum error correction implementation
+2. Use WebFetch to extract detailed information from promising sources
+3. Save your findings to research_notes/quantum-error-correction.md
+
+OUTPUT FORMAT (save to research_notes/quantum-error-correction.md):
+# Quantum Error Correction Implementation
+
+## Summary
+[2-3 paragraph summary of key findings]
+
+## Key Findings
+- [Bullet points of important facts, data, techniques]
+
+## Sources
+1. [URL] - [Brief description of what this source contributed]
+2. [URL] - [Brief description]
+...
+
+## Notable Quotes
+> "[Relevant quote]" - Source
+
+## Gaps and Conflicts
+- [Any conflicting information or areas needing more research]
+```
+
+**Launch all researcher agents in a single message** with multiple Task tool calls for true parallelism.
+
+### Phase 4: Report Generation (Report-Writer Agent)
+
+After all researcher agents complete, spawn a single report-writer agent:
+
+**Spawning the report-writer agent:**
+
+```
+Task tool with:
+- subagent_type: "general-purpose"
+- prompt: Include these elements:
+ 1. Clear statement: "You are a REPORT-WRITER agent"
+ 2. Tool restrictions: "Only use Read, Glob, and Write tools"
+ 3. Instructions to read all files from research_notes/
+ 4. Report structure requirements
+ 5. Output file paths for report and sources
+```
+
+**Example report-writer prompt:**
+```
+You are a REPORT-WRITER agent synthesizing research findings into a final report.
+
+YOUR TOOLS: Only use Read, Glob, and Write.
+
+TASK:
+1. Use Glob to list all files in research_notes/
+2. Use Read to load each research notes file
+3. Synthesize findings into a comprehensive report
+4. Write the final report to [topic]-report.md
+5. Write the sources bibliography to [topic]-sources.md
+
+REPORT STRUCTURE:
+- Executive Summary (2-3 paragraphs)
+- [Adaptive middle sections based on topic]
+- Critical Analysis
+- Conclusions
+- References (numbered citations)
+
+SOURCES FILE STRUCTURE:
+# Research Sources for [Topic]
+
+## [1] Source Title
+- **URL**: [url]
+- **Accessed**: [date]
+- **Type**: [Academic paper / Blog post / Documentation / News article]
+- **Key Points**: [bullet points]
+- **Relevance**: [why this source matters]
+
+WRITING GUIDELINES:
+- Use numbered citations [1], [2], etc.
+- Cross-reference findings across multiple researcher notes
+- Note any conflicts or gaps in the research
+- Use clear, precise academic language
+- Include tables for comparisons where appropriate
+```
+
+### Phase 5: Output and Summary
+
+After the report-writer completes:
+
+1. Inform the user of the generated files:
+ - `[topic]-report.md`: Main research report
+ - `[topic]-sources.md`: Complete bibliography
+ - `research_notes/`: Directory of raw research (can be deleted)
+
+2. Provide a brief verbal summary of key findings
+
+3. Offer to answer follow-up questions or expand on any section
+
+## File Structure
+
+```
+./
+├── research_plan.md # Your research plan (Phase 2)
+├── research_notes/ # Researcher agent outputs (Phase 3)
+│ ├── subtopic-1.md
+│ ├── subtopic-2.md
+│ └── ...
+├── [topic]-report.md # Final report (Phase 4)
+└── [topic]-sources.md # Bibliography (Phase 4)
+```
+
+## Logging and Observability
+
+Track research progress by documenting in `research_plan.md`:
+
+1. **Research threads assigned**: List each subtopic and its researcher
+2. **Status tracking**: Note when each researcher completes
+3. **Issues encountered**: Document any gaps or conflicts found
+
+This provides transparency into the research process and helps with debugging or expanding research later.
+
+## Best Practices
+
+### Agent Separation
+
+- **Lead agent**: ONLY spawns agents and coordinates - no direct research
+- **Researchers**: ONLY search, fetch, and write notes - no synthesis
+- **Report-writer**: ONLY reads notes and writes report - no new research
+
+This separation ensures clean handoffs and reproducible results.
+
+### Research Quality
+
+- Prioritize authoritative, recent sources (especially for time-sensitive topics)
+- Cross-reference claims across multiple researcher notes
+- Note conflicting information or perspectives
+- Distinguish between facts, expert opinions, and speculation
+- Be transparent about limitations in available information
+
+### Efficiency
+
+- Launch all researcher agents truly in parallel (single message, multiple Task tool calls)
+- Use model="haiku" for researcher agents to reduce costs
+- Use model="sonnet" for report-writer agent for better synthesis
+- Clear task delineation prevents redundant research
+
+## Common Patterns
+
+### Comparative Research
+When comparing technologies, approaches, or solutions:
+- Assign one researcher per option being compared
+- Assign one researcher for cross-cutting concerns (performance, cost, etc.)
+- Report-writer creates comparison tables
+
+### Technical Deep-Dives
+When researching technical topics:
+- Assign researchers to: fundamentals, implementation, case studies, limitations
+- Report-writer structures from basics to advanced
+
+### Market/Landscape Research
+When surveying a domain or market:
+- Assign researchers to: major players, emerging players, trends, analysis firms
+- Report-writer categorizes and evaluates the landscape
+
+### Historical/Evolution Research
+When investigating how something developed:
+- Assign researchers to different time periods or key events
+- Report-writer creates timeline and connects to present
diff --git a/.claude/skills/deep-research/references/research-frameworks.md b/.claude/skills/deep-research/references/research-frameworks.md
new file mode 100644
index 0000000..97ca64c
--- /dev/null
+++ b/.claude/skills/deep-research/references/research-frameworks.md
@@ -0,0 +1,133 @@
+# Research Frameworks and Methodologies
+
+This reference provides frameworks and methodologies that can guide the research process for different types of research questions.
+
+## Research Question Frameworks
+
+### The 5 W's + H Framework
+For exploratory research, ensure coverage of:
+- **Who**: Key players, stakeholders, researchers, organizations
+- **What**: Core concepts, technologies, approaches, solutions
+- **When**: Timeline, history, current state, future projections
+- **Where**: Geographic distribution, domains, contexts of application
+- **Why**: Motivations, drivers, problems being solved
+- **How**: Implementation, mechanisms, processes, methodologies
+
+### PESTLE Analysis Framework
+For market/domain research:
+- **Political**: Regulations, policies, government initiatives
+- **Economic**: Costs, market size, funding, economic impact
+- **Social**: User adoption, cultural factors, societal impact
+- **Technological**: Innovation, technical capabilities, limitations
+- **Legal**: Compliance, intellectual property, standards
+- **Environmental**: Sustainability, resource usage, ecological impact
+
+### SWOT Analysis Framework
+For comparative or evaluative research:
+- **Strengths**: Advantages, capabilities, unique features
+- **Weaknesses**: Limitations, gaps, disadvantages
+- **Opportunities**: Potential applications, growth areas, synergies
+- **Threats**: Risks, challenges, competing solutions
+
+## Information Quality Assessment
+
+### Source Credibility Criteria
+Evaluate sources based on:
+1. **Authority**: Author credentials, institutional affiliation
+2. **Accuracy**: Citations, peer review, verification
+3. **Objectivity**: Bias, conflicts of interest, perspective
+4. **Currency**: Publication date, relevance to current state
+5. **Coverage**: Depth, comprehensiveness, scope
+
+### Evidence Hierarchy
+Prioritize evidence types (strongest to weakest):
+1. Meta-analyses and systematic reviews
+2. Peer-reviewed research studies
+3. Technical documentation from primary sources
+4. Expert analysis and whitepapers
+5. Industry reports and surveys
+6. News articles and blog posts
+7. Anecdotal evidence and opinions
+
+## Research Depth Levels
+
+### Level 1: Overview (Quick Research)
+- Basic definitions and concepts
+- Key players and notable examples
+- High-level pros/cons or features
+- **Depth**: 3-5 sources, 1-2 pages
+
+### Level 2: Standard Analysis (Moderate Research)
+- Detailed explanations and mechanisms
+- Multiple examples and case studies
+- Comparative analysis of options
+- Identification of trends and patterns
+- **Depth**: 10-15 sources, 5-10 pages
+
+### Level 3: Deep Dive (Comprehensive Research)
+- Technical implementation details
+- Historical context and evolution
+- Extensive comparative analysis
+- Critical evaluation and synthesis
+- Multiple perspectives and viewpoints
+- Edge cases and limitations
+- Future directions and implications
+- **Depth**: 20+ sources, 15+ pages
+
+## Synthesis Strategies
+
+### Thematic Synthesis
+Group findings by themes/topics:
+1. Identify recurring themes across sources
+2. Organize information by theme
+3. Analyze relationships between themes
+4. Build cohesive narrative
+
+### Chronological Synthesis
+Organize by timeline:
+1. Establish historical context
+2. Trace evolution and development
+3. Identify key milestones and transitions
+4. Connect past to present state
+
+### Comparative Synthesis
+Structure around comparisons:
+1. Define comparison criteria
+2. Evaluate each option against criteria
+3. Identify patterns and trade-offs
+4. Provide framework for decision-making
+
+### Framework-Based Synthesis
+Use established frameworks:
+1. Select appropriate framework (PESTLE, SWOT, etc.)
+2. Map findings to framework categories
+3. Ensure comprehensive coverage
+4. Derive insights from framework application
+
+## Common Research Pitfalls to Avoid
+
+1. **Confirmation Bias**: Seeking only sources that support initial assumptions
+2. **Recency Bias**: Over-weighting recent sources for non-time-sensitive topics
+3. **Source Echo Chambers**: Citing multiple sources that reference the same original source
+4. **Shallow Coverage**: Broad but superficial research without depth in key areas
+5. **Over-Technical**: Excessive jargon without explanations for intended audience
+6. **Missing Context**: Presenting findings without necessary background or implications
+7. **Weak Citations**: Vague or missing source attribution
+8. **Synthesis Gaps**: Collecting information without meaningful analysis or connection
+
+## Report Quality Checklist
+
+Before finalizing a report, verify:
+
+- [ ] Clear executive summary captures key findings
+- [ ] All technical terms defined on first use
+- [ ] Multiple authoritative sources for key claims
+- [ ] Conflicting information acknowledged and addressed
+- [ ] Structured sections with logical flow
+- [ ] Tables/lists used for complex comparisons
+- [ ] Proper citations throughout [1], [2], etc.
+- [ ] Complete references section with all sources
+- [ ] Critical analysis beyond mere description
+- [ ] Implications and conclusions clearly stated
+- [ ] Limitations of research acknowledged
+- [ ] Separate sources bibliography file created
diff --git a/.claude/skills/dhh-rails-style/SKILL.md b/.claude/skills/dhh-rails-style/SKILL.md
new file mode 100644
index 0000000..56fbb1b
--- /dev/null
+++ b/.claude/skills/dhh-rails-style/SKILL.md
@@ -0,0 +1,276 @@
+---
+name: dhh-rails-style
+description: Write Ruby and Rails code in DHH's 37signals style. Use when writing Rails code, creating models, controllers, or any Ruby file. Embodies REST purity, fat models, thin controllers, Current attributes, Hotwire patterns, and "clarity over cleverness."
+trigger: ruby, rails, model, controller, concern, hotwire, turbo, stimulus
+---
+
+# DHH Rails Style Guide
+
+Apply 37signals/DHH conventions to Ruby and Rails code.
+
+## Core Philosophy
+
+> "The best code is the code you don't write. The second best is the code that's obviously correct."
+
+**Vanilla Rails is plenty:**
+- Rich domain models over service objects
+- CRUD controllers over custom actions
+- Concerns for horizontal code sharing
+- Records as state instead of boolean columns
+- Database-backed everything (no Redis)
+- Build solutions before reaching for gems
+
+## What We Deliberately Avoid
+
+| Avoid | Use Instead |
+|-------|-------------|
+| devise | Custom ~150-line auth |
+| pundit/cancancan | Simple role checks in models |
+| sidekiq | Solid Queue (database-backed) |
+| redis | Database for everything |
+| view_component | Partials |
+| GraphQL | REST with Turbo |
+| React/Vue | Hotwire + Stimulus |
+| RSpec | Minitest |
+| FactoryBot | Fixtures |
+
+## Naming Conventions
+
+### Methods
+
+```ruby
+# Verbs for actions
+card.close
+card.gild
+board.publish
+
+# Predicates return boolean
+card.closed?
+card.golden?
+user.admin?
+
+# Avoid set_ methods
+# ❌ card.set_status("closed")
+# ✅ card.close
+```
+
+### Concerns
+
+Name as adjectives describing capability:
+
+```ruby
+module Closeable
+ extend ActiveSupport::Concern
+ # ...
+end
+
+module Publishable; end
+module Watchable; end
+module Searchable; end
+```
+
+### Scopes
+
+```ruby
+# Ordering
+scope :chronologically, -> { order(created_at: :asc) }
+scope :reverse_chronologically, -> { order(created_at: :desc) }
+scope :alphabetically, -> { order(name: :asc) }
+scope :latest, -> { order(created_at: :desc).limit(1) }
+
+# Eager loading
+scope :preloaded, -> { includes(:author, :comments) }
+
+# Parameterized
+scope :sorted_by, ->(column) { order(column) }
+scope :created_after, ->(date) { where("created_at > ?", date) }
+```
+
+### Controllers
+
+Nouns matching resources:
+
+```ruby
+# ❌ Bad: Custom actions
+class CardsController
+ def close; end
+ def reopen; end
+end
+
+# ✅ Good: Nested resource
+class Cards::ClosuresController
+ def create; end # POST /cards/:id/closure
+ def destroy; end # DELETE /cards/:id/closure
+end
+```
+
+## REST Mapping
+
+Transform custom actions into resources:
+
+```
+POST /cards/:id/close → POST /cards/:id/closure
+DELETE /cards/:id/close → DELETE /cards/:id/closure
+POST /cards/:id/archive → POST /cards/:id/archival
+POST /cards/:id/publish → POST /cards/:id/publication
+```
+
+## Controller Patterns
+
+```ruby
+class Cards::ClosuresController < ApplicationController
+ before_action :set_card
+
+ def create
+ @card.close(by: Current.user)
+ redirect_to @card
+ end
+
+ def destroy
+ @card.reopen(by: Current.user)
+ redirect_to @card
+ end
+
+ private
+
+ def set_card
+ @card = Current.user.cards.find(params[:card_id])
+ end
+end
+```
+
+## Model Patterns
+
+### State as Records
+
+```ruby
+# ❌ Bad: Boolean column
+class Card < ApplicationRecord
+ # closed: boolean
+ def close
+ update!(closed: true)
+ end
+end
+
+# ✅ Good: State record
+class Card < ApplicationRecord
+ has_one :closure, dependent: :destroy
+
+ def close(by: Current.user)
+ create_closure!(closed_by: by)
+ end
+
+ def closed?
+ closure.present?
+ end
+end
+
+class Closure < ApplicationRecord
+ belongs_to :card
+ belongs_to :closed_by, class_name: "User"
+end
+```
+
+### Concerns
+
+```ruby
+# app/models/concerns/closeable.rb
+module Closeable
+ extend ActiveSupport::Concern
+
+ included do
+ has_one :closure, as: :closeable, dependent: :destroy
+ scope :closed, -> { joins(:closure) }
+ scope :open, -> { where.missing(:closure) }
+ end
+
+ def close(by: Current.user)
+ create_closure!(closed_by: by)
+ end
+
+ def reopen
+ closure&.destroy
+ end
+
+ def closed?
+ closure.present?
+ end
+end
+```
+
+## Current Attributes
+
+```ruby
+# app/models/current.rb
+class Current < ActiveSupport::CurrentAttributes
+ attribute :user, :session, :request_id
+
+ def user=(user)
+ super
+ Time.zone = user&.time_zone || "UTC"
+ end
+end
+
+# Usage anywhere
+Current.user
+Current.session
+```
+
+## Frontend Patterns
+
+### Turbo Frames
+
+```erb
+<%= turbo_frame_tag dom_id(@card) do %>
+ <%= render @card %>
+<% end %>
+```
+
+### Turbo Streams
+
+```erb
+<%# app/views/cards/create.turbo_stream.erb %>
+<%= turbo_stream.prepend "cards", @card %>
+<%= turbo_stream.update "flash", partial: "shared/flash" %>
+```
+
+### Stimulus
+
+```javascript
+// Small, focused controllers
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ static targets = ["menu"]
+
+ toggle() {
+ this.menuTarget.classList.toggle("hidden")
+ }
+}
+```
+
+## Testing
+
+```ruby
+# Minitest + fixtures
+class CardTest < ActiveSupport::TestCase
+ test "can be closed" do
+ card = cards(:open)
+ card.close(by: users(:admin))
+ assert card.closed?
+ end
+end
+```
+
+## Success Criteria
+
+Code follows DHH style when:
+
+- [ ] Controllers map to CRUD verbs on resources
+- [ ] Models use concerns for horizontal behavior
+- [ ] State tracked via records, not booleans
+- [ ] No service objects or unnecessary abstractions
+- [ ] Database-backed solutions (no Redis)
+- [ ] Tests use Minitest with fixtures
+- [ ] Turbo/Stimulus for interactivity
+- [ ] No npm/yarn dependencies
diff --git a/.claude/skills/domain-name-brainstormer/SKILL.md b/.claude/skills/domain-name-brainstormer/SKILL.md
new file mode 100644
index 0000000..b763c44
--- /dev/null
+++ b/.claude/skills/domain-name-brainstormer/SKILL.md
@@ -0,0 +1,212 @@
+---
+name: domain-name-brainstormer
+description: Generates creative domain name ideas for your project and checks availability across multiple TLDs (.com, .io, .dev, .ai, etc.). Saves hours of brainstorming and manual checking.
+---
+
+# Domain Name Brainstormer
+
+This skill helps you find the perfect domain name for your project by generating creative options and checking what's actually available to register.
+
+## When to Use This Skill
+
+- Starting a new project or company
+- Launching a product or service
+- Creating a personal brand or portfolio site
+- Rebranding an existing project
+- Registering a domain for a side project
+- Finding available alternatives when your first choice is taken
+
+## What This Skill Does
+
+1. **Understands Your Project**: Analyzes what you're building and who it's for
+2. **Generates Creative Names**: Creates relevant, memorable domain options
+3. **Checks Availability**: Verifies which domains are actually available across multiple TLDs
+4. **Multiple Extensions**: Suggests .com, .io, .dev, .ai, .app, and more
+5. **Provides Alternatives**: Offers variations if top choices are taken
+6. **Branding Insights**: Explains why certain names work well
+
+## How to Use
+
+### Basic Brainstorming
+
+```
+I'm building a project management tool for remote teams.
+Suggest domain names.
+```
+
+```
+Help me brainstorm domain names for a personal finance app
+```
+
+### Specific Preferences
+
+```
+I need a domain name for my AI writing assistant.
+Prefer short names with .ai or .io extension.
+```
+
+### With Keywords
+
+```
+Suggest domain names using the words "pixel" or "studio"
+for my design agency
+```
+
+## Example
+
+**User**: "I'm building a tool for developers to share code snippets. Suggest creative domain names."
+
+**Output**:
+```
+Analyzing your project...
+Target audience: Developers
+Key features: Code sharing, snippets, collaboration
+
+🎯 Domain Name Suggestions
+
+## Available (.com)
+1. ✓ snippetbox.com - Clear, memorable, available!
+ Why: Directly describes the product, easy to remember
+
+2. ✓ codeclip.com - Short and snappy
+ Why: Implies quick code sharing, only 8 characters
+
+3. ✓ devpaste.com - Developer-focused
+ Why: Familiar to devs (like pastebin), clear purpose
+
+## Available (Alternative TLDs)
+4. ✓ snippet.dev - Perfect extension for developers
+ Why: .dev extension signals developer tool
+
+5. ✓ codebox.io - Tech-forward
+ Why: .io popular with tech startups, clean name
+
+6. ✓ sharecode.app - Descriptive
+ Why: .app extension, clearly states the action
+
+## Premium/Taken (.com)
+- codeshare.com (Taken, est. $2,500)
+- snippets.com (Taken, premium domain)
+
+## Recommendations
+
+🏆 Top Pick: snippet.dev
+- Perfect for developer audience
+- Short and memorable
+- .dev extension adds credibility
+- Available now!
+
+🥈 Runner-up: snippetbox.com
+- .com is universally recognized
+- Slightly longer but descriptive
+- Great brandability
+
+Next steps:
+1. Register your favorite before someone else does!
+2. Want me to check more variations?
+3. Need help with logo ideas for these names?
+```
+
+**Inspired by:** Ben Aiad's use case from Lenny's Newsletter
+
+## Domain Naming Tips
+
+### What Makes a Good Domain
+
+✓ **Short**: Under 15 characters ideal
+✓ **Memorable**: Easy to recall and spell
+✓ **Pronounceable**: Can be said in conversation
+✓ **Descriptive**: Hints at what you do
+✓ **Brandable**: Unique enough to stand out
+✓ **No hyphens**: Easier to share verbally
+
+### TLD Guide
+
+- **.com**: Universal, trusted, great for businesses
+- **.io**: Tech startups, developer tools
+- **.dev**: Developer-focused products
+- **.ai**: AI/ML products
+- **.app**: Mobile or web applications
+- **.co**: Alternative to .com
+- **.xyz**: Modern, creative projects
+- **.design**: Creative/design agencies
+- **.tech**: Technology companies
+
+## Advanced Features
+
+### Check Similar Variations
+
+```
+Check availability for "codebase" and similar variations
+across .com, .io, .dev
+```
+
+### Industry-Specific
+
+```
+Suggest domain names for a sustainable fashion brand,
+checking .eco and .fashion TLDs
+```
+
+### Multilingual Options
+
+```
+Brainstorm domain names in English and Spanish for
+a language learning app
+```
+
+### Competitor Analysis
+
+```
+Show me domain patterns used by successful project
+management tools, then suggest similar available ones
+```
+
+## Example Workflows
+
+### Startup Launch
+1. Describe your startup idea
+2. Get 10-15 domain suggestions across TLDs
+3. Review availability and pricing
+4. Pick top 3 favorites
+5. Register immediately
+
+### Personal Brand
+1. Share your name and profession
+2. Get variations (firstname.com, firstnamelastname.dev, etc.)
+3. Check social media handle availability too
+4. Register consistent brand across platforms
+
+### Product Naming
+1. Describe product and target market
+2. Get creative, brandable names
+3. Check trademark conflicts
+4. Verify domain and social availability
+5. Test names with target audience
+
+## Tips for Success
+
+1. **Act Fast**: Good domains get taken quickly
+2. **Register Variations**: Get .com and .io to protect brand
+3. **Avoid Numbers**: Hard to communicate verbally
+4. **Check Social Media**: Make sure @username is available too
+5. **Say It Out Loud**: Test if it's easy to pronounce
+6. **Check Trademarks**: Ensure no legal conflicts
+7. **Think Long-term**: Will it still make sense in 5 years?
+
+## Pricing Context
+
+When suggesting domains, I'll note:
+- Standard domains: ~$10-15/year
+- Premium TLDs (.io, .ai): ~$30-50/year
+- Taken domains: Market price if listed
+- Premium domains: $hundreds to $thousands
+
+## Related Tools
+
+After picking a domain:
+- Check logo design options
+- Verify social media handles
+- Research trademark availability
+- Plan brand identity colors/fonts
+
diff --git a/.claude/skills/hotwire-patterns/SKILL.md b/.claude/skills/hotwire-patterns/SKILL.md
new file mode 100644
index 0000000..0da0680
--- /dev/null
+++ b/.claude/skills/hotwire-patterns/SKILL.md
@@ -0,0 +1,281 @@
+---
+name: hotwire-patterns
+description: Turbo and Stimulus patterns for Rails applications. Use when implementing interactivity, real-time updates, or frontend behavior without JavaScript frameworks.
+trigger: turbo, stimulus, hotwire, frame, stream, javascript, frontend, spa
+---
+
+# Hotwire Patterns
+
+## Philosophy
+
+> "The HTML-over-the-wire approach. Turbo lets you get the speed of a single-page app without writing JavaScript."
+
+**Core Principles:**
+- Server renders HTML, not JSON
+- Turbo handles navigation and updates
+- Stimulus adds JS behavior when needed
+- No build step, no npm
+
+## Turbo Drive
+
+Intercepts links and forms, fetches via AJAX, replaces ``:
+
+```erb
+<%# Automatic - no code needed %>
+<%= link_to "Dashboard", dashboard_path %>
+
+<%# Disable for specific links %>
+<%= link_to "External", "https://example.com", data: { turbo: false } %>
+
+<%# Disable for a section %>
+
+ <%= link_to "Legacy", legacy_path %>
+
+```
+
+## Turbo Frames
+
+Independent sections that update without full page reload:
+
+```erb
+<%# Define a frame %>
+<%= turbo_frame_tag "card_#{@card.id}" do %>
+ <%= render @card %>
+<% end %>
+
+<%# Navigation within frame stays in frame %>
+<%= turbo_frame_tag "card_#{@card.id}" do %>
+ <%= link_to "Edit", edit_card_path(@card) %>
+<% end %>
+
+<%# Break out of frame %>
+<%= link_to "View Full", card_path(@card), data: { turbo_frame: "_top" } %>
+```
+
+### Lazy Loading
+
+```erb
+<%= turbo_frame_tag "comments",
+ src: card_comments_path(@card),
+ loading: :lazy do %>
+
+ <% end %>
+
+ <% if testimonial.body_text.present? %>
+
+ <%= testimonial.body_text %>
+
+ <% end %>
+
+ <%# Quote + User layout - stacks on mobile/tablet (below lg), side-by-side on desktop %>
+
+ <%# Quote block %>
+
+ “
+
+
+ <%= testimonial.quote %>
+
+ <%# Speech bubble tail - pointing down on mobile/tablet, pointing right on desktop %>
+ <%# Mobile/tablet: pointing down from bottom-left (more to right on tablet to align with avatar) %>
+
+
+ <%# Desktop: pointing right toward user %>
+
+
+
+
+
+ <%# User tile - extra top margin on mobile/tablet to account for speech bubble tail %>
+
+
+ <%# Mobile navigation dots - only shown on mobile, hidden on tablet+ where arrows are shown %>
+ <% if testimonials.size > 1 %>
+
+ <% testimonials.each_with_index do |_, dot_index| %>
+
+ <% end %>
+
+ <% end %>
+
+
+ <%# Right arrow - hidden on mobile, shown on tablet+ %>
+ <% if testimonials.size > 1 %>
+
+ <% else %>
+
+ <% end %>
+
+
+
+<% end %>
diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb
index 904d5ab..17d158c 100644
--- a/app/views/home/index.html.erb
+++ b/app/views/home/index.html.erb
@@ -1,54 +1,69 @@
<%# Set page title for home page %>
<% content_for(:title) { "Discover why Ruby continues to be a beloved language for developers worldwide" } %>
-
- <% # Split pinned posts into 3 columns for desktop, maintaining left-to-right order %>
- <% pinned_cols = [[], [], []] %>
- <% @pinned_posts.each_with_index do |post, index| %>
- <% pinned_cols[index % 3] << post %>
+ <%# Navigation buttons + Sign in - same style as main nav %>
+ <%# Sticky on tablet+ (min-width: 640px AND min-height: 500px) but not horizontal phones %>
+
+
+ <%# Desktop/Tablet: show all buttons %>
+
+ <% Category.with_posts.ordered.each do |category| %>
+ <% next if category.is_success_story? && !has_success_stories? %>
+ <%= link_to category.name, category_path(category),
+ class: "text-gray-600 bg-gray-100 hover:bg-gray-200 px-3 py-2 rounded-md text-sm font-medium whitespace-nowrap" %>
<% end %>
-
- <% pinned_cols.each do |column_posts| %>
-
- <% column_posts.each do |post| %>
- <%= render 'posts/post_tile', post: post %>
- <% end %>
-