Responsive landing built with HTML + CSS + vanilla JavaScript only (no frameworks, no UI/JS libraries shipped to the browser).
Live: https://test.symbyanz.ru/
npm install
npm run dev # http://localhost:5173 — auto-minify on save, hot reload
npm run minify # one-shot: emit .min.css / .min.js next to source
npm run build # emit dist/ — minified HTML + the same .min assets
npm run preview # serve dist/ at http://localhost:4173
npm run images # regenerate WebP/AVIF + og-cover.jpg from sources
npm run favicons # regenerate favicon PNGs from favicon.svgindex.html references the minified assets (styles/main.min.css, js/main.min.js, etc.). The unminified .css/.js files are the editable source — npm run minify produces the .min files alongside them, and npm run dev watches source files and refreshes the .min files automatically on save.
npm run build produces dist/ for deploy: minified HTML + the .min.css / .min.js files + static assets. No bundling, no transpilation — csso for CSS, terser for JS (with import paths rewritten to .min.js), html-minifier-terser for HTML.
npm run images / npm run favicons use sharp to (re)generate the modern-format raster set and PNG favicon variants. The committed outputs in assets/img/*.webp, assets/img/*.avif, and assets/favicon/*.png are all reproducible from these scripts.
Static site served by nginx at https://test.symbyanz.ru/. Server-side root: /home/sym/hire-test/ on the symbyanz host. Cert (symbyanz.ru, www.symbyanz.ru, test.symbyanz.ru) is auto-renewed by certbot.timer.
npm run build
rsync -avz --delete --chown=sym:sym dist/ symbyanz:/home/sym/hire-test/The vhost lives at /etc/nginx/sites-available/test.symbyanz.ru (HTTP→HTTPS redirect + cert refs were inserted by certbot). No nginx changes needed for content-only updates.
index.html
site.webmanifest
build.mjs produces dist/ from .min files + assets
scripts/
dev.mjs dev loop: watch source, minify on save, live-server
minify-source.mjs emit .min.css / .min.js next to source
generate-images.mjs WebP/AVIF + og-cover from raster sources
generate-favicons.mjs PNG favicon set from favicon.svg
styles/
reset.css reset + reduced-motion guard
fonts.css @font-face declarations
main.css tokens + layout + components
js/
main.js entry point
modules/
anchors.js smooth-scroll for hero anchor buttons
ticker.js continuous-scroll text ticker
participants-carousel.js looped, auto-advance every 4s
stages-carousel.js manual, no loop, no auto-advance
reveal.js reveal-on-scroll animation
assets/
img/ raster (jpg/png + webp; avif for hero)
fonts/ self-hosted woff2 + woff
favicon/ svg + png set (32, 180, 192, 512)
.claude/
CLAUDE.md project rules for AI assistants
settings.local.json tool permissions
- Pixel-perfect to the Figma layout
- Responsive 320–2560 px, no horizontal scroll, no overflow / overlap
- Hero buttons are anchors that smooth-scroll to their sections
- Ticker — properly looping continuous scroll
- Participants carousel — looped, auto-advances every 4 s
- Stages carousel — manual only, no loop, no auto-advance
- Mobile and desktop don't duplicate text content in the DOM
- One custom animation (reveal-on-scroll, respects
prefers-reduced-motion)