miffuser
A single-file Progressive Web App that puts the entire MIFF 2026 programme, 349 films across 7 days and 7 venues, in your pocket. Offline. Installed. No app store.
The constraint is the concept.
miffuser began with a single constraint: one file. No build toolchain, no CDN, no server. The entire festival programme, 349 films with schedules, descriptions, and catalogue images, lives in a single index.html that deploys to any static host and runs fully offline after first visit.
Single-file PWA stack
| LAYER | TECHNOLOGY | NOTES |
|---|---|---|
| Data | JS array literal |
349 film objects parsed at startup, zero latency |
| UI | Vanilla JS + HTML |
Direct DOM templating, no virtual DOM, no diffing |
| Styles | CSS custom props |
Full dark/light system via :root token swap |
| Offline | Service Worker |
Cache-first app-shell, all 349 images precached |
| Install | Web App Manifest |
beforeinstallprompt, iOS and Android paths |
| State | localStorage |
11 keys: list, ratings, notes, priorities, settings |
| Export | window.open + print |
Client-side PDF, no server, no library |
At festival scale (349 records, single-user, no real-time sync), a framework adds bundle size and complexity with zero benefit. Vanilla JS renders the full schedule in under 16ms. The constraint produced the architecture.
"What does a real MIFF attendee need on their phone at 9am, offline, queueing for Audi 1?"That question shaped every feature decision, from Live Mode to package slot offset timing.
The main interface.
1. App Header & Live Clock
Icon, title, tagline. Live clock showing current time. Persists across all views.
2. Live Now Toggle
Activates real-time mode. Filters to films currently screening or about to start. Refreshes every 60 seconds.
3. Day Tabs
One per festival day (Jun 15-21) plus All Days. Active tab in gold. In Live Mode, past days are hidden automatically.
4. Full-Text Search Bar
Full-text search across title, director, country, section, language, and venue. Composes with active filters in real time.
5. 10-Dimension Filter Panel
Opens 10-dimension filter panel. Badge shows active filter count when filters are applied.
6. Time-slot Header & Film Cards
Films grouped by screening start time. Title, exact screening window, package slot, venue tag, duration, country, section, director, language.
The schedule clock drives every visible element: active day tab, time-slot visibility, and the "Ended" badge on each film card. Everything updates passively without a refresh.
Every film. Everything.
1. Drag Pill + Close
Bottom-sheet indicator. Dismisses on tap outside or X. Android back button also dismisses.
2. Section Tag
Festival section in red. Always the first element, gives instant context.
3. Watched Toggle
Marks film as watched. Unlocks the post-watch thoughts notes field.
4. Metadata Tags
Country, duration, year, language as pill tags color-coded by type.
5. Catalogue Image
Official MIFF 2026 catalogue page crop with exact page number. Sourced from official materials.
6. Screening Schedule
All slots. Each row shows offset time, package window, venue, date, and an Add button for that slot.
Catalogue Image as Information
When no synopsis exists in the official catalogue, the scanned page replaces it. Attendees get exactly what MIFF published: nothing invented.
Screening-Level Saves
Saving a film saves the specific date, time, and venue slot, not just the title. A film screening four times requires a real decision.
Curate. Save. Track.
| # | DIMENSION | OPTIONS | SAMPLE VALUES |
|---|---|---|---|
| 01 | Priority Mark | 4 | Must Watch, Priority, Good to Go, Unmarked |
| 02 | Section | 30+ | MIFF Prism, Short Comp, Animation Canvas, Best of Fest, Emerging Voices |
| 03 | Country / Language | 55 / 74 | Argentina to Vietnam. Ao to Without Dialogue, across 6 continents |
| 04 | Venue | 7 | Audi 1, Audi 2, RR III, JB Hall, IICT, SVKM, Ravindra Natya Mandir |
Same app. Different light.
15 fields. Zero fetch.
Every film object is complete at parse time. No lazy-loading, no API calls, no spinner. The entire dataset is available the instant the JS executes.
| KEY | TYPE | CONTENT |
|---|---|---|
savedScreenings |
Object | filmId::date::time → true |
miff_priorities |
Object | filmId → "must" | "priority" | "goodtogo" |
miff_watched |
Object | filmId → true |
miff_ratings |
Object | filmId → emoji rating level |
miff_notes |
Object | filmId → {{pre: string, thoughts: string}} |
miffuser_mode |
String | "dark" or "light" |
miffuser_textsize |
String | "small" | "medium" | "large" | "xlarge" |
The why behind the what.
Screening-level bookmarks
My List saves the specific date/time/venue slot, not just the film. A film screening four times requires a real choice. The bookmark is the commitment, not just the intention.
No invented descriptions
Strict data integrity rule: if the official MIFF catalogue provides no synopsis, none is shown. Catalogue page images are used instead. Attendees make real scheduling decisions from this data.
Independent filter state
Schedule and My List maintain separate filter contexts. Returning from a filtered My List to Schedule should never produce a view the user did not consciously set.
Back button = modal dismiss
Modal open/close is pushed to browser history. Android's physical back button dismisses the modal naturally. Double back-press on the main view shows an exit toast, matching native app behaviour.
Package slot offset timing
MIFF programmes short films in packages. "Film C" in a 2PM package might start at 2:18. miffuser calculates and displays the offset start time so attendees know exactly when to walk in.
Notes unlocked by state
"Thoughts after watching" is hidden until the film is marked Watched. Intentional friction: it makes writing post-screening feel like a meaningful moment, not a dead form field.
Built by a filmmaker who needed it.
miffuser was designed and built by Sohaib Ahmer, a filmmaker and Master's student in Film & Video Communication at the National Institute of Design, Ahmedabad.
The project sits at the intersection of both fields: a deep understanding of how festival audiences navigate programmes, and the discipline to build a production quality PWA from scratch. miffuser was developed and iterated during the festival itself.