Tyumen.Online — City Portal Powered by Real-World Data
ClientConcept project
IndustryCity media, regional portals
Period2026

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.

Astro 5Tailwind CSSVanilla JSRSS parser2GIS APIHTML parsingcron + rsync
Open site ↗

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.

Places catalog from 2GIS on /places — 160 venues across 8 categories

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-*.mjs for RSS / HTML / 2GIS, run as prebuild
  • 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