mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-04-20 16:40:29 +00:00
559 lines
25 KiB
Markdown
559 lines
25 KiB
Markdown
# 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
|
|
|
|
1. **Phase 1: Core Card Styling**
|
|
- Update `.featured-card` with modern shadows and transitions
|
|
- Enhance badge styling in `style.css`
|
|
- Add hover effects and transforms
|
|
|
|
2. **Phase 2: Hero & Featured Section**
|
|
- Improve hero section gradient/background
|
|
- Polish benefit cards
|
|
- Add section separators
|
|
|
|
3. **Phase 3: Typography & Spacing**
|
|
- Update font weights and sizes
|
|
- Improve padding throughout
|
|
- Better visual rhythm
|
|
|
|
4. **Phase 4: Navigation & Polish**
|
|
- Navbar improvements
|
|
- Loading states
|
|
- Final micro-interactions
|
|
|
|
## Key CSS Changes
|
|
|
|
### Tile Grid Layout
|
|
```css
|
|
.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)
|
|
```css
|
|
--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
|
|
```css
|
|
.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
|
|
```css
|
|
.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)
|
|
```css
|
|
.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
|
|
```css
|
|
.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)
|
|
```css
|
|
: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
|
|
```css
|
|
.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
|
|
```css
|
|
.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!
|
|
```sql
|
|
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 states
|
|
- `seahorse-confused.svg` - Lost/confused pose for 404 errors
|
|
- `seahorse-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)
|
|
1. Update border-radius variables (softer corners)
|
|
2. New shadow system
|
|
3. Card hover effects with teal accent
|
|
4. Tile grid layout (`minmax(280px, 1fr)`)
|
|
5. Wave pattern SVG for hero background
|
|
|
|
### Phase 2: Card Component & Data
|
|
1. Update `repo-card.html` with new structure
|
|
2. Add `Digest`, `Tag`, `CreatedAt` fields
|
|
3. Update queries for latest manifest info
|
|
4. Replace push list with card grid
|
|
|
|
### Phase 3: Hero & Section Polish
|
|
1. Hero gradient + wave pattern
|
|
2. Benefit card improvements
|
|
3. Section headers and spacing
|
|
4. Mobile responsive breakpoints
|
|
|
|
### Phase 4: Mascot Integration (BLOCKED - needs art)
|
|
1. Empty state component with mascot
|
|
2. 404 page with confused seahorse
|
|
3. Hero mascot (optional)
|
|
|
|
### Phase 5: Testing
|
|
1. Dark mode verification
|
|
2. Mobile responsive check
|
|
3. All functionality works (stars, links, copy)
|
|
|
|
## Verification
|
|
|
|
1. **Visual check on homepage** - cards have depth and polish
|
|
2. **Hover states** - smooth transitions on cards, buttons, badges
|
|
3. **Dark mode** - all changes work in both themes
|
|
4. **Mobile** - responsive at all breakpoints
|
|
5. **Functionality** - stars, search, navigation all work
|
|
6. **Performance** - no jank from CSS transitions
|
|
7. **Accessibility** - badge text readable (contrast check)
|