All hero, CTA, and footer login/register buttons now point to https://app.armarium.ch/login and https://app.armarium.ch/register. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Astro Rocket — A production-ready Astro 6 starter theme. Change the text, launch your site.
Overview
Astro Rocket is a launch-ready starter theme for web designers, developers, bloggers, and anyone who needs a portfolio website. Every page is already built and styled — you change the text and content, and your site is ready to go live.
It ships with a full blog, a complete component library, a built-in SEO layer, dark mode, a contact form, and 12 colour themes you can switch with one click. It's built on Astro 6 and Tailwind CSS v4.
Live demo → astrorocket.dev · Built by Hans Martens → hansmartens.dev
Astro Rocket is a fork of Velocity by Southwell Media. Velocity is the foundation — a powerful Astro boilerplate with a comprehensive design system and component library. Full credit to the Southwell Media team for that work. Astro Rocket builds on it with a different goal: a complete, ready-to-launch website where you only change the text to make it your own.
What changed from Velocity
The following changes were made to the free Velocity theme to create Astro Rocket:
| Change | Velocity | Astro Rocket |
|---|---|---|
| Theme switching | Edit a CSS import file and rebuild | 12 colour swatches in the header — click one and the logo badge, blog images, and every brand color update live on screen. No file edits, no rebuilds. Selector can be removed from the header once you've chosen a color. |
| Colour themes | 1 default theme | 12 Tailwind-based themes — all 12 shown as swatches in the header selector (Orange, Amber, Lime, Emerald, Teal, Cyan, Sky, Blue, Indigo, Violet, Purple, Magenta) |
| Logo badge | Requires a custom logo file | Auto-generated monogram badge — first letter of your site name on brand color, live-updates with active theme |
| Favicon | Static file to replace manually | Auto-generated SVG favicon — first letter + brand color, pre-rendered at build time from site.config.ts, no design tools needed |
| Blog image gradients | Plain image containers | Every blog cover and card uses a brand-color gradient background that updates live when the active theme changes |
| Icon system | Basic SVG Icon component |
Unified Icon component powered by Iconify — 350+ Lucide UI icons + 3000+ Simple Icons brand icons |
| Typing effect | Not included | Hero section includes an animated typing effect |
| Dark mode storage | localStorage |
sessionStorage — resets to dark on every new tab/session (see why) |
| Target audience | Developers & agencies | Web designers, developers, bloggers, and portfolio sites |
| Ready to launch | Boilerplate starting point | Fully styled pages — replace the text and your site is live |
| Maintained by | Southwell Media | Hans Martens |
Key Features
| Feature | Description |
|---|---|
| Astro 6 | Latest version with Content Layer API, security features, and performance optimizations |
| Tailwind CSS v4 | CSS-first configuration with OKLCH color system and fluid typography |
| 12 Colour Themes | All 12 colour swatches are shown in the header dropdown — click one and the logo badge, blog image gradients, and every brand color update live instantly. No file edits, no rebuilds. The selector can be removed from the header once you've settled on a color. |
| Scroll Progress Bar | A thin 2px brand-coloured bar on the header edge that fills as you scroll. Enabled on the homepage (above the floating header), blog index, and post pages (below the solid header). Controlled via showScrollProgress and scrollProgressPosition props on the Header component. |
| Design Tokens | Three-tier token architecture (reference → semantic → component) |
| 57 Components | 31 UI, 7 patterns, 1 hero, 4 layout, 4 blog, 7 landing, 3 SEO — all accessible with TypeScript |
| Auto Logo & Favicon | First letter of your site name on brand color — generated automatically from site.config.ts, no design tools needed |
| Icon System | Unified Icon component (Astro + React) — 350+ Lucide UI icons and 3000+ Simple Icons brand icons via Iconify |
| Typing Effect | Animated typing effect in the hero section |
| Page Animations | Smooth page transitions via Astro View Transitions, scroll-triggered counter and score animations, scroll-reactive header, card hover effects, and a full suite of UI micro-animations — all with reduced-motion support |
| SEO Toolkit | Meta tags, JSON-LD structured data, sitemap, and robots.txt |
| Static OG Image | A polished default Open Graph image serves as social preview for all pages — no build-time generation required |
| Dark Mode | Dark-first design with sessionStorage persistence |
| Content Collections | Type-safe blog, pages, authors, and FAQs with Zod validation |
| API Routes | Contact form and newsletter endpoints with validation |
| React Islands | Optional client-side interactivity where needed |
Internationalization (i18n)
The base theme is i18n-ready with locale-aware content collection schemas. Full i18n support with language routing and a LanguageSwitcher component can be added via the create-velocity-astro CLI from Southwell Media.
Quick Start
Prerequisites
- Node.js 22.12.0+ (required for Astro 6)
- pnpm 9.x (recommended) or npm/yarn
Installation
# Clone the repository
git clone https://github.com/hansmartens68/astro-rocket.git my-project
cd my-project
# Install dependencies
pnpm install
# Copy environment variables
cp .env.example .env
# Start development server
pnpm dev
Visit http://localhost:4321 to see your site.
Project Structure
astro-rocket/
├── public/ # Static assets (fonts, favicon)
├── src/
│ ├── assets/ # Images and icons (processed by Astro)
│ ├── components/
│ │ ├── ui/ # UI component library (31 components)
│ │ │ ├── form/ # Button, Input, Textarea, Select, Checkbox, Radio, Switch
│ │ │ ├── data-display/ # Card, Badge, Avatar, Table, Pagination, Progress, Skeleton
│ │ │ ├── feedback/ # Alert, Toast, Tooltip
│ │ │ ├── overlay/ # Dialog, Dropdown, Tabs, VerticalTabs, Accordion
│ │ │ ├── layout/ # Separator
│ │ │ ├── primitives/ # Icon
│ │ │ ├── content/ # CodeBlock
│ │ │ └── marketing/ # Logo, CTA, NpmCopyButton, SocialProof, TerminalDemo
│ │ ├── patterns/ # Composed patterns (ContactForm, SearchInput, StatCard, etc.)
│ │ ├── layout/ # Header, Footer, Navigation, ThemeToggle, ThemeSelector
│ │ ├── seo/ # SEO, JsonLd, Breadcrumbs
│ │ ├── blog/ # Blog-specific components
│ │ └── landing/ # Landing page components
│ ├── content/ # Content collections
│ │ ├── blog/ # Blog posts (en/, es/, fr/)
│ │ ├── projects/ # Portfolio project pages
│ │ ├── authors/ # Author profiles
│ │ └── faqs/ # FAQ entries
│ ├── layouts/ # Page layouts
│ ├── lib/ # Utilities (schema, cn)
│ ├── pages/ # Routes and API endpoints
│ │ ├── api/ # Contact, newsletter endpoints
│ │ └── blog/ # Blog routes
│ ├── styles/ # Global CSS and design tokens
│ │ ├── tokens/ # colors.css, typography.css, spacing.css
│ │ └── themes/ # 12 colour theme files
│ └── config/ # Site and navigation configuration
├── astro.config.mjs # Astro configuration
├── package.json
└── tsconfig.json
Commands
| Command | Description |
|---|---|
pnpm dev |
Start development server with hot reload |
pnpm build |
Build for production |
pnpm preview |
Preview production build locally |
pnpm check |
Run Astro type checker |
pnpm lint |
Run ESLint |
pnpm lint:fix |
Fix ESLint issues |
pnpm format |
Format code with Prettier |
pnpm format:check |
Check code formatting |
pnpm test |
Run Vitest tests |
pnpm test:e2e |
Run Playwright E2E tests |
Configuration
Site Configuration
Edit src/config/site.config.ts:
const siteConfig = {
name: 'Your Site Name',
description: 'Your site description for SEO',
url: 'https://yoursite.com',
ogImage: '/og-default.svg',
author: 'Your Name',
email: 'hello@yoursite.com',
twitter: {
site: '@yourhandle',
creator: '@yourhandle',
},
};
Environment Variables
Create a .env file from .env.example:
# Required
SITE_URL=https://yoursite.com
# Optional - Analytics
PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX
PUBLIC_GTM_ID=GTM-XXXXXXX
# Optional - Verification
GOOGLE_SITE_VERIFICATION=your-code
BING_SITE_VERIFICATION=your-code
Design System
Astro Rocket uses a three-tier design token system with OKLCH colors for perceptual uniformity:
- Primitives (
src/styles/tokens/primitives.css) — raw color scales (gray, brand, status) - Semantic tokens (
src/styles/themes/*.css) — purpose-based mappings (background, foreground, border, etc.) - Tailwind (
src/styles/global.css) —@themedirectives that expose tokens as utility classes
Switching Themes
Astro Rocket ships with 12 colour themes, all based on Tailwind's color palette. All 12 are shown as colour swatches in the header dropdown (ThemeSelectorDropdown) on desktop and in the mobile menu (ThemeSelector). Clicking a swatch applies the theme instantly — the logo badge, blog image gradients, and every brand color on the page update live. No file edits, no rebuilds. This is the key difference from Velocity, where switching theme requires editing a CSS import file and rebuilding.
The 12 themes in order: Orange, Amber, Lime, Emerald, Teal, Cyan, Sky, Blue (default), Indigo, Violet, Purple, and Magenta. The themes array in src/components/layout/ThemeSelector.astro controls which swatches are shown and in what order. You can also remove the selector from the header entirely once you've settled on a color — just remove showThemeSelector from the layout file.
The theme files live in src/styles/themes/:
amber.css blue.css cyan.css emerald.css
green.css indigo.css lime.css magenta.css
orange.css purple.css sky.css teal.css
violet.css
Customizing Brand Colors
Edit src/styles/tokens/primitives.css and update the --brand-* OKLCH values:
:root {
--brand-50: oklch(97.5% 0.02 45); /* lightest tint */
--brand-100: oklch(94.8% 0.04 45);
--brand-200: oklch(87.5% 0.08 45);
--brand-300: oklch(77.8% 0.14 45);
--brand-400: oklch(68.5% 0.19 40);
--brand-500: oklch(62.5% 0.22 38); /* primary brand color */
--brand-600: oklch(53.2% 0.19 38);
--brand-700: oklch(45.5% 0.16 38);
--brand-800: oklch(37.2% 0.13 38);
--brand-900: oklch(26.5% 0.09 38);
}
OKLCH values are oklch(lightness chroma hue). To shift your brand to blue, change the hue from 38-45 to ~260. Use oklch.com to pick colors visually.
Creating a New Theme
-
Duplicate
src/styles/themes/default.cssas your starting point -
Implement all ~35 semantic tokens for both
:root(light) and.dark(dark):Backgrounds:
--background,--background-secondary,--background-tertiary,--background-elevatedForegrounds:
--foreground,--foreground-secondary,--foreground-muted,--foreground-subtleBorders:
--border,--border-strong,--border-subtleInteractive:
--primary,--primary-hover,--primary-foreground,--secondary,--secondary-hover,--secondary-foreground,--accent,--accent-hover,--accent-lightSurfaces:
--muted,--muted-foreground,--card,--card-border,--input-bg,--input-border,--input-focus,--ringDestructive:
--destructive,--destructive-foregroundGradients:
--gradient-start,--gradient-endInvert sections:
--surface-invert,--surface-invert-secondary,--surface-invert-tertiary,--on-invert,--on-invert-secondary,--on-invert-muted,--border-invert,--border-invert-strong -
Update the import in
src/styles/tokens/colors.cssto point to your new theme file
Dark Mode
Dark mode toggles via the .dark class on <html>. The default is dark — the design was built dark-first and it looks great for portfolios and creative sites.
FOUC is prevented by an inline script that reads sessionStorage before first paint. Use the included ThemeToggle component:
---
import ThemeToggle from '@/components/layout/ThemeToggle.astro';
---
<ThemeToggle />
To opt out of dark mode, remove the .dark { ... } block from your theme file.
Why
sessionStorageinstead oflocalStorage? This is a deliberate choice.sessionStoragepersists the user's preference during their visit but resets when the tab is closed — so every new visit starts with the intended dark design. For a portfolio or marketing site this is the right call. For a product users return to daily (a SaaS dashboard, editor, etc.), switch tolocalStorageso the preference survives across sessions. Read the full reasoning in this blog post.
WCAG Contrast Requirements
Foreground tokens are documented with their contrast ratios inline. When customizing, maintain these minimums:
| Token | Minimum ratio | Standard |
|---|---|---|
--foreground |
7:1 | WCAG AAA |
--foreground-secondary |
7:1 | WCAG AAA |
--foreground-muted |
4.5:1 | WCAG AA |
--foreground-subtle |
4.5:1 | WCAG AA |
Status -foreground tokens |
4.5:1 | WCAG AA (on their -light bg) |
Using Design Tokens
<!-- Tailwind utilities (recommended) -->
<div class="bg-background text-foreground">
<h1 class="text-primary font-display">Hello</h1>
</div>
<!-- CSS custom properties -->
<style>
.custom {
background: var(--background-secondary);
color: var(--foreground);
}
</style>
Components
Astro Rocket includes 57 components across 7 categories. All UI components use class-variance-authority (CVA) for type-safe variant management.
UI Components (31)
Form (ui/form/)
| Component | Description |
|---|---|
| Button | Interactive button with primary, secondary, outline, ghost, destructive variants and loading state |
| Input | Text input with label, hint, and error states |
| Textarea | Multi-line text input |
| Select | Dropdown selection |
| Checkbox | Boolean toggle with indeterminate state |
| Radio | Single selection from group |
| Switch | Toggle switch input |
Data Display (ui/data-display/)
| Component | Description |
|---|---|
| Card | Content container with variant, padding, and hover options |
| Badge | Status labels and tags with contextual variants |
| Avatar | User images with fallback |
| AvatarGroup | Grouped avatar display with overlap |
| Table | Styled data table |
| Pagination | Page navigation controls |
| Progress | Progress bar indicator |
| Skeleton | Loading placeholders |
Feedback (ui/feedback/)
| Component | Description |
|---|---|
| Alert | Contextual feedback messages (info, success, warning, error) |
| Toast | Temporary notification messages |
| Tooltip | Hover tooltips with positioning |
Overlay (ui/overlay/)
| Component | Description |
|---|---|
| Dialog | Modal overlay |
| Dropdown | Menu with trigger |
| Tabs | Horizontal tabbed content panels |
| VerticalTabs | Vertical tab navigation |
| Accordion | Collapsible content sections |
Layout (ui/layout/)
| Component | Description |
|---|---|
| Separator | Visual divider between sections |
Primitives (ui/primitives/)
| Component | Description |
|---|---|
| Icon | Unified icon component (Astro + React) powered by Iconify. Supports all Lucide icons (lucide:*) and all Simple Icons brand icons (simple-icons:*). Includes shorthand names for common social and brand icons. Five size variants: xs, sm, md, lg, xl. |
Content (ui/content/)
| Component | Description |
|---|---|
| CodeBlock | Syntax-highlighted code display |
Marketing (ui/marketing/)
| Component | Description |
|---|---|
| Logo | Auto-generated monogram badge — renders the first letter of siteConfig.name on the active brand color. Five sizes: sm, md, lg, xl, 2xl. No logo file required. |
| CTA | Call-to-action sections with slot-based composition |
| NpmCopyButton | NPM install command with copy-to-clipboard |
| SocialProof | Testimonial and trust indicator cards |
| TerminalDemo | Animated terminal demonstration (React) |
Pattern Components (7)
| Component | Description |
|---|---|
| ContactForm | Complete contact form with validation |
| NewsletterForm | Email subscription form |
| FormField | Reusable form field wrapper |
| SearchInput | Search input with icon |
| PasswordInput | Password input with visibility toggle |
| StatCard | Statistics display card |
| EmptyState | Empty state placeholder with icon and action |
Other Categories
| Category | Count | Components |
|---|---|---|
| Hero | 1 | Hero section with centered/split layouts, grid pattern, and typing effect |
| Layout | 6 | Header (with scroll progress bar), Footer, ThemeToggle, ThemeSelector, ThemeSelectorDropdown, Analytics |
| Blog | 4 | ArticleHero, BlogCard, ShareButtons, RelatedPosts |
| Landing | 5 | Credibility, LighthouseScores, TechStack, FeatureTabs, and more |
| SEO | 3 | SEO, JsonLd, Breadcrumbs |
Usage Example
---
import { Button, Input, Card } from '@/components/ui';
---
<Card>
<Input label="Email" type="email" name="email" required />
<Button variant="primary">Submit</Button>
</Card>
Icon Usage
---
import Icon from '@/components/ui/primitives/Icon/Icon.astro';
---
<!-- Lucide UI icons — use any icon name from lucide.dev -->
<Icon name="arrow-right" size="md" />
<Icon name="mail" size="sm" />
<Icon name="layers" size="lg" />
<!-- Simple Icons brand icons — shorthand names available -->
<Icon name="github" size="md" />
<Icon name="x-twitter" size="md" />
<Icon name="brand-astro" size="md" />
<Icon name="brand-tailwind" size="md" />
<!-- Or use the full Iconify name directly -->
<Icon name="simple-icons:vercel" size="md" />
<Icon name="lucide:rocket" size="xl" />
All UI components are imported via barrel exports from @/components/ui. View all components at /components in development.
Content Management
Blog Posts
Create posts in src/content/blog/[locale]/:
---
title: "Your Post Title"
description: "Brief description for SEO"
publishedAt: 2026-01-30
author: "Author Name"
tags: ["astro", "tutorial"]
locale: en
---
Your content here...
Querying Content
---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog', ({ data }) => {
return import.meta.env.PROD ? !data.draft : true;
});
---
SEO
Automatic Features
- Meta tags: Title, description, canonical URL
- Open Graph: Complete OG tags for social sharing
- Twitter Cards: Large image cards
- JSON-LD: WebSite, Organization, BlogPosting, Breadcrumb, FAQ schemas
- Sitemap: Auto-generated at
/sitemap-index.xml - robots.txt: Dynamic generation with sitemap reference
- OG Images: A static default OG image serves all pages and blog posts
Using the SEO Component
---
import SEO from '@/components/seo/SEO.astro';
---
<head>
<SEO
title="Page Title"
description="Page description"
/>
</head>
OG Image
A static default OG image (public/og-default.svg) serves as the social preview for all pages. The path is set via ogImage in src/config/site.config.ts. To use a custom image for a specific page, pass it as the image prop to the layout component.
API Routes
Contact Form
POST /api/contact
// Request (FormData)
{
name: string, // 2-100 chars
email: string, // Valid email
subject: string, // Required
message: string, // 10-5000 chars
honeypot: string // Must be empty (spam check)
}
// Response
{ success: true }
// or
{ success: false, errors: { field: ["message"] } }
Newsletter
POST /api/newsletter
// Request (FormData)
{ email: string }
// Response
{ success: true }
// or
{ success: false, error: "message" }
Deployment
Configuration files included for major platforms.
Vercel (Recommended)
vercel
Netlify
netlify deploy --prod
Cloudflare Pages
wrangler pages deploy dist
Static Export
Build outputs to dist/ for any static host:
pnpm build
Browser Support
- Chrome (last 2 versions)
- Firefox (last 2 versions)
- Safari (last 2 versions)
- Edge (last 2 versions)
Performance
Astro Rocket is optimized for Core Web Vitals:
- Lighthouse Score: 95+ across all categories
- Zero JavaScript by default (islands architecture)
- Optimized fonts with
font-display: swap - Image optimization via Astro's built-in processing
- Prefetching for instant page transitions
Animations
Every page in Astro Rocket includes purposeful animations that make the site feel polished and alive. All animations respect the user's prefers-reduced-motion setting — they are disabled automatically for users who prefer less motion.
Page transitions
Astro Rocket uses Astro's built-in <ClientRouter /> (View Transitions API) to animate between pages. Instead of a full browser reload, content fades smoothly from one page to the next. This is enabled globally in BaseLayout.astro and requires no per-page configuration.
Scroll-triggered animations
Two components use an IntersectionObserver to trigger animations when elements enter the viewport:
- Counter animation — the stats block on the homepage (Years Experience, Projects Delivered, etc.) counts up from zero when it scrolls into view. Each number animates with a cubic ease-out over 1.2 seconds.
- Lighthouse score bars — the
LighthouseScoreslanding component animates its score bars into place as the section becomes visible.
Scroll-reactive header
The floating header changes its appearance as the user scrolls. When the page is at the top, the header is transparent with inverted text. Once the user scrolls past 60px, the header gains a solid background and the text flips to normal colors — all driven by CSS transitions via a data-scrolled attribute.
Scroll progress bar
A thin 2px brand-coloured bar on the header edge that grows from left to right as the user scrolls, showing reading progress at a glance. Enable it with two props on the <Header> component:
| Prop | Type | Default | What it does |
|---|---|---|---|
showScrollProgress |
boolean |
false |
Renders the progress bar |
scrollProgressPosition |
'top' | 'bottom' |
'bottom' |
Edge of the header where the bar sits |
The bar is enabled by default on three page types: the homepage (above the floating header), the blog index, and individual blog posts (both below the solid bar header). Use scrollProgressPosition="top" on a floating capsule header and 'bottom' on a solid bar header. The bar colour always matches --color-brand-500 and updates instantly when the visitor switches themes.
Card hover effects
Cards throughout the site lift slightly on hover (-translate-y-1) and gain a subtle shadow. This is a Tailwind utility applied consistently to all interactive cards.
UI micro-animations
The full animation library is defined in src/styles/global.css. These classes are used by components throughout the site:
| Class | What it does |
|---|---|
animate-fade-in |
Fades an element from transparent to visible (0.5s ease-out) |
animate-slide-up |
Slides an element up from 12px below while fading in (0.5s ease-out) |
animate-slide-down |
Slides an element down from 12px above while fading in (0.5s ease-out) |
animate-dropdown-in |
Slides and scales a dropdown menu into view (0.2s spring) |
animate-dropdown-out |
Collapses a dropdown menu out of view (0.15s) |
animate-sheet-up |
Slides a bottom sheet up from off-screen (0.25s spring) |
animate-menu-down |
Slides the mobile navigation drawer open (0.25s spring) |
animate-tab-enter |
Crossfades tab panel content when switching tabs |
animate-toast-in |
Slides a toast notification in from the right (350ms spring) |
animate-tooltip-in |
Fades and scales a tooltip into view |
animate-pulse |
Breathing pulse for skeleton loading states |
animate-spin |
Continuous rotation for loading spinners |
animate-shake |
Brief shake for error feedback (400ms) |
Animation delay utilities (.delay-0 through .delay-5, in 50ms steps) let you stagger multiple elements into view.
Contributing
Contributions are welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure your code passes linting (pnpm lint) and type checking (pnpm check) before submitting.
License
MIT License — see LICENSE for details.
Links
- Astro Rocket on GitHub
- Velocity — the original theme by Southwell Media
- Astro Documentation
- Tailwind CSS v4
Astro Rocket is designed and maintained by Hans Martens. Built on Velocity — the original theme by Southwell Media.