25 KiB
Website Visual Improvement Plan
Goal
Create a fun, personality-driven container registry that embraces its nautical theme while being clearly functional. Think GitHub's Octocat or DigitalOcean's Sammy - playful but professional.
Brand Identity (from seahorse logo)
- Primary Teal: #4ECDC4 (body color) - the "ocean" feel
- Dark Teal: #2E8B8B (mane/fins) - depth and contrast
- Mint Background: #C8F0E7 - light, airy, underwater
- Coral Accent: #FF6B6B (eye) - warmth, CTAs, highlights
- Nautical theme to embrace:
- "Ship" containers (not just push)
- "Holds" for storage (like a ship's cargo hold)
- "Sailors" are users, "Captains" own holds
- Seahorse mascot as the friendly guide
Design Direction: Fun but Functional
- Softer, more rounded corners
- Playful color combinations (teal + coral)
- Mascot appearances in empty states, loading, errors
- Ocean-inspired subtle backgrounds (gradients, waves)
- Friendly copy and microcopy throughout
- Still clearly a container registry with all the technical info
Current State
- Pure CSS with custom properties for theming
- Basic card designs for repositories
- Simple hero section with terminal mockup
- Existing badges: Helm charts, multi-arch, attestations
- Existing stats: stars, pull counts
Layout Wireframes
Current Homepage Layout
┌─────────────────────────────────────────────────────────────────┐
│ [Logo] [Search] [Theme] [User] │ Navbar
├─────────────────────────────────────────────────────────────────┤
│ │
│ ship containers on the open web. │ Hero
│ ┌─────────────────────────┐ │
│ │ $ docker login atcr.io │ │
│ └─────────────────────────┘ │
│ [Get Started] [Learn More] │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Benefits
│ │ Docker │ │ Your Data │ │ Discover │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Featured │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ [icon] user/repo ★ 12 ↓ 340 ││ WIDE cards
│ │ Description text here... ││ (current)
│ └─────────────────────────────────────────────────────────────┘│
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ [icon] user/repo2 ★ 5 ↓ 120 ││
│ └─────────────────────────────────────────────────────────────┘│
│ │
│ What's New │
│ (similar wide cards) │
└─────────────────────────────────────────────────────────────────┘
Proposed Layout: Tile Grid
┌─────────────────────────────────────────────────────────────────┐
│ [Logo] [Search] [Theme] [User] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ship containers on the open web. │
│ ┌─────────────────────────┐ │
│ │ $ docker login atcr.io │ │
│ └─────────────────────────┘ │
│ [Get Started] [Learn More] │
│ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Docker │ │ Your Data │ │ Discover │ │
│ └────────────┘ └────────────┘ └────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Featured [View All] │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐│
│ │ [icon] │ │ [icon] │ │ [icon] ││ 3 columns
│ │ user/repo │ │ user/repo2 │ │ user/repo3 ││ ~300px each
│ │ Description... │ │ Description... │ │ Description... ││
│ │ ────────────────││ │ ────────────────││ │ ────────────────│││
│ │ ★ 12 ↓ 340 │ │ ★ 5 ↓ 120 │ │ ★ 8 ↓ 89 ││
│ └──────────────────┘ └──────────────────┘ └──────────────────┘│
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐│
│ │ ... │ │ ... │ │ ... ││
│ └──────────────────┘ └──────────────────┘ └──────────────────┘│
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ What's New │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐│
│ │ ... │ │ ... │ │ ... ││ Same tile
│ └──────────────────┘ └──────────────────┘ └──────────────────┘│ layout
└─────────────────────────────────────────────────────────────────┘
Unified Tile Card (Same for Featured & What's New)
┌─────────────────────────────┐
│ ┌────┐ user/repo [Helm] │ Icon + name + type badge
│ │icon│ :latest │ Tag (if applicable)
│ └────┘ │
│ │
│ Description text that │ Description (2-3 lines max)
│ wraps nicely here... │
│ │
│ sha256:abcdef12 │ Digest (truncated)
│ ───────────────────────────│ Divider
│ ★ 12 ↓ 340 1 day ago │ Stats + timestamp
└─────────────────────────────┘
Card anatomy:
┌─────────────────────────────┐
│ HEADER │ - Icon (48x48)
│ - icon + name + badge │ - user/repo
│ - tag (optional) │ - :tag or :latest
├─────────────────────────────┤
│ BODY │ - Description (clamp 2-3 lines)
│ - description │ - sha256:abc... (monospace)
│ - digest │
├─────────────────────────────┤
│ FOOTER │ - ★ star count
│ - stats + time │ - ↓ pull count
│ │ - "2 hours ago"
└─────────────────────────────┘
Both Sections Use Same Card (Different Sort)
Featured (by stars/curated): What's New (by last_push):
┌─────────────────────────┐ ┌─────────────────────────┐
│ user/repo │ │ user/repo │
│ :latest │ │ :v1.2.3 │ ← latest tag
│ Description... │ │ Description... │
│ │ │ │
│ sha256:abc123 │ │ sha256:def456 │ ← latest digest
│ ───────────────────────│ │ ───────────────────────│
│ ★ 12 ↓ 340 1 day ago │ │ ★ 5 ↓ 89 2 hrs ago │ ← last_push time
└─────────────────────────┘ └─────────────────────────┘
Same card component, different data source:
- Featured: GetFeaturedRepos() (curated or by stars)
- What's New: GetRecentlyUpdatedRepos() (ORDER BY last_push DESC)
Card Dimensions Comparison
Current: █████████████████████████████████████████ (~800px+ wide)
Proposed: ████████████ ████████████ ████████████ (~280-320px each)
Card 1 Card 2 Card 3
Mobile Responsive Behavior
Desktop (>1024px): [Card] [Card] [Card] 3 columns
Tablet (768-1024px): [Card] [Card] 2 columns
Mobile (<768px): [Card] 1 column (full width)
Playful Elements
Empty State (no repos):
┌─────────────────────────────────────────┐
│ │
│ 🐴 (seahorse) │
│ "Nothing here yet!" │
│ │
│ Ship your first container to get │
│ started on your voyage. │
│ │
│ [Start Shipping] │
└─────────────────────────────────────────┘
Error/404:
┌─────────────────────────────────────────┐
│ │
│ 🐴 (confused seahorse) │
│ "Lost at sea!" │
│ │
│ We couldn't find that container. │
│ Maybe it drifted away? │
│ │
│ [Back to Shore] │
└─────────────────────────────────────────┘
Hero with subtle ocean feel:
┌─────────────────────────────────────────┐
│ ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋ │ Subtle wave pattern bg
│ │
│ ship containers on the │
│ open web. 🐴 │ Mascot appears!
│ │
│ ┌─────────────────────┐ │
│ │ $ docker login ... │ │
│ └─────────────────────┘ │
│ │
│ ≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋≋ │
└─────────────────────────────────────────┘
Card with Personality
┌───────────────────────────────────┐
│ ┌──────┐ │
│ │ icon │ user/repo │
│ │ │ :latest [⚓ Helm] │ Anchor icon for Helm
│ └──────┘ │
│ │
│ A container that does amazing │
│ things for your app... │
│ │
│ sha256:abcdef12 │
│ ─────────────────────────────────│
│ ★ 12 ↓ 340 1 day ago │
│ │
│ 🐴 Shipped by alice.bsky.social │ Playful "shipped by" line
└───────────────────────────────────┘
(optional: "Shipped by" could be subtle or only on hover)
Design Improvements
1. Enhanced Card Design (Priority: High)
Files: pkg/appview/public/css/style.css, pkg/appview/templates/components/repo-card.html
- Add subtle gradient backgrounds on hover
- Improve shadow depth (layered shadows for modern look)
- Add smooth transitions (transform, box-shadow)
- Better icon styling with ring/border accent
- Enhanced badge visibility with better contrast
- Add "Updated X ago" timestamp to cards
- Improve stat icon/count alignment and spacing
2. Hero Section Polish (Priority: High)
Files: pkg/appview/public/css/style.css, pkg/appview/templates/pages/home.html
- Add subtle background pattern or gradient mesh
- Improve terminal mockup styling (better shadows, glow effect)
- Enhance benefit cards with icons and better spacing
- Add visual separation between hero and content
- Improve CTA button styling with better hover states
3. Typography & Spacing (Priority: High)
Files: pkg/appview/public/css/style.css
- Increase visual hierarchy with better font weights
- Add more breathing room (padding/margins)
- Improve heading styles with subtle underlines or accents
- Better link styling with hover states
- Add letter-spacing to badges for readability
4. Badge System Enhancement (Priority: Medium)
Files: pkg/appview/public/css/style.css, templates
- Create unified badge design language
- Add subtle icons inside badges (already using Lucide)
- Improve color coding: Helm (blue), Attestation (green), Multi-arch (purple)
- Add "Official" or "Verified" badge styling (for future use)
- Better hover states on interactive badges
5. Featured Section Improvements (Priority: Medium)
Files: pkg/appview/templates/pages/home.html, pkg/appview/public/css/style.css
- Add section header with subtle styling
- Improve grid responsiveness
- Add "View All" link styling
- Better visual distinction from "What's New" section
6. Navigation Polish (Priority: Medium)
Files: pkg/appview/public/css/style.css, nav templates
- Improve search bar visibility and styling
- Better user menu dropdown aesthetics
- Add subtle border or shadow to navbar
- Improve mobile responsiveness
7. Loading & Empty States (Priority: Low)
Files: pkg/appview/public/css/style.css
- Add skeleton loading animations
- Improve empty state illustrations/styling
- Better transition when content loads
8. Micro-interactions (Priority: Low)
Files: pkg/appview/public/css/style.css, pkg/appview/public/js/app.js
- Add subtle hover animations throughout
- Improve button press feedback
- Star button animation on click
- Copy button success animation
Implementation Order
-
Phase 1: Core Card Styling
- Update
.featured-cardwith modern shadows and transitions - Enhance badge styling in
style.css - Add hover effects and transforms
- Update
-
Phase 2: Hero & Featured Section
- Improve hero section gradient/background
- Polish benefit cards
- Add section separators
-
Phase 3: Typography & Spacing
- Update font weights and sizes
- Improve padding throughout
- Better visual rhythm
-
Phase 4: Navigation & Polish
- Navbar improvements
- Loading states
- Final micro-interactions
Key CSS Changes
Tile Grid Layout
.featured-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
/* Already exists but updating min-width */
.featured-card {
min-height: 200px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
Enhanced Shadow System (Multi-layer for depth)
--shadow-card: 0 1px 3px rgba(0,0,0,0.08), 0 4px 12px rgba(0,0,0,0.05);
--shadow-card-hover: 0 8px 25px rgba(78,205,196,0.15), 0 4px 12px rgba(0,0,0,0.1);
--shadow-nav: 0 2px 8px rgba(0,0,0,0.1);
Card Design Enhancement
.featured-card {
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
border: 1px solid var(--border);
}
.featured-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-card-hover);
border-color: var(--primary); /* teal accent on hover */
}
Icon Container Styling
.featured-icon-placeholder {
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
box-shadow: 0 2px 8px rgba(78,205,196,0.3);
}
Badge System (Consistent, Accessible)
.badge-helm {
background: #0d6cbf;
color: #fff;
}
.badge-multi {
background: #7c3aed;
color: #fff;
}
.badge-attestation {
background: #059669;
color: #fff;
}
/* All badges: */
font-weight: 600;
letter-spacing: 0.02em;
text-transform: uppercase;
font-size: 0.7rem;
padding: 0.25rem 0.5rem;
border-radius: 4px;
Hero Section Enhancement
.hero-section {
background:
linear-gradient(135deg, var(--hero-bg-start) 0%, var(--hero-bg-end) 50%, rgba(78,205,196,0.1) 100%),
url('/static/wave-pattern.svg'); /* subtle wave pattern */
background-size: cover, 100% 50px;
background-position: center, bottom;
background-repeat: no-repeat, repeat-x;
}
.benefit-card {
border: 1px solid transparent;
border-radius: 12px; /* softer corners */
transition: all 0.2s ease;
}
.benefit-card:hover {
border-color: var(--primary);
transform: translateY(-4px);
}
Playful Border Radius (Softer Feel)
:root {
--radius-sm: 6px; /* was 4px */
--radius-md: 12px; /* was 8px */
--radius-lg: 16px; /* new */
}
.featured-card { border-radius: var(--radius-md); }
.benefit-card { border-radius: var(--radius-md); }
.btn { border-radius: var(--radius-sm); }
.hero-terminal { border-radius: var(--radius-lg); }
Fun Empty States
.empty-state {
text-align: center;
padding: 3rem;
}
.empty-state-mascot {
width: 120px;
height: auto;
margin-bottom: 1.5rem;
animation: float 3s ease-in-out infinite;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.empty-state-title {
font-size: 1.5rem;
font-weight: 600;
color: var(--fg);
}
.empty-state-text {
color: var(--secondary);
margin-bottom: 1.5rem;
}
Typography Refinements
.featured-title {
font-weight: 600;
letter-spacing: -0.01em;
}
.featured-description {
line-height: 1.5;
opacity: 0.85;
}
Data Model Change
Current "What's New": Shows individual pushes (each tag push is a separate card)
Proposed "What's New": Shows repos ordered by last update time (same as Featured, different sort)
Tracking: repository_stats table already has last_push timestamp!
SELECT * FROM repository_stats ORDER BY last_push DESC LIMIT 9;
Unified Card Data:
| Field | Source |
|---|---|
| Handle, Repository | users + manifests |
| Tag | Latest tag from tags table |
| Digest | From latest tag or manifest |
| Description, IconURL | repo_pages or annotations |
| StarCount, PullCount | stars count + repository_stats |
| LastUpdated | repository_stats.last_push |
| ArtifactType | manifests.artifact_type |
Files to Modify
| File | Changes |
|---|---|
pkg/appview/public/css/style.css |
Rounded corners, shadows, hover, badges, ocean theme |
pkg/appview/public/wave-pattern.svg |
NEW: Subtle wave pattern for hero background |
pkg/appview/templates/components/repo-card.html |
Add Tag, Digest, LastUpdated fields |
pkg/appview/templates/components/empty-state.html |
NEW: Reusable fun empty state with mascot |
pkg/appview/templates/pages/home.html |
Both sections use repo-card grid |
pkg/appview/templates/pages/404.html |
Fun "Lost at sea" error page |
pkg/appview/db/queries.go |
New GetRecentlyUpdatedRepos() query; add fields to RepoCardData |
pkg/appview/handlers/home.go |
Replace GetRecentPushes with GetRecentlyUpdatedRepos |
pkg/appview/templates/partials/push-list.html |
Delete or repurpose (no longer needed) |
Dependencies
Mascot Art Needed:
seahorse-empty.svg- Friendly pose for "nothing here yet" empty statesseahorse-confused.svg- Lost/confused pose for 404 errorsseahorse-waving.svg(optional) - For hero section accent
Can proceed without art:
- CSS changes (colors, shadows, rounded corners, gradients)
- Card layout and grid changes
- Data layer changes (queries, handlers)
- Wave pattern background (simple SVG)
Blocked until art is ready:
- Empty state component with mascot
- 404 page redesign with mascot
- Hero mascot integration (optional)
Implementation Phases
Phase 1: CSS & Layout (No art needed)
- Update border-radius variables (softer corners)
- New shadow system
- Card hover effects with teal accent
- Tile grid layout (
minmax(280px, 1fr)) - Wave pattern SVG for hero background
Phase 2: Card Component & Data
- Update
repo-card.htmlwith new structure - Add
Digest,Tag,CreatedAtfields - Update queries for latest manifest info
- Replace push list with card grid
Phase 3: Hero & Section Polish
- Hero gradient + wave pattern
- Benefit card improvements
- Section headers and spacing
- Mobile responsive breakpoints
Phase 4: Mascot Integration (BLOCKED - needs art)
- Empty state component with mascot
- 404 page with confused seahorse
- Hero mascot (optional)
Phase 5: Testing
- Dark mode verification
- Mobile responsive check
- All functionality works (stars, links, copy)
Verification
- Visual check on homepage - cards have depth and polish
- Hover states - smooth transitions on cards, buttons, badges
- Dark mode - all changes work in both themes
- Mobile - responsive at all breakpoints
- Functionality - stars, search, navigation all work
- Performance - no jank from CSS transitions
- Accessibility - badge text readable (contrast check)