A powerful and clean event calendar for WordPress with recurring events, categories, locations, import/export and more.
  • PHP 57%
  • JavaScript 27.3%
  • CSS 12.8%
  • Shell 2.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Robin bf7f6acecf 1.3.1: filter long category and tag lists
A site with dozens of categories had no way to find one: tagging an
event meant scrolling a checkbox list, and so did managing the terms.

- A filter box above every category and tag list — the event modal's two
  checklists, and both sections of the Categories & tags panel. Matching
  is case- and accent-insensitive (norm() strips diacritics), so
  "theatre" finds "Théâtre".
- Ticked terms stay visible whatever is typed: the filter must never
  hide what the event is already tagged with. Hidden checkboxes keep
  their state, so collect() sends the same values either way.
- Ancestors of a match stay on screen, so a filtered category tree still
  reads as a tree instead of a flat set of orphans.
- No threshold on list length — the box is there on two categories as on
  fifty. A control that sometimes appears is one more mechanism to
  learn, and it also made the feature invisible on the demo site.
- Escape clears the filter instead of closing the modal, and typing in
  one no longer flips the dirty flag: markDirty() ignores the filter's
  input events, so filtering is not an edit.
- Creating a term from the modal starts with whatever was typed in the
  filter, then clears it, so the new ticked term isn't sitting in a list
  that hides everything around it.
- Block inspectors take their category/tag control from
  window.lrobCalendar.termControl() in blocks-shared.js: core's
  searchable ComboboxControl, falling back to SelectControl only where
  the component is missing.
- escAttr() for term names inside attributes. esc() leaves quotes alone,
  and a term named `Fete "du" village` would have broken out of the new
  data-search attribute and of the rename field's value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 10:43:38 +00:00
admin 1.3.1: filter long category and tag lists 2026-09-15 10:43:38 +00:00
assets 1.3.1: filter long category and tag lists 2026-09-15 10:43:38 +00:00
blocks 1.3.1: filter long category and tag lists 2026-09-15 10:43:38 +00:00
includes 1.3.0: migrate off The Events Calendar, fix repeat intervals 2026-09-08 12:35:28 +00:00
languages 1.3.1: filter long category and tag lists 2026-09-15 10:43:38 +00:00
tests 1.3.0: migrate off The Events Calendar, fix repeat intervals 2026-09-08 12:35:28 +00:00
.gitignore v1.2.1: dark themes, properly 2026-08-01 18:45:42 +00:00
CHANGELOG.md 1.3.1: filter long category and tag lists 2026-09-15 10:43:38 +00:00
CLAUDE.md 1.3.1: filter long category and tag lists 2026-09-15 10:43:38 +00:00
deploy.sh v1.2.1: dark themes, properly 2026-08-01 18:45:42 +00:00
LICENSE Initial commit: LRob Calendar v1.0.0 2026-05-14 14:24:43 +02:00
lrob-calendar.php 1.3.1: filter long category and tag lists 2026-09-15 10:43:38 +00:00
publish.sh Point tooling at the single 'origin' remote 2026-08-02 22:55:52 +00:00
README.md Drop every reference to the old GitHub home 2026-08-01 19:27:58 +00:00
release.sh 1.2.2: cut per-request work, finish the category-image removal 2026-08-03 00:26:35 +00:00
uninstall.php v1.1.2: full event info everywhere + demo events + polish 2026-05-16 13:22:31 +02:00

📅 LRob — Calendar

A clean, fast event calendar for WordPress — without the bloat.

Recurring events, a beautiful month grid & agenda, click-to-preview popups, and a modern in-page editor. No page builder required, no SaaS, no clutter.

Plugin homepage: lrob.fr/wordpress/plugins/lrob-calendar


🚀 Highlights

  • 🗓️ Month grid & agenda — click any event for an in-page preview (image, dates, location, description) with prev/next navigation and a full-res lightbox.
  • ✍️ Modern event editor — manage everything from one clean screen; create & edit in a dynamic modal, no page reloads, no block editor needed.
  • 🔁 Recurring events — daily / weekly / monthly / yearly, “2nd Tuesday”, end after N or on a date, exception dates. Shown on every occurrence.
  • 🧩 Three blocks — Calendar, Events List (list / grid / minimal + AJAX pagination), and Single Event.
  • 📍 Locations — venue, address, coordinates, and an OpenStreetMap embed on event pages.
  • 🏷️ Categories & tags — per-category colours, managed inline from the events screen.
  • 📥 Import / Export & migration — JSON import/export, plus one-step migration from The Events Calendar and All-in-One Event Calendar.
  • 🌗 Theme-friendly — looks good on light and dark themes; assets load only where a block is used.
  • 🌍 Translation-ready — English + French included.
  • 🔄 Self-updating — new versions arrive in your Updates screen, straight from git.lrob.net.

🧩 At a glance

Requires WordPress 6.0+
Requires PHP 8.0+
Editor Custom screen + modal (Gutenberg optional)
Text domain lrob-calendar
Build step None — no Composer, no npm

📦 Installation

  1. Download the latest release zip from the releases page — or run ./release.sh locally to build one.
  2. WordPress admin → Plugins → Add New → Upload Plugin → upload the zip.
  3. Activate.
  4. Open Calendar → Settings to set the timezone, first day of the week, the public-pages toggle, and a few performance limits.

⚡ Quick start

  1. Go to Calendar — you land on the custom management screen.
  2. Click + New event. The editor opens in a modal:
    • Title and a short description (simple formatting — bold, italic, lists, links).
    • When — start/end date & time, timezone, or mark it all-day / instant.
    • Recurrence (optional) — frequency, interval, the weekdays, and an end condition. Complex rules are preserved and editable in the WordPress editor.
    • Location, contact, cost (optional).
    • Categories & tags, and a featured image.
  3. Save — it appears instantly in the list and on your calendar.

Need the full block editor for a particular event? The “→ WordPress editor” link in the modal header takes you there at any time.


🧱 The blocks

  • Event Calendar — month grid or agenda layout, with the click-to-preview popup and lightbox.
  • Events List — list, grid, or minimal template, optional AJAX pagination, and an optional, capped number of recent past events.
  • Single Event — embed one specific event anywhere.

Each block loads its own CSS/JS only when present on the page.


📥 Migrating from another plugin

Already using another calendar? On Calendar → Import / Export, the “Migrate from another plugin” box detects data from The Events Calendar or All-in-One Event Calendar, exports it to a JSON file, and you import that file right back — events, dates, recurrence, locations, categories and images included.


🌍 Translations

Ships with English and French. The whole pipeline lives in release.sh (make-pot → translate .po → make-json for the editor → msgfmt). Add a locale by dropping a languages/lrob-calendar-<locale>.po and running the script.


🛠️ For developers

  • No build tooling. Plain PHP + vanilla JS; blocks use wp.element/wp.i18n without JSX. Ship by copying the folder into wp-content/plugins/.
  • Storage. Events live in three custom tables (not postmeta) for fast date-range queries; recurrence occurrences are materialised into an instances table.
  • REST API. …/wp-json/lrob-calendar/v1/events (public, read-only) powers the front-end; an authenticated admin namespace powers the editor.
  • Release. ./release.sh regenerates translations and builds the distributable zip.

See CLAUDE.md for the full architecture notes.


🗺️ Roadmap

Ideas on the radar (suggestions welcome):

  • iCal / ICS — per-event .ics download and a subscribable feed.
  • Frontend event submission with moderation.
  • Email reminders / RSVP.
  • Extra map providers beyond OpenStreetMap.

PRs welcome.


📝 Changelog

See CHANGELOG.md.


💬 Feedback & contributions

Bug reports, feature ideas and pull requests welcome on the issue tracker.


📜 License & credits

Plugin code: GPL-2.0-or-later. See LICENSE.

Built by

LRob — WordPress web hosting specialist based in Orléans, France.


Your events. Your site. No SaaS.