Tyumen.Online — City Portal Powered by Real-World Data
Multi-page Tyumen city portal built with Astro and refreshed automatically from live sources: news from 72.ru RSS every 3 hours, events from kto72.ru daily, 160+ places from 2GIS weekly. 20+ routes, full SSG, zero runtime cost.
Results
-
11 unique screen templates expand into 20+ routes via dynamic [slug] pages
-
Real data from three sources: 72.ru (RSS, every 3 hours), kto72.ru (HTML-scraped events, daily), 2GIS (places catalog, weekly)
-
Build-time fetching: data is pulled at build and baked into static HTML — zero runtime cost, instant indexing
-
Catalog of 160 Tyumen places across 8 categories with chip-based filtering, no reload
-
Pure static output, served by Nginx in milliseconds, indexable by Yandex/Google from the first byte
The brief
Design and build a city information portal that does not “look like a news site from 2015.” The goal: show what a modern regional portal should look like today — a unified design system, premium-media typography, and at the same time real, non-static content that refreshes automatically without an editor in the loop.
Technically, three problems had to be solved at once: (1) give users fresh news and city events, (2) avoid a cloud CMS bill and avoid running a PHP backend on the server, (3) keep maximum speed and SEO-indexability.
The solution
The stack was chosen as a deliberate “old-school minimal” set: Astro 5 as the static generator, Tailwind CSS via CDN, vanilla JavaScript for interactivity (filters, mobile menu). No React, no Redux, no server runtime — everything renders to HTML at build time.
11 screens → 20+ routes
The design is assembled as a set of unique templates per screen type:
- Home (
/) — hero block plus three news cards and a side stack - News (
/news) — feed with rubric chip filter, sticky bar, sidebar - Events (
/afisha) — events with category filter, cards with prices and age ratings - Places (
/places) — venues catalog with two sections: curated “top” places and the automatic full 2GIS catalog - Transport (
/transport), Services (/services), Search (/search), About (/about) - Dynamic routes:
/article/[slug],/event/[slug],/place/[slug]
Each of the 11 templates expands into real URLs via Astro’s getStaticPaths — the output is 20+ pages, each indexed independently.
Real data from three sources
The core feature of the project is that the content is not invented. Three separate prebuild scripts fetch it:
- News from 72.ru — RSS feed parsing for the publication, date normalization, category and cover extraction. Runs on cron every 3 hours.
- Events from kto72.ru — HTML scraping of the event catalog (a Bitrix template without a public API): cheerio pulls title, price, age rating, image, ticket-buy link. Daily cron.
- Places from 2GIS — calls to the public 2GIS catalog API, fetched across 8 categories (restaurants, cafes, bars, spa, medical, auto, sport, shopping), 160 top-rated places. Weekly cron.
After each fetch, data lands in src/data/*.json and within a few seconds the whole site is rebuilt (astro build). The resulting static output is synced to production over rsync.

Build-time everything — zero runtime cost
This is the key architectural decision. There is not a single PHP process, no Node server, and no database query in production. Nginx serves ready-made HTML files directly — TTFB is measured in tens of milliseconds. Content stays fresh because rebuilds run in the background on a schedule.
The side effect is perfect SEO indexability. All 20+ pages with real data are served to Yandex/Google bots fully rendered, no JavaScript execution required and no hydration risks. That matters for a regional portal that needs to surface in local search.
Design system
A small in-house palette in the spirit of Material Design 3: primary #0048d1 plus container tokens, surface levels from lowest to highest, an accent coral for CTAs, typography on Manrope (headlines) + Inter (body). All tokens are declared in tailwind.config inside the Layout and used consistently across the 11 templates.
Interactivity without a bundle
Chip filters (on /news, /afisha, /places) are 30 lines of plain JS per page — no React, no library. IntersectionObserver is only used for scroll-reveal animations. The frontend bundle is effectively zero; the places page weighs around 200 KB of HTML with 160 venue cards.
Decorative animation
Over the home hero — three blurred gradient blobs that drift in a figure-eight pattern on a 40-second loop. An animated gradient backdrop for hero sections. prefers-reduced-motion: reduce is honored everywhere — animations switch off entirely for users with that preference.
The outcome
The portal runs on a dedicated subdomain with a Let’s Encrypt cert. Content updates automatically — no editor needed. The whole site opens instantly even on weak mobile connections because the response is pure static.
This is a demonstration of how a regional city portal can look and work in 2026: not yet another WordPress CMS with a heavy admin, but a lightweight SSG architecture with a transparent data flow — “source → JSON → HTML → CDN.”
Tech stack
- Framework: Astro 5 (static generation, content collections, dynamic routes)
- Styles: Tailwind CSS via CDN (config declared inside the Layout — no local CSS pipeline)
- JS: vanilla, a tiny inline script per page
- Data builders: Node scripts in
scripts/fetch-*.mjsfor RSS / HTML / 2GIS, run asprebuild - Parsing: cheerio for kto72.ru, built-in XML parser for the 72.ru RSS, fetch for the 2GIS API
- Deploy: rsync over SSH to a VPS, Nginx + Let’s Encrypt
- Schedule: cron on the VPS (news every 3 hours, events daily, places weekly)
Ready to discuss your project?
Free audit and preliminary estimate within 24 hours of your request.
Send a request