Showcase Track Guide
Showcase Track - Implementation Path
Section titled “Showcase Track - Implementation Path”Demonstrate technical excellence and best practices
Overview
Section titled “Overview”This track focuses on building a comprehensive showcase project with advanced patterns, comprehensive testing, and professional polish.
Track Philosophy
Section titled “Track Philosophy”- Technical Excellence: Demonstrate best practices and advanced patterns
- Production Ready: Build with enterprise-grade quality
- Comprehensive Testing: Automated quality assurance
- Performance Focused: 98+ Lighthouse scores across all categories
- Developer Experience: TypeScript-first with comprehensive tooling
Best For
Section titled “Best For”- Technical portfolios
- Developer showcases
- Team references
- Client presentations
- Skill demonstrations
- Best practices examples
Success Metrics
Section titled “Success Metrics”| Metric | Target | Why It Matters |
|---|---|---|
| Lighthouse Performance | 98+ | Perfect technical execution |
| Lighthouse Accessibility | 100 | WCAG AA compliance |
| Bundle Size | <160KB JS | Performance budget |
| Test Coverage | 80%+ | Quality assurance |
| TypeScript Coverage | 100% | Type safety |
| Build Time | <60s | Developer productivity |
Phase Implementation Guide
Section titled “Phase Implementation Guide”Phase 0: Foundation (1 day)
Section titled “Phase 0: Foundation (1 day)”💡 Starter Template: Advanced foundation is pre-configured with best practices
Showcase Decisions:
Framework: Astro + Islands ArchitectureStyling: Design Tokens + Tailwind CSSJavaScript: Selective (performance-budgeted)Testing: Playwright + Visual RegressionCI/CD: GitHub ActionsDeployment: Cloudflare Pages + AnalyticsMonitoring: Real User Monitoring (RUM)Content: Type-safe Collections + CMS📖 See Also: Islands Architecture Guide for implementation details
Phase 1: Content Architecture (2 days)
Section titled “Phase 1: Content Architecture (2 days)”Showcase Content Collections:
import { defineCollection, z } from 'astro:content';
const projectsCollection = defineCollection({ type: 'content', schema: ({ image }) => z.object({ title: z.string(), description: z.string(), technologies: z.array(z.string()), date: z.date(), featured: z.boolean().default(false), cover: image(), gallery: z.array(image()).optional(), demo: z.string().url().optional(), github: z.string().url().optional(), status: z.enum(['completed', 'in-progress', 'planned']).default('completed'), })});
const blogCollection = defineCollection({ type: 'content', schema: ({ image }) => z.object({ title: z.string(), description: z.string(), date: z.date(), updated: z.date().optional(), author: z.string().default('Your Name'), tags: z.array(z.string()), cover: image().optional(), draft: z.boolean().default(false), featured: z.boolean().default(false), })});
export const collections = { 'projects': projectsCollection, 'blog': blogCollection,};Phase 2: Design System (3 days)
Section titled “Phase 2: Design System (3 days)”💡 Starter Template: Design tokens system is pre-built in
/tokens/
Showcase Design Tokens:
{ "color": { "primary": { "50": { "value": "#eff6ff" }, "500": { "value": "#3b82f6" }, "900": { "value": "#1e3a8a" } }, "semantic": { "background": { "primary": { "value": "{color.neutral.50}" }, "secondary": { "value": "{color.neutral.100}" } }, "text": { "primary": { "value": "{color.neutral.900}" }, "secondary": { "value": "{color.neutral.600}" } } } }, "typography": { "scale": { "xs": { "value": "0.75rem" }, "sm": { "value": "0.875rem" }, "base": { "value": "1rem" }, "lg": { "value": "1.125rem" }, "xl": { "value": "1.25rem" } } }, "spacing": { "xs": { "value": "0.25rem" }, "sm": { "value": "0.5rem" }, "md": { "value": "1rem" }, "lg": { "value": "1.5rem" }, "xl": { "value": "2rem" } }}Phase 3: Tooling
Section titled “Phase 3: Tooling”Showcase CI/CD Pipeline:
name: Astro CI
on: push: branches: [ main ] pull_request: branches: [ main ]
jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm'
- name: Install dependencies run: pnpm install
- name: Build run: pnpm run build
- name: Run tests run: pnpm run test
- name: Visual Tests run: pnpm run test:visual env: PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
- name: Lighthouse CI uses: treosh/lighthouse-ci-action@v10 with: uploadArtifacts: true
- name: Bundle Analysis run: pnpm run analyzePhase 4: Skeleton
Section titled “Phase 4: Skeleton”Showcase Layout System:
***
import { ViewTransitions } from 'astro:transitions';import { SEO } from 'astro-seo';import Header from '@/components/layout/Header.astro';import Footer from '@/components/layout/Footer.astro';import SkipLinks from '@/components/a11y/SkipLinks.astro';import Analytics from '@/components/Analytics.astro';
export interface Props { title: string; description: string; image?: string; article?: boolean; publishedTime?: string; modifiedTime?: string; author?: string; noindex?: boolean;}
const { title, description, image = '/og-default.jpg', article = false, publishedTime, modifiedTime, author, noindex = false,} = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
***
<!DOCTYPE html><html lang="en" class="scroll-smooth"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content={Astro.generator}>
<SEO title={title} description={description} canonical={canonicalURL.toString()} openGraph={{ basic: { title, type: article ? 'article' : 'website', image, url: canonicalURL.toString(), }, optional: { description, siteName: 'Your Site Name', }, article: article ? { publishedTime, modifiedTime, author, } : undefined, }} twitter={{ card: 'summary_large_image', site: '@yourhandle', creator: '@yourhandle', }} extend={{ meta: [ { name: 'robots', content: noindex ? 'noindex, nofollow' : 'index, follow' }, { name: 'theme-color', content: '#0066cc' }, ], link: [ { rel: 'icon', href: '/favicon.ico', sizes: 'any' }, { rel: 'icon', href: '/icon.svg', type: 'image/svg+xml' }, { rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }, { rel: 'manifest', href: '/manifest.json' }, ], }} />
<ViewTransitions />
<!-- Preload critical fonts --> <link rel="preload" href="./fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
<!-- Critical CSS --> <style is:inline> /* Prevent FOUC */ .astro-route-announcer { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; } </style></head><body> <SkipLinks />
<Header />
<main id="main" tabindex="-1"> <slot /> </main>
<Footer />
<Analytics />
<!-- Development helpers --> {import.meta.env.DEV && ( <script> // Grid overlay with Shift+G document.addEventListener('keydown', (e) => { if (e.shiftKey && e.key === 'G') { document.body.classList.toggle('grid-overlay'); } }); </script> )}</body></html>Phase 5: Components (4 days)
Section titled “Phase 5: Components (4 days)”Showcase Component Library:
-
Interactive Button with Loading State
src/components/ui/Button.astro export interface Props {variant?: 'primary' | 'secondary' | 'ghost' | 'danger';size?: 'sm' | 'md' | 'lg';loading?: boolean;disabled?: boolean;href?: string;type?: 'button' | 'submit' | 'reset';id?: string;}const {variant = 'primary',size = 'md',loading = false,disabled = false,href,type = 'button',id,...attrs} = Astro.props;const Tag = href ? 'a' : 'button';<Tag{...attrs}href={href}type={!href ? type : undefined}disabled={disabled || loading}data-loading={loading}id={id}class:list={['btn',`btn-${variant}`,`btn-${size}`,{ 'btn-loading': loading }]}><span class="btn-content"><slot /></span>{loading && (<span class="btn-spinner"><svg class="animate-spin" width="16" height="16" viewBox="0 0 24 24">{/* spinner icon */}</svg></span>)}</Tag> -
Interactive Card Component
src/components/ui/Card.astro import { Image } from 'astro:assets';import type { ImageMetadata } from 'astro:assets';export interface Props {title: string;description: string;image?: ImageMetadata;href?: string;tags?: string[];date?: Date;interactive?: boolean;}const {title,description,image,href,tags = [],date,interactive = false,} = Astro.props;const CardContent = () => (<>{image && (<div class="card-image"><Imagesrc={image}alt=""widths={[400, 800]}sizes="(max-width: 768px) 100vw, 400px"loading="lazy"/></div>)}<div class="card-body"><h3 class="card-title">{title}</h3><p class="card-description">{description}</p>{date && <time class="card-date">{date.toLocaleDateString()}</time>}<div class="card-tags">{tags.map(tag => <span class="card-tag">{tag}</span>)}</div></div></>);{interactive ? (<articleclass="card interactive-card"data-href={href}client:visible><CardContent /></article>) : href ? (<a href={href} class="card card-link"><CardContent /></a>) : (<article class="card"><CardContent /></article>)}<script>// Progressive enhancement for interactive cardsdocument.querySelectorAll('.interactive-card').forEach(card => {card.addEventListener('click', (e) => {const href = card.dataset.href;if (href && !e.target.closest('a')) {window.location.href = href;}});});</script> -
Hero Section with Particle Animation
***
import Button from '@/components/ui/Button.astro';import ParticleField from '@/components/islands/ParticleField';
export interface Props { title: string; subtitle?: string; cta?: { text: string; href: string; }; pattern?: 'dots' | 'grid' | 'waves';}
const { title, subtitle, cta, pattern = 'dots' } = Astro.props;
***
<section class="hero"> <div class="hero-background"> <ParticleField pattern={pattern} client:idle /> </div>
<div class="hero-content"> <h1 class="hero-title"> {title.split(' ').map((word, i) => ( <span style={{ animationDelay: `${i * 100}ms` }} class="animate-fade-in-up" > {word} </span> ))} </h1>
{subtitle && ( <p class="hero-subtitle">{subtitle}</p> )}
{cta && ( <div class="hero-cta"> <Button href={cta.href} size="lg"> {cta.text} </Button> </div> )} </div></section>
<style> .hero { @apply relative min-h-screen flex items-center justify-center; @apply overflow-hidden; }
.hero-background { @apply absolute inset-0 -z-10; }
.hero-content { @apply relative z-10 text-center px-4; }
.hero-title { @apply text-5xl md:text-7xl font-bold mb-4; @apply bg-clip-text text-transparent bg-gradient-to-r from-primary-500 to-secondary-500; }
.hero-subtitle { @apply text-lg md:text-xl text-foreground-muted max-w-2xl mx-auto mb-8; }
.hero-cta { @apply mt-8; }</style>Phase 6: Sections (2 days)
Section titled “Phase 6: Sections (2 days)”Showcase Content Sections:
- Project Showcase with Filtering
***
import { getCollection } from 'astro:content';import ProjectCard from '@/components/ui/ProjectCard.astro';import FilterBar from '@/components/islands/FilterBar';
const projects = await getCollection('projects');const technologies = [...new Set(projects.flatMap(p => p.data.technologies))];
***
<section class="project-showcase"> <div class="container"> <h2 class="section-title">Featured Projects</h2>
<FilterBar filters={technologies} client:load />
<div class="projects-grid" data-projects> {projects.map(project => ( <div data-tags={project.data.technologies.join(',')}> <ProjectCard project={project} /> </div> ))} </div> </div></section>Phase 7: Content (5 days)
Section titled “Phase 7: Content (5 days)”Showcase Content Collections:
***
title: "Interactive Design System"technologies: ['Astro', 'Preact', 'Tailwind', 'Style-Dictionary']date: 2024-01-15cover: ./images/design-system-hero.jpggallery: - ./images/tokens-structure.png - ./images/component-library.png - ./images/documentation-site.png
***
import Figure from '@/components/mdx/Figure.astro';import Callout from '@/components/mdx/Callout.astro';import CodeDemo from '@/components/mdx/CodeDemo.astro';
# Building a Design System
<Callout type="info"> This project demonstrates a full-featured design system with token automation, component library, and documentation site.</Callout>
Our goal was to create a single source of truth for design that could be consumed by multiple web applications.
<Figure src="./images/tokens-structure.png" caption="Token structure using Style Dictionary"/>
## Key Features
- Automated token pipeline- WCAG AA compliant color palettes- Interactive component examples
<CodeDemo client:visible> <div slot="preview"> <Button>Click Me</Button> </div> <div slot="code"> ```html <button class="btn btn-primary">Click Me</button> ``` </div></CodeDemo>Phase 8: QA (3 days)
Section titled “Phase 8: QA (3 days)”Showcase Testing Implementation:
-
E2E Test Suite
tests/e2e/critical-paths.spec.ts import { test, expect } from '@playwright/test';test.describe('Critical Paths', () => {test('Homepage loads and has correct title', async ({ page }) => {await page.goto('/');await expect(page).toHaveTitle(/Your Site Name/);});test('Can navigate to projects and filter', async ({ page }) => {await page.goto('/projects');await page.click('button[data-filter="Astro"]');await expect(page.locator('[data-tags*="Astro"]')).toBeVisible();await expect(page.locator('[data-tags*="React"]')).not.toBeVisible();});}); -
Visual Regression Testing
tests/visual/components.spec.ts import { test, expect } from '@playwright/test';import percySnapshot from '@percy/playwright';test('Button component variants', async ({ page }) => {await page.goto('/components/button');await percySnapshot(page, 'Button Variants');}); -
Unit Tests for Utilities
src/utils/formatDate.test.ts import { expect, test } from 'vitest';import { formatDate } from './formatDate';test('formats date correctly', () => {const date = new Date('2024-01-15T00:00:00Z');expect(formatDate(date)).toBe('January 15, 2024');});
Phase 9: Performance (2 days)
Section titled “Phase 9: Performance (2 days)”Showcase Performance Optimization:
-
Image Optimization Strategy
src/components/ui/OptimizedImage.astro import { Image } from 'astro:assets';import type { ImageMetadata } from 'astro:assets';interface Props {src: ImageMetadata;alt: string;lazy?: boolean;widths?: number[];sizes?: string;}const {src,alt,lazy = true,widths = [400, 800, 1200],sizes = '(max-width: 800px) 100vw, 800px'} = Astro.props;<Imagesrc={src}alt={alt}widths={widths}sizes={sizes}loading={lazy ? 'lazy' : 'eager'}format="avif"fallbackFormat="webp"/> -
Font Loading Strategy
src/layouts/BaseLayout.astro <head><linkrel="preload"href="/fonts/inter-variable.woff2"as="font"type="font/woff2"crossorigin><style>@font-face {font-family: 'Inter';src: url('/fonts/inter-variable.woff2') format('woff2');font-weight: 100 900;font-display: swap;}</style></head>
Phase 10: Deployment (1 day)
Section titled “Phase 10: Deployment (1 day)”Showcase Deployment & Headers:
/* X-Frame-Options: DENY X-Content-Type-Options: nosniff Referrer-Policy: no-referrer Permissions-Policy: interest-cohort=() Content-Security-Policy: ...*/Phase 11: Documentation (2 days)
Section titled “Phase 11: Documentation (2 days)”Showcase Documentation Examples:
-
Interactive Code Demos
src/components/mdx/CodeDemo.astro // ... logic to handle slots<div class="code-demo"><div class="preview"><slot name="preview" /></div><div class="code"><slot name="code" /></div></div> -
Video Embed Component
src/components/mdx/Video.astro interface Props {src: string;title: string;width?: number;height?: number;}const { src, title, width = 16, height = 9 } = Astro.props;<div style={`aspect-ratio: ${width}/${height}`}><iframesrc={src}title={title}frameborder="0"allowfullscreenloading="lazy"client:visible/></div>
Phase 12: Post-Launch (1 day)
Section titled “Phase 12: Post-Launch (1 day)”Showcase Monitoring & Analytics:
import type { APIRoute } from 'astro';
export const POST: APIRoute = async ({ request }) => { const data = await request.json();
// Process analytics data const metrics = { ...data, timestamp: new Date().toISOString(), userAgent: request.headers.get('user-agent'), };
// Send to analytics service await sendToAnalytics(metrics);
// Store for internal dashboard await storeMetrics(metrics);
return new Response(JSON.stringify({ success: true }), { status: 200, headers: { 'Content-Type': 'application/json', }, });};Advanced Patterns
Section titled “Advanced Patterns”1. Progressive Enhancement
Section titled “1. Progressive Enhancement”***
// Enhance forms progressively
***
<form method="POST" action="/api/contact" data-enhance> <!-- Form works without JS --></form>
<script> // Enhance if JS available document.querySelectorAll('[data-enhance]').forEach(form => { form.addEventListener('submit', async (e) => { e.preventDefault();
const formData = new FormData(form); const response = await fetch(form.action, { method: form.method, body: formData, });
// Handle response with better UX }); });</script>2. Performance Budgets
Section titled “2. Performance Budgets”import { defineConfig } from 'astro/config';import bundleAnalyzer from '@bundle-analyzer/astro';
export default defineConfig({ integrations: [ bundleAnalyzer({ analyzeMode: 'static', openAnalyzer: false, generateStatsFile: true, statsFilename: 'bundle-stats.json', }), ], vite: { build: { rollupOptions: { output: { manualChunks: { 'preact': ['preact'], 'utils': ['./src/utils/index.ts'], }, }, }, }, },});Showcase vs MVP
Section titled “Showcase vs MVP”When to Choose Showcase
Section titled “When to Choose Showcase”✅ Choose Showcase when:
- Building a technical portfolio
- Demonstrating skills to employers
- Creating a team reference
- Have 4-6 weeks available
- Want comprehensive testing
- Need selective interactivity
❌ Avoid Showcase when:
- Timeline is critical
- Content is the only focus
- Working solo with limited time
- Building a simple site
- Learning Astro basics
Migration Path
Section titled “Migration Path”From MVP to Showcase:
- Add testing infrastructure
- Enhance components gradually
- Introduce islands selectively
- Improve documentation
- Add monitoring
Performance Metrics
Section titled “Performance Metrics”Technical Excellence
Section titled “Technical Excellence”- Lighthouse: 98+ all categories
- Bundle size: <160KB JS
- Test coverage: 80%+
- Zero accessibility violations
- Sub-second load times
Developer Experience
Section titled “Developer Experience”- Type safety throughout
- Comprehensive documentation
- Automated testing
- Visual regression prevention
- Easy onboarding
Business Impact
Section titled “Business Impact”- Improved conversions
- Better engagement metrics
- Lower bounce rates
- Higher satisfaction scores
- Reduced maintenance costs
Design Decisions
Section titled “Design Decisions”Islands Architecture
Section titled “Islands Architecture”We use interactive islands sparingly:
- Filter controls
- Search functionality
- Complex forms
- Data visualizations
Performance Strategy
Section titled “Performance Strategy”- AVIF/WebP images with fallbacks
- Critical CSS inlined
- Fonts preloaded
- JS lazy loaded
Deployment
Section titled “Deployment”- Cloudflare Pages for hosting
- GitHub Actions for CI/CD
- Automated rollbacks on regression
Conclusion
Section titled “Conclusion”The Showcase track demonstrates your ability to build production-grade applications with modern best practices. It’s an investment in quality that pays dividends through easier maintenance, better performance, and a portfolio piece that stands out.
Remember: The goal isn’t to use every feature, but to thoughtfully apply advanced patterns where they add value. Show restraint in your technical choices while demonstrating depth in your implementation.