Skip to content
⚠️ This document is AI-translated. The Chinese version is the authoritative source.

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

LayerTechnologyVersionSourcePurpose
FrameworkAstro^5.17.1package.jsonStatic site generator
LanguageTypeScript^5.9.3package.jsonType safety
UI FrameworkNone--Architecture decisionPure Astro components + vanilla JS
CSSCustom CSS--global.cssCSS variables + dark mode
FontsSystem font stack--global.cssNo external font dependencies
DeploymentVercel--vercel.jsonHosting + CDN
HTML MinifycompressHTMLtrueastro.config.mjsReduce file size
Package Managernpm--package-lock.jsonDependency management

System Font Stack

css
--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

RouteFileDescription
/src/pages/index.astroHome page with all main sections
/developerssrc/pages/developers/index.astroDeveloper page, 43KB of rich technical docs
/templatessrc/pages/templates/index.astroTemplate store, iframe-embedded Presto store UI
/showcase/*public/showcase/Pre-rendered static files built by Presto

Component Architecture

text
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

ComponentFile SizeResponsibilities
Header36KBNavigation bar, bilingual toggle, responsive menu, scroll-based styling
Hero7.5KBHero title, version number (auto-synced), download button, background gradient
Features6KBFeature grid layout with icons + bilingual descriptions
Showcase17KBProduct showcase carousel, 5 iframes embedding real Presto UI components
Download16KBDownload section, multi-platform detection (macOS/Windows/Linux), version number (auto-synced)
Footer2KBFooter 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):

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:

  1. Presto repository publishes new version -> repository_dispatch event release-published
  2. sync-release.yml downloads release assets, creates homepage release
  3. Updates version numbers using sed:
bash
# 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
  1. 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):

html
<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):

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):

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: nosniff
    • X-Frame-Options: SAMEORIGIN
    • Referrer-Policy: strict-origin-when-cross-origin
    • Permissions-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:

  1. Parse tag (from client_payload or inputs)
  2. Download release assets from Presto repository (requires PRESTO_PAT)
  3. Create homepage release (same tag name, copy release notes)
  4. Update version numbers (Download.astro + Hero.astro)
  5. Auto-commit and push

sync-showcase.yml

Trigger conditions:

  • Presto repository showcase build completed (repository_dispatch: showcase-updated)
  • Manual trigger (workflow_dispatch)

Steps:

  1. Clean old files (rm -rf public/_app public/showcase)
  2. Download artifact from Presto repository (showcase-static, requires PRESTO_PAT)
  3. Copy to public/ directory
  4. Auto-commit and push

Responsive Design

Breakpoint List

BreakpointDescription
1024pxTablet landscape
900pxTablet portrait
768pxLarge phone / small tablet
640pxPhone landscape
560pxLarge phone portrait
480pxSmall phone portrait

IntersectionObserver Scroll Animations

Implementation (src/layouts/Layout.astro):

javascript
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):

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:

javascript
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

bash
# Local dev server (localhost:4321)
npm run dev

# Build static site to dist/
npm run build

# Preview build output
npm run preview


Presto — Markdown to PDF