Calendari IOC - Building a Modular Academic Calendar Planner
Calendari IOC is the academic planner we use at the Institut Obert de Catalunya to keep module teams aligned. Instead of rewriting spreadsheets every term, the app lets coordinators configure an IOC study plan, drag assignments onto a visual timetable, reconcile conflicts, and export polished calendars for students. It is a single-page application that runs entirely in the browser, so your data never leaves your device unless you decide to export it.
Try It Online Today
The latest build is live at https://itrascastro.github.io/ioc/calendari-ioc/. Open it in any modern browser and Calendari IOC will:
- Bootstrap with the official IOC presets and themes.
- Persist every calendar, category, and UI preference to
localStorage
so you can close the tab and resume later. - Offer a full experience without requiring a login or backend service.
Because it is a static deployment you can also install it on any intranet simply by copying the published files.
Who It Serves
Calendari IOC is built for teachers, heads of department, and course coordinators who need to orchestrate overlapping modules, exams, and tutoring sessions. The interface is multilingual by design (Catalan labels in UI, English-ready data), and the workflow assumes you are planning for real IOC semesters with evaluation periods, modular assignments, and shared milestones.
Why I Built It
During the 2024-2025 academic year I found myself coordinating several FP modules. The spreadsheets we used could not cope with late calendar changes, and copying dates between groups caused endless inconsistencies. I wanted a planner that embraced IOC terminology, respected evaluation periods, and empowered teachers who are not necessarily technical. That constraint—”must run anywhere without installation”—pushed me toward a static, zero-backend SPA with opinionated defaults.
Key Workflows
- Configure a study in minutes: The onboarding wizard guides you through selecting the study type (FP, BTX, or a custom plan). Behind the scenes
StudyTypeDiscoveryService
loads curated JSON describing semesters, evaluation phases, and recommended milestones, so the generated calendar already speaks IOC terminology. - Plan modules visually: The main board gives you month, week, day, semester, compact, and global views. Drag-and-drop repositions events instantly, color coding comes from reusable categories, and the event modal stores descriptions, due dates, and category context.
- Keep categories under control: Create unlimited categories, tweak names or colors with the dedicated color picker, and reuse templates that respect IOC contrast guidelines so exported calendars remain accessible.
- Resolve conflicts with the pending panel: When an event cannot be placed (for example after a replication) it is queued in the “Unplaced Events” tray. From there you can drag it back into the calendar once you free space.
- Clone and synchronize calendars: Replica mode copies milestones from one calendar to another, calculates available ranges, and surfaces warnings before overwriting. It is ideal for duplicating an FP module across parallel groups while keeping their timelines coordinated.
- Share and import safely: The calendar actions menu exports HTML (full and compact versions), ICS, or JSON. Colleagues can import JSON back into the interface, and ICS files slide neatly into institutional calendars.
- Switch themes and stay focused: A one-click theme toggle swaps between light and dark palettes, updating logos and ensuring contrast compliance so long planning sessions stay comfortable on the eyes.
Power Features We Care About
- Centralized modals for setup, event editing, replication, confirmation, and color picking keep the surface consistent across views.
CalendarManager
,EventManager
, andCategoryManager
coordinate state viaAppStateManager
, which serializes cleanly for exports and restores objects throughCalendariIOC_DataRehydrator
.- A dedicated
ErrorManager
prevents silent failures and routes validation messages through the UI helper so teachers always know what happened. - The drag-and-drop helper provides snap-to-slot behaviour, keyboard focus management, and prevents accidental drops outside the timetable.
For Developers and Contributors
Even though the hosted version is ready to use, the project is intentionally simple to hack on:
git clone https://github.com/itrascastro/calendari-ioc.git
cd calendari-ioc
npm install
npm run serve
npm run serve
launches python3 -m http.server
on port 8000 so relative fetch
calls succeed. Open http://localhost:8000
and you will see the same experience as the production build. When you modify scripts or configuration JSON, reload and Bootstrap.initializeAsync()
will rebuild the calendars with your new logic.
Quality checks rely on Cypress end-to-end suites:
npm run test:open
for interactive debugging.npm run test:headless
for CI-friendly validation covering creation, editing, replication, import/export, theming, and pending-event flows.
Architecture in Detail
When I started Calendari IOC I deliberately avoided frameworks so the tool could live inside the IOC firewall without extra build steps. The result is a modular vanilla-JS architecture that still feels maintainable.
Bootstrapping the app
index.html
is responsible for loading the entire dependency graph. Once the DOM is ready, Bootstrap.initializeAsync()
wires together discovery services, managers, renderers, and the global action dispatcher. The boot sequence:
- Loads study presets via
StudyTypeDiscoveryService
(usingfetch
against theconfig/
directory). - Rehydrates any calendars stored in
localStorage
usingCalendariIOC_DataRehydrator
. - Creates instances of
CalendarManager
,EventManager
,CategoryManager
,ReplicaManager
, andViewManager
. - Renders the default monthly view and binds every UI control through data-action attributes.
Managers and application state
All business logic sits in manager classes under js/managers/
. AppStateManager
is the single source of truth: it keeps calendars, categories, UI preferences, and pending events in memory, serializes them to localStorage
, and exposes getters/setters for the rest of the system. Managers subscribe to state changes and expose intent-based methods (addCalendar
, duplicateEvent
, executeReplication
) that the UI layer can call.
Configuration and domain model
Every IOC study type ships as JSON (config/fp.json
, config/btx.json
, etc.) coupled with system-level presets in config/sys/
. These files define semesters, evaluation milestones, suggested categories, and palette choices. At runtime they are materialized into domain objects (CalendariIOC_Calendar
, CalendariIOC_Event
, CalendariIOC_Category
) so behaviour such as validation or replication can live alongside the data.
UI rendering and helpers
The UI layer is broken into dedicated renderers for each view (MonthViewRenderer
, WeekViewRenderer
, SemesterViewRenderer
, CompactViewRenderer
, GlobalViewRenderer
). Helper modules keep the DOM manipulation safe and reusable: UIHelper
batches DOM updates, ColorContrastHelper
enforces accessible palettes, DragDropHelper
adds snapping and keyboard support, while ModalRenderer
centralizes the modals used across the app.
Persistence, replication, and data safety
- Persistence:
StorageManager
syncsAppStateManager
withlocalStorage
, running light migrations when the schema evolves. - Replication:
ReplicaServiceFactory
decides which replica strategy to use (estudis vs generic) and ensures collisions end up in the “Unplaced Events” tray instead of silently overwriting items. - Import & Export: Dedicated exporters generate ICS, HTML, compact HTML, and JSON with the same styling you see on screen; the JSON importer can rebuild a calendar on any other machine in one click.
- Error handling:
ErrorManager
wraps operations intry/catch
, translating meaningful messages into toasts or modal warnings so the user never loses context.
Styling and accessibility
CSS is organized into layers (variables
, base
, layout
, components
, calendar
, themes
). Theme toggling swaps logos and color variables, and the layout uses Flexbox plus CSS Grid to stay responsive on tablets and desktops alike. Focus states, aria-labels, and contrast helpers were tuned specifically for long planning sessions with real teachers.
Testing and delivery
Every critical workflow is covered by Cypress specs under cypress/e2e/
. They automate calendar creation, replication, category management, theme switching, and import/export flows. Because the project is static, continuous delivery is as simple as copying the compiled assets to GitHub Pages or an internal web server.
Roadmap
We are already exploring the next major upgrades:
- Enable weekday-respecting replication so weekend-intensive modules stay aligned after cloning.
- Add linting and unit tests around the managers to complement the Cypress regression suite.
- Offer an optional shared workspace (IndexedDB or lightweight backend) for teams that prefer collaborative editing over file exchange.
Until then, Calendari IOC is battle-tested for the current academic year. Launch it from the public URL, export the calendar formats you need, and keep your team working from the same source of truth.