Presto Website Architecture
The Presto website (Presto-homepage) is a purely static site built with Astro 5, deployed on the Vercel platform. It integrates with the main repository (Presto) via CI/CD to achieve automatic version number synchronization and Showcase static file updates. As of March 2026.
System Overview
Tech Stack Overview
| Layer | Technology | Version | Source | Purpose |
|---|---|---|---|---|
| Framework | Astro | ^5.17.1 | package.json | Static site generator |
| Language | TypeScript | ^5.9.3 | package.json | Type safety |
| UI Framework | None | -- | Architecture decision | Pure Astro components + vanilla JS |
| CSS | Custom CSS | -- | global.css | CSS variables + dark mode |
| Fonts | System font stack | -- | global.css | No external font dependencies |
| Deployment | Vercel | -- | vercel.json | Hosting + CDN |
| HTML Minify | compressHTML | true | astro.config.mjs | Reduce file size |
| Package Manager | npm | -- | package-lock.json | Dependency management |
System Font Stack
--font-sans:
system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", Roboto,
Oxygen, Ubuntu, Cantarell, sans-serif;
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;Page Routes and Component Responsibilities
Page Route Structure
| Route | File | Description |
|---|---|---|
/ | src/pages/index.astro | Home page with all main sections |
/developers | src/pages/developers/index.astro | Developer page, 43KB of rich technical docs |
/templates | src/pages/templates/index.astro | Template store, iframe-embedded Presto store UI |
/showcase/* | public/showcase/ | Pre-rendered static files built by Presto |
Component Architecture
src/
├── components/
│ ├── Header.astro # Navigation bar (36KB)
│ ├── Hero.astro # Hero section (version number, download button)
│ ├── Features.astro # Feature showcase
│ ├── Showcase.astro # Live UI showcase (iframe)
│ ├── Download.astro # Download section (multi-platform detection)
│ └── Footer.astro # Footer
├── layouts/
│ └── Layout.astro # Global HTML shell (i18n detection, scroll animations)
└── styles/
└── global.css # Global styles (CSS variables, responsive breakpoints)Component Responsibilities
| Component | File Size | Responsibilities |
|---|---|---|
| Header | 36KB | Navigation bar, bilingual toggle, responsive menu, scroll-based styling |
| Hero | 7.5KB | Hero title, version number (auto-synced), download button, background gradient |
| Features | 6KB | Feature grid layout with icons + bilingual descriptions |
| Showcase | 17KB | Product showcase carousel, 5 iframes embedding real Presto UI components |
| Download | 16KB | Download section, multi-platform detection (macOS/Windows/Linux), version number (auto-synced) |
| Footer | 2KB | Footer links, copyright info |
Key Architecture Decisions
1. Showcase iframe Embedding
What: The Showcase section on the home page embeds real Presto application UI components (not screenshots) via iframes.
Why:
- Real interactive experience: Users can actually interact with the Presto interface, not just static images
- Auto-updates: When Presto builds new showcase static files, they are automatically synced to the website via CI
- Reduced maintenance cost: No need to manually capture and replace screenshots
- Performance optimization:
loading="lazy"+sandbox="allow-scripts allow-same-origin"security sandbox
Implementation details (src/components/Showcase.astro):
<iframe
src={s.iframeSrc}
loading="lazy"
sandbox="allow-scripts allow-same-origin"
class="showcase-iframe"
title={s.en}
></iframe>5 showcase scenarios:
/showcase/editor-gongwen-- Editor: Official Document/showcase/editor-jiaoan-- Editor: Lesson Plan/showcase/batch-- Batch Conversion/showcase/templates-- Template Management/showcase/drop-- File Drop
2. Template Store iframe Embedding
What: The /templates page embeds Presto's /showcase/store-templates via iframe; the store UI is maintained in the Presto repository.
Why:
- Separation of concerns: Template store business logic belongs to the main app; the website only handles presentation
- Consistency: Template store UI stays consistent with the Presto desktop app
- Independent updates: Store UI updates don't require website code changes
- Reduced duplication: Avoids maintaining the same store UI in two repositories
3. Automatic Version Number Sync
What: sync-release.yml automatically updates version numbers in Hero.astro and Download.astro when Presto publishes a new version.
Why:
- Prevents manual errors: Version number inconsistency could lead users to download wrong versions
- Reduced maintenance cost: Release process is automated, no manual website code changes needed
- Timeliness: Version number updates are triggered immediately after Presto releases
Implementation mechanism:
- Presto repository publishes new version ->
repository_dispatcheventrelease-published sync-release.ymldownloads release assets, creates homepage release- Updates version numbers using
sed:
# Download.astro
sed -i "s/^const version = '.*';$/const version = '${VER}';/" src/components/Download.astro
# Hero.astro
sed -i "s/Latest v[0-9][0-9.]*/Latest v${VER}/" src/components/Hero.astro- Auto-commits and pushes, triggering Vercel auto-deployment
4. Bilingual System
What: All text is wrapped in <span class="zh"> + <span class="en">, toggled via CSS.
Why:
- Simple and efficient: Pure CSS implementation, no i18n framework needed
- Avoids FOUC (Flash of Unstyled Content): Layout.astro detects language via inline script before rendering
- Performance optimization: No additional JavaScript switching logic needed
- Easy maintenance: All text is centralized within components, no external translation files needed
Implementation mechanism (src/layouts/Layout.astro):
<script is:inline>
(function () {
var stored = localStorage.getItem("presto-lang");
var lang = stored || (navigator.language.startsWith("zh") ? "zh" : "en");
document.documentElement.lang = lang;
})();
</script>CSS switching logic (src/styles/global.css):
html[lang="en"] .zh {
display: none;
}
html[lang="zh"] .en {
display: none;
}5. Dark Mode
What: Pure CSS @media (prefers-color-scheme: dark) auto-switching, no JS toggle button.
Why:
- Follows system: User's system settings are automatically applied, no manual switching needed
- Performance optimization: No JavaScript runtime overhead
- Simplified code: No theme state and switching logic to maintain
- CSS variables: All colors defined via CSS variables, smooth transitions
Implementation mechanism (src/styles/global.css):
:root {
--color-bg: #ffffff;
--color-text: #0f172a;
--color-accent: #2563eb;
}
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #09090b;
--color-text: #fafafa;
--color-accent: #60a5fa;
}
}6. Zero-Framework Strategy
What: No React/Vue/Svelte or other frontend frameworks; pure Astro components + inline vanilla JS.
Why:
- Performance first: Pure static HTML, no hydration overhead
- Simplified build: No complex build configuration for frontend frameworks
- Reduced bundle size: No framework runtime to load
- SEO friendly: All content rendered as static HTML at build time
- Low maintenance cost: No framework version upgrades and dependency compatibility issues
The only JavaScript:
- i18n language detection (inline script, 15 lines)
- Scroll animation IntersectionObserver (inline script, 30 lines)
- Showcase carousel logic (inline script, within Showcase.astro)
Deployment Process and CI Integration
Vercel Auto-Deployment
Presto-homepage is connected to the Vercel platform. Every new commit to the main branch automatically triggers a build and deployment.
Configuration (vercel.json):
cleanUrls: true-- No .html suffix- Security headers:
X-Content-Type-Options: nosniffX-Frame-Options: SAMEORIGINReferrer-Policy: strict-origin-when-cross-originPermissions-Policy: camera=(), microphone=(), geolocation=()Content-Security-Policy:default-src 'self'; script-src 'self' 'unsafe-inline';style-src 'self' 'unsafe-inline'; img-src 'self' data:;frame-src 'self'; connect-src 'self'; font-src 'self'
CI Workflow Integration
sync-release.yml
Trigger conditions:
- Presto repository publishes new version (
repository_dispatch: release-published) - Manual trigger (
workflow_dispatch, requires specifying tag)
Steps:
- Parse tag (from
client_payloadorinputs) - Download release assets from Presto repository (requires
PRESTO_PAT) - Create homepage release (same tag name, copy release notes)
- Update version numbers (Download.astro + Hero.astro)
- Auto-commit and push
sync-showcase.yml
Trigger conditions:
- Presto repository showcase build completed (
repository_dispatch: showcase-updated) - Manual trigger (
workflow_dispatch)
Steps:
- Clean old files (
rm -rf public/_app public/showcase) - Download artifact from Presto repository (
showcase-static, requiresPRESTO_PAT) - Copy to
public/directory - Auto-commit and push
Responsive Design
Breakpoint List
| Breakpoint | Description |
|---|---|
| 1024px | Tablet landscape |
| 900px | Tablet portrait |
| 768px | Large phone / small tablet |
| 640px | Phone landscape |
| 560px | Large phone portrait |
| 480px | Small phone portrait |
IntersectionObserver Scroll Animations
Implementation (src/layouts/Layout.astro):
document.addEventListener("DOMContentLoaded", function () {
var els = document.querySelectorAll(".animate-on-scroll");
if (!("IntersectionObserver" in window)) {
// Fallback: show all elements directly
els.forEach(function (el) {
el.classList.add("is-visible");
});
return;
}
var observer = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add("is-visible");
observer.unobserve(entry.target); // Trigger only once
}
});
},
{ threshold: 0.05, rootMargin: "0px 0px -20px 0px" },
);
els.forEach(function (el) {
observer.observe(el);
});
});CSS animations (src/styles/global.css):
.animate-on-scroll {
opacity: 0;
transform: translateY(16px);
transition:
opacity 0.6s ease,
transform 0.6s ease;
}
.animate-on-scroll.is-visible {
opacity: 1;
transform: translateY(0);
}Showcase iframe Scaling
The Showcase iframe has a fixed width of 1200px and is dynamically scaled via JavaScript to fit the container width:
function scaleIframes() {
var containers = document.querySelectorAll(".slide-image");
for (var i = 0; i < containers.length; i++) {
var iframe = containers[i].querySelector(".showcase-iframe");
if (!iframe) continue;
var cw = containers[i].offsetWidth;
var scale = cw / 1200;
iframe.style.transform = "scale(" + scale + ")";
containers[i].style.height = Math.round(800 * scale) + "px";
}
}Performance Optimization
Build-Time Optimization
- compressHTML: true -- Astro automatically compresses HTML
- System font stack -- No external font loading, avoids FOUT
- Purely static site -- No server-side rendering, CDN direct caching
Runtime Optimization
- Lazy loading iframes -- Showcase iframes loaded lazily
- IntersectionObserver -- Animations triggered only when visible
- CSS variables -- Dark mode switching with no repaint overhead
- will-change: transform -- Carousel animation GPU acceleration
Vercel Optimization
- Global CDN -- Static assets served from nearest edge node
- HTTP/2 -- Multiplexing, reduced connection overhead
- Auto compression -- Gzip/Brotli compression
Development Commands
# Local dev server (localhost:4321)
npm run dev
# Build static site to dist/
npm run build
# Preview build output
npm run previewRelated Documentation
- Software Architecture -- Component boundaries and data flow of the Presto main application
- CI/CD Pipeline -- Complete CI/CD configuration for Presto repositories
- Presto-homepage/CLAUDE.md -- Website development constraints and conventions
