This document outlines the plan to migrate the current static Vite-based website to Astro, converting the existing index.html into a reusable splash layout that can be used for future landing pages.
- Build Tool: Vite 7.1.2
- CSS Framework: Tailwind CSS 4.1.12 with @tailwindcss/vite plugin
- JavaScript Libraries:
- Alpine.js 3.15.0 (for reactive components)
- GSAP 3.13.0 with ScrollTrigger (for animations)
- Lottie (loaded via CDN for animation playback)
- External Dependencies:
- Google Fonts (Inter, Manrope, Plus Jakarta Sans, Roboto Slab)
- Font Awesome 7.0.1
- Fathom Analytics
/
├── index.html (main landing page)
├── src/
│ ├── style.css (Tailwind configuration and custom styles)
│ └── main.js (GSAP animations and Alpine.js initialization)
├── public/
│ ├── CurlyBoi_Animated.json (Lottie animation)
│ ├── *.svg (various image assets)
│ └── files/ (PDF documents)
├── package.json
└── vite.config.js (assumed to exist)
- Hero Section with:
- Lottie animation (CurlyBoi) on first visit only (using sessionStorage)
- GSAP animations for logo and date reveal
- Smooth scroll functionality
- Content Sections:
- Conference information with fade-up animations
- Sponsorship call-to-action
- Social media links
- Footer
- Interactive Elements:
- Alpine.js for scroll functionality
- GSAP ScrollTrigger for scroll-based animations
- Session storage to skip animations on return visits
- SEO/Metadata:
- Schema.org structured data (Event markup)
- Open Graph tags (implied)
- Fathom Analytics
- Framework: Astro 5.14.4 (latest stable as of October 2025)
- Content Management: Astro Content Collections with MDX support (@astrojs/mdx 4.3.6)
- Styling: SCSS/Sass 1.93.2
- TypeScript: Yes (TypeScript 5.9.3)
- Additional Tools:
- Prettier 3.6.2 with Astro plugin (prettier-plugin-astro 0.14.1) for code formatting
- Custom utility libraries (execa, jsdom, luxon)
/
├── astro.config.mjs
├── tsconfig.json
├── package.json
├── src/
│ ├── env.d.ts
│ ├── layouts/
│ │ ├── Base.astro (base HTML layout)
│ │ ├── Splash.astro (new: converted from index.html)
│ │ └── Page.astro (standard page layout for future pages)
│ ├── pages/
│ │ └── index.astro (uses Splash layout)
│ ├── components/
│ │ ├── HeroSection.astro
│ │ ├── SponsorSection.astro
│ │ ├── SocialLinks.astro
│ │ └── Footer.astro
│ ├── styles/
│ │ ├── global.scss
│ │ └── splash.scss (splash-specific styles)
│ └── scripts/
│ ├── animations.js (GSAP setup)
│ └── alpine-setup.js (Alpine.js initialization)
├── public/ (unchanged)
└── _redirects (for Netlify/deployment)
# Remove Vite-specific dependencies
npm uninstall vite @tailwindcss/vite
# Install Astro core (latest stable)
npm install --save-dev astro@^5.14.4
# Install Astro integrations
npm install --save-dev @astrojs/mdx@^4.3.6
# Install styling dependencies
npm install --save-dev sass@^1.93.2 typescript@^5.9.3
# Install development tools
npm install --save-dev prettier@^3.6.2 prettier-plugin-astro@^0.14.1
# Keep existing runtime dependencies
# (alpinejs, gsap are already installed)Create astro.config.mjs:
// @ts-check
import { defineConfig } from "astro/config"
import mdx from "@astrojs/mdx"
export default defineConfig({
markdown: {
syntaxHighlight: "prism",
},
integrations: [mdx()],
legacy: {
collections: true, // For compatibility if using older content collections API
},
redirects: {
// Add any necessary redirects here
},
})Create tsconfig.json (reference 2025 website):
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"allowJs": true,
"jsx": "preserve"
}
}Create src/env.d.ts:
/// <reference types="astro/client" />{
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"start": "astro dev",
"astro": "astro"
}
}Create .prettierrc.toml:
plugins = ["prettier-plugin-astro"]Create .prettierignore:
dist/
node_modules/
Current implementation uses Tailwind v4 with the new @import "tailwindcss" syntax. Astro typically works better with traditional Tailwind v3 approach or pure SCSS.
Option A: Keep Tailwind (Recommended for Minimal Changes)
- Install Tailwind v3 with PostCSS integration
- Convert
src/style.cssto work with Astro's asset pipeline
Option B: Convert to Pure SCSS (More Aligned with 2025 Website)
- Extract Tailwind theme values into SCSS variables
- Convert utility classes to SCSS mixins/extends
- Create
src/styles/global.scsswith base styles - Create
src/styles/splash.scssfor splash-specific styles
src/
├── styles/
│ ├── _variables.scss (colors, fonts, sizes from Tailwind theme)
│ ├── _mixins.scss (button styles, utilities)
│ ├── global.scss (body, common styles)
│ └── splash.scss (splash layout specific)
Action Items:
- Extract CSS custom properties from
@themeblock into SCSS variables - Convert
.btn,.btn-primary, etc. into SCSS classes or mixins - Keep
.bg-separatorand.bg-patternas they are complex utilities
This layout should include:
- HTML document structure
<head>with meta tags- Font preloads and stylesheets
- Analytics scripts (Fathom)
- Common Schema.org data structure
- Slot for page content
---
export interface Props {
title: string;
description?: string;
ogImage?: string;
schemaData?: object;
}
const { title, description, ogImage, schemaData } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/favicon2.svg" />
<title>{title}</title>
{description && <meta name="description" content={description} />}
<!-- Font preconnects and stylesheets -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:...&display=swap" rel="stylesheet">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" />
<!-- Fathom Analytics -->
<script src="https://cdn.usefathom.com/script.js" data-site="BETINVUJ" defer></script>
<!-- Schema.org structured data -->
{schemaData && (
<script type="application/ld+json" set:html={JSON.stringify(schemaData)} />
)}
</head>
<body>
<slot />
</body>
</html>This layout extends Base.astro and implements the splash page structure:
- Uses Base layout with Schema.org event data
- Includes scripts for Lottie, GSAP, Alpine.js
- Provides named slots for hero, content, footer sections
---
import Base from './Base.astro';
const schemaData = {
"@context": "https://schema.org",
"@type": "Event",
// ... rest of Schema.org data
};
---
<Base title="PyCon AU 2026" schemaData={schemaData}>
<slot name="hero" />
<slot name="content" />
<slot name="footer" />
<!-- Lottie -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.11.0/lottie.min.js" crossorigin></script>
<!-- Main scripts -->
<script src="/src/scripts/animations.js"></script>
</Base>Standard layout for future content pages (not used initially):
---
import Base from './Base.astro';
export interface Props {
title: string;
description?: string;
}
const { title, description } = Astro.props;
---
<Base title={title} description={description}>
<main>
<slot />
</main>
</Base>- Extract hero section HTML from index.html (lines 85-119)
- Keep Alpine.js directives
- Keep GSAP target IDs and classes
- Extract main content section (lines 121-151)
- Break into sub-components if needed:
IntroCard.astro(conference intro)SponsorCallout.astro(sponsor information)
- Extract social section (lines 154-174)
- Consider making links configurable via props
- Extract footer section (lines 176-188)
- Make copyright year dynamic
Move content from src/main.js with these changes:
- Keep GSAP and ScrollTrigger initialization
- Keep Alpine.js initialization
- Ensure scripts run client-side (use
<script>tag in Astro, not<script is:inline>) - Maintain sessionStorage logic for first-time visitors
Astro Integration Options:
- Option A: Keep as external script loaded via
<script>tag (simpler) - Option B: Use Astro's
<script>tag withis:inlinefor client-side execution - Option C: Break into smaller, component-specific scripts using
<script>in components
In Astro, client-side JS needs special handling:
<!-- In layout or component -->
<script>
import Alpine from 'alpinejs'
import { gsap } from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"
// Initialize on client
if (typeof window !== 'undefined') {
window.Alpine = Alpine
Alpine.start()
gsap.registerPlugin(ScrollTrigger)
window.gsap = gsap
// ... rest of animation code
}
</script>Convert index.html to use Splash layout and components:
---
import Splash from '../layouts/Splash.astro';
import HeroSection from '../components/HeroSection.astro';
import ContentSection from '../components/ContentSection.astro';
import SocialLinks from '../components/SocialLinks.astro';
import Footer from '../components/Footer.astro';
---
<Splash>
<HeroSection slot="hero" />
<ContentSection slot="content" />
<SocialLinks slot="footer" />
<Footer slot="footer" />
</Splash>- Verify all assets in
public/are accessible - Ensure paths remain correct (Astro serves
public/at root) - No changes needed for most assets
npm run devTest Cases:
- ✅ Page loads correctly
- ✅ Fonts load properly
- ✅ Lottie animation plays on first visit (desktop only)
- ✅ Animation skipped on return visits (sessionStorage works)
- ✅ GSAP animations trigger on scroll
- ✅ Alpine.js smooth scroll works
- ✅ Social links work
- ✅ All images and SVGs display
- ✅ PDF download works
- ✅ Schema.org data validates
- ✅ Fathom analytics loads
- ✅ Mobile responsive design works
npm run build
npm run previewVerify:
- Build completes without errors
- Preview server works
- All assets are correctly bundled
- No console errors in browser
Create _redirects (for Netlify):
# Add any necessary redirects
# Astro
dist/
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
# environment variables
.env
.env.production
# macOS
.DS_Store
- Deploy to staging environment
- Test all functionality
- Verify analytics work
- Check performance metrics
Once basic migration is complete, consider adding:
- News/announcements collection
- Sponsor information collection
- Team member profiles
Example structure:
src/
├── content/
│ ├── config.ts (defines collections)
│ ├── news/
│ │ └── *.md
│ ├── sponsors/
│ │ └── *.md
│ └── team/
│ └── *.md
Using the Page layout, create:
- About page
- Code of Conduct page
- Venue information page
- Schedule page (once available)
Build reusable components:
- Button variants
- Card components
- Section wrappers
- Header/Navigation (when needed)
If migration issues arise:
- Keep Vite setup: Don't delete
vite.config.jsor Vite dependencies until Astro is fully working - Git branch strategy: Create
astro-migrationbranch, keepmainstable - Parallel development: Both systems can coexist temporarily
- Incremental cutover: Test on staging before production deployment
- Phase 1 (Setup): 2-3 hours
- Phase 2 (Styles): 3-4 hours
- Phase 3 (Layouts): 2-3 hours
- Phase 4 (Components): 3-4 hours
- Phase 5 (JavaScript): 2-3 hours
- Phase 6 (Pages): 1 hour
- Phase 7 (Testing): 2-3 hours
- Phase 8 (Deployment): 1-2 hours
Total: ~16-23 hours
- Alpine.js works well with Astro
- Keep
x-data,x-init, etc. directives in components - Initialize Alpine in client-side script
- GSAP works great with Astro
- Ensure ScrollTrigger registration happens on client
- Watch for hydration timing issues with animations
- Keep Tailwind: Faster migration, but may need Tailwind v3
- Switch to SCSS: More aligned with 2025 website, more work upfront
- Current implementation uses CSS custom properties in
@theme - These can be preserved in SCSS or standard CSS
- Astro provides better initial page load (static HTML)
- Client-side JavaScript hydration only where needed
- Consider code splitting for animations if page grows
- Astro Documentation
- Astro Migration Guide
- PyCon AU 2025 Website Repository
- Current project structure and dependencies
Migration is complete when:
- ✅ Site builds without errors
- ✅ All pages render correctly
- ✅ All animations work as expected
- ✅ All interactive features functional
- ✅ Analytics tracking works
- ✅ Schema.org markup validates
- ✅ Performance equal or better than Vite version
- ✅ Development experience improved (hot reload, etc.)
- ✅ Documentation updated
- ✅ Team members can work with Astro setup
Document Version: 1.1 Last Updated: 2025-10-12 Author: Development Plan for PyCon AU 2026 Astro Migration
- Updated all package versions to latest stable releases as of October 2025:
- Astro: 5.5.2 → 5.14.4
- @astrojs/mdx: 4.2.0 → 4.3.6
- Sass: 1.77.8 → 1.93.2
- TypeScript: 5.5.4 → 5.9.3
- Prettier: 3.3.3 → 3.6.2
- prettier-plugin-astro: 0.11.1 → 0.14.1
- Initial migration plan created