Back to portfolio

Case Study · Side Project · iOS & Android

Večeras

Noćas u gradu

An entertainment guide for Banja Luka. The app automatically pulls cinema repertoire from two multiplex cinemas, theater programs from two stages, and music event listings — enriched with global movie data and served to a React Native mobile app.

iOSAndroid2024–2026

Overview

The Problem

Finding out what's on tonight in Banja Luka requires checking multiple separate websites — two cinema chains, two theater venues, and scattered music event listings — each with different formats and update cycles. There was no single place to see everything.

The Solution

A backend that runs on autopilot — scraping, enriching, and storing the data — paired with a polished mobile app that surfaces it all in one place. The system handles data freshness automatically; the app works offline after the first load.

2
Cinemas scraped
2
Theater venues
3
Languages
5+
Cron jobs / day

Mobile App

Built with Expo SDK 54 and React Native. File-based routing via Expo Router v6, React Navigation Drawer for the tab structure, and React Native Paper for Material Design 3 components.

Cinema

Ongoing and upcoming movies for both Cineplexx and Cinestar, switchable by tap. Shows poster, genre, duration, 3rd party rating, and showtimes.

Theater

Full program for Narodno Pozorište RS and Jazavac Banja Luka. Schedule updated automatically via scraper and manual .docx import.

Music

Upcoming music events grouped by date, with venue detail pages including contact info, address, and Instagram links.

Favorites

Movies saved locally to device via MMKV — fast synchronous reads, no network required. Persists across app restarts.

Offline-first

React Query data persisted to MMKV (24 h cache). expo-image handles disk-level image caching. A network banner shows when offline.

Multi-language

Three locales: English, Serbian Latin, Serbian Cyrillic. Language, theme, and accent colour saved to device storage.

Večeras dark theme
Večeras light theme

Backend & Architecture

NestJS 11 with a modular architecture. Each domain (cinema, theater, music, email) lives in its own module. Cinema data is scraped on a recurring schedule, enriched with metadata from external sources, and stored in PostgreSQL via a single atomic transaction. AdminJS provides backoffice management; Resend handles automated email reporting.

Cinema Module

Manages movies, showtimes, and crawl history for both Cineplexx and Cinestar. Exposes REST endpoints consumed by the mobile app.

Theater Module

Handles program schedules for Narodno Pozorište RS and Jazavac. Supports both automated scraping and manual .docx imports.

Music Module

Manages music events with venue detail pages. Events grouped by date with contact info, address, and social links.

Enrichment Module

Enriches each movie with metadata from TMDB and third-party rating sources. Images are uploaded to Cloudinary for CDN delivery.

Admin Module

AdminJS panel for managing movies, locking manually curated entries, and triggering data refreshes without touching the database directly.

Email Module

HTML reports dispatched after every scheduled run — success or failure — with diff highlights showing exactly what changed.

Want the full technical breakdown?

The detailed case study covers the 8-step crawl pipeline, third party web sites scraping strategy, hash-based change detection, concurrency control, and infrastructure setup.

Request the PDF

Tech Stack

Mobile (cinemaAI)

Expo SDK 54React Native 0.81React 19Expo Router v6 (file-based)React Navigation DrawerTanStack React Query v5MMKV (persistence)React Native Paper (Material Design 3)i18next (3 locales)Sentry (crash reporting)TypeScript 5.9

Backend (repertoar-server)

NestJS 11ExpressTypeScript 5.6PostgreSQL 16TypeORM 0.3Crawlee + CheerioCrawlerCheerioAdminJS (admin panel)Resend (email)Docker + Docker Compose

External APIs

TMDB API (movie data)3rd party rating sourcesCloudinary (image CDN)Resend (transactional email)

Infrastructure

Hetzner VPSCoolify (PaaS)Traefik (TLS termination)EAS (Expo Application Services)Google Play Console