Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/minnesota-furs/onlinesched/archive/refs/heads/main.zipA flexible event scheduling plugin for WordPress conventions and organizations.
Dedication
This project is dedicated in memory of Cyn and Snap.
Both supported me during the years this tool was being built, and both helped keep me moving when the work was heavier than it looked. They are part of why this project made it across the line.
Community and Support
We built OnlineSched for Furry Migration, but we are sharing it because we want other conventions and community organizations to have a capable scheduling tool without starting from scratch. It is our gift to the wider community, and both nonprofit and for-profit organizations are welcome to use it.
Furry Migration is a nonprofit organization, and this project is maintained by volunteers. We are happy to help when we can. If a for-profit organization needs dedicated support beyond what our volunteers can provide, please reach out so we can talk about options.
Acknowledgements
OnlineSched began as a prototype built by the original Furry Migration team, with Ringer and Mouring as key builders. It was later expanded, updated, and cleaned up for this open-source release. The project reflects the work of everyone who contributed along the way.
Contents
- Installation
- First-Time Setup
- Managing Cancellations
- Embedding the Schedule
- Calendar Feeds and External Endpoints
- Favorites and Privacy
- Customizing the Look
- For Theme Developers
- WP-CLI Schedule Maintenance
- Development and Testing
Installation
You can install this plugin either by downloading a pre-built release or by building it from source.
Option 1: Download from GitHub Releases (Recommended)
- Go to the Releases page on GitHub.
- Download the
OnlineSched-x.x.x.zipfile from the latest release. - In your WordPress admin dashboard, go to Plugins > Add New Plugin > Upload Plugin.
- Choose the downloaded zip file and click Install Now.
- Activate the plugin.
Option 2: Build from Source
If you are developing the plugin or want to build it yourself:
- Clone the repository into your WordPress
wp-content/pluginsdirectory:git clone https://github.com/minnesota-furs/OnlineSched.git cd OnlineSched - Install PHP dependencies via Composer:
composer install --no-dev - Install Node dependencies and build the assets:
npm install npm run build - Activate the plugin in your WordPress admin dashboard.
If you want to package a release zip locally, run npm run release. This generates a clean installation zip in the dist/ directory.
First-Time Setup
After activating the plugin, complete these steps before your schedule will appear:
- Create your schedule page. Add a new Page in WordPress, give it a title such as "Schedule," set its template to Online Schedule, and publish it.
- Connect the page to OnlineSched. Go to Event Scheduling > Event Settings and select the page you just created as the Schedule page. If you also use Kiosk, Live, Hours, or Map pages, assign those here too.
- Set the active year. Enter the current convention or schedule year on the same settings screen.
- Add events. Go to Event Scheduling > Events and assign each event its room, day, tags, and panelists.
- Optional: customize the display. Use the Colors and Header Flare settings to match your organization's visual identity.
- Optional: configure social login. Go to Event Scheduling > Social Login to add credentials for the providers you want to use. No login providers appear until credentials are configured.
Once those pieces are in place, the schedule is ready to publish.
Managing Cancellations
When an event is cancelled, keep it published so people can see what happened. Open the event in the Classic Editor, find the Cancellation panel, check This event is cancelled, and update the event.
That checkbox is a shortcut for OnlineSched's existing Cancelled Tag Type.
It does not create another cancellation field or change the event's publication
status. The checkbox and the native Tag Type box stay synchronized when either
the Cancelled or Canceled spelling is added or removed.
Avoid moving a cancelled event to Trash or changing it to Draft, Pending Review, or Private. Those actions make it disappear from schedules, calendar feeds, and companion applications. OnlineSched shows a warning before common editor and Events list actions remove a published event from public output.
Embedding the Schedule (Shortcode)
You can easily embed the schedule on any post or page using the shortcode:
[onlinesched_schedule]
Optional Attributes:
mode- Set tostandard(default),kiosk(hides favorites/login), orlive. Example:[onlinesched_schedule mode="kiosk"]tabs- A comma-separated list of tabs to display. Default isprogramming,essentials,hours. Example:[onlinesched_schedule tabs="programming,hours"]tag- Pre-filter the schedule to only show events with a specific tag slug. Example:[onlinesched_schedule tag="fursuiting"]room- Pre-filter the schedule to only show events in a specific room slug. Example:[onlinesched_schedule room="mainstage"]
Limitations
Use only one [onlinesched_schedule] shortcode per page.
Each schedule uses a fixed set of element IDs for tabs, event links, and modals. Adding a second schedule creates duplicate IDs, so its tabs and event links may control the first schedule instead.
If you need two schedule views, use one shortcode with the tabs, tag, or room attribute, or place the views on separate pages and link between them. The dedicated Online Schedule page template has the same one-schedule-per-page limitation.
Theme Asset Integration
The plugin loads its typeface and icon font under their own stylesheet handles, so a theme that already provides either can opt out without touching the main bundle:
add_filter( 'onlinesched_load_fonts', '__return_false' );
add_filter( 'onlinesched_load_fontawesome', '__return_false' );
To keep the stylesheet but change the typeface, override the CSS variable instead of disabling the handle:
add_action( 'wp_head', function () {
echo ':root{--os-font-family:"YourFont",sans-serif;}';
} );
Sizes inside the schedule are em-relative to --os-font-size-base, so the
surrounding theme's body size does not distort internal proportions. Override it
when your content uses a different base:
:root { --os-font-size-base: 18px; }
Calendar Feeds and External Endpoints
OnlineSched exposes public read-only endpoints for calendar clients, kiosks, signage, and other external displays. These endpoints return events from the configured schedule year only.
Single Event ICS
Use this when you need one event as an .ics file:
/wp-content/plugins/OnlineSched/ical.php?cal-id=123
Parameters:
cal-id- WordPress post ID for anos_event.
Filtered Schedule ICS
Use this for full-schedule or filtered calendar subscriptions:
/wp-content/plugins/OnlineSched/icalby.php
/wp-content/plugins/OnlineSched/icalby.php?room=main-stage
/wp-content/plugins/OnlineSched/icalby.php?tag=essentials
/wp-content/plugins/OnlineSched/icalby.php?room=main-stage,panel-room-a&tag=essentials&limit=10&textlen=300
/wp-content/plugins/OnlineSched/icalby.php?room=all
/wp-content/plugins/OnlineSched/icalby.php?tag=all&textlen=0
/wp-content/plugins/OnlineSched/icalby.php?room=all&cancelled_title_prefix=true
/wp-content/plugins/OnlineSched/icalby.php?events=123,456
Parameters:
roomorrooms- one or moreos_roomslugs, comma separated. Useallfor all rooms.tagortags- one or moreos_tagslugs, comma separated. Useallfor all tags.events- up to 100 publicos_eventpost IDs, comma separated. Membership stays fixed while event details continue to update.limit- maximum number of upcoming events to include.textlen- maximum description length. Default is250; use0or a negative value for full descriptions.cancelled_title_prefix- set to1,true,yes, oronto prefix cancelled event summaries withCancelled -. This opt-in compatibility aid is limited to full and filtered schedule ICS feeds.
Cancelled events are included with STATUS:CANCELLED. The optional title prefix supplements
that standards-compliant status for display systems that do not show cancellation state; it
does not change stored event titles, individual event feeds, or any other output.
ICS output uses UTC DTSTART/DTEND values with trailing Z, CRLF line endings,
folded content lines, METHOD:PUBLISH, and text/calendar; method=PUBLISH response
headers for broad compatibility with Google Calendar/Gmail, Outlook, Microsoft 365,
Apple Calendar, and Android calendar apps. Calendar metadata includes the configured
calendar name and the site's WordPress timezone. Event UIDs are generated as globally
scoped values using the site host.
Schedule Subscription Publishing
Disabling schedule subscriptions empties full and filtered schedule feeds. It does not disable individual event calendar actions.
When you are preparing a new schedule year, you can pause full-schedule calendar subscriptions without taking away the calendar buttons on events that are already visible. Go to Event Scheduling > Event Settings > Schedule Calendar Subscriptions and clear Publish full-schedule calendar subscriptions.
While publishing is disabled:
- Full and filtered schedule feeds return a valid empty calendar, including feeds filtered by room or tag.
- Full-schedule subscription buttons are hidden.
- Existing subscribers stay connected and receive the schedule again after publishing is re-enabled at the same feed URL.
- Individual event calendar actions remain available because those events are already visible on the schedule page.
- The public schedule, individual event feeds, and JSON feed are unchanged.
The setting is enabled by default on upgrade. Calendar applications decide when to refresh subscriptions, so changes may not appear immediately after you pause or resume publishing.
JSON Feed
OnlineSched includes a public JSON app feed for the companion app, kiosks, and other structured clients that need schedule, hours, and info data without loading the full interactive schedule.
Breaking change in 3.0.0: json.php replaced its former signage-oriented output
(a flat array of room/title/startTime/description) with the sectioned,
schema-versioned contract documented below. This was a deliberate, owner-accepted
break made while the project had no known external feed consumers; see
CHANGELOG for the full list of what changed. Signage displays built
against the old output should migrate to ?section=schedule.
The feed has four sections, selected with ?section=:
/wp-content/plugins/OnlineSched/json.php?section=meta
/wp-content/plugins/OnlineSched/json.php?section=schedule
/wp-content/plugins/OnlineSched/json.php?section=hours
/wp-content/plugins/OnlineSched/json.php?section=info
/wp-content/plugins/OnlineSched/json.php?section=info&page=parking
/wp-content/plugins/OnlineSched/json.php
Omitting section is the same as ?section=schedule.
meta — handshake
The first call an app makes. Reports the schema version, a revision number per section, a composed change stamp, the convention window, publication state, and the configured info-page index.
{
"schema_version": 1,
"con_name": "Furry Migration",
"year": "2026",
"timezone": "America/Chicago",
"revisions": { "schedule": 41, "hours": 7, "info": 12 },
"change_stamp": "41.7.12",
"con_start": "2026-09-09",
"con_end": "2026-09-14",
"public_dates": {
"start": "2026-09-11",
"end": "2026-09-13",
"start_at": "2026-09-11T10:00:00-05:00",
"end_at": "2026-09-13T18:00:00-05:00"
},
"schedule_published": true,
"essentials": {
"label": "Essentials",
"tags": ["essentials", "guest-of-honor", "special-guest", "vip"]
},
"sections": ["schedule", "hours", "info"],
"info_pages": [
{ "slug": "parking", "title": "Parking", "updated": "2026-07-20T15:04:00Z" }
],
"resources": {
"schedule": {
"url": "https://www.furrymigration.org/wp-content/plugins/OnlineSched/json.php?section=schedule&rev=41",
"schema_version": 1,
"enabled": true,
"revision": "41"
},
"hours": {
"url": "https://www.furrymigration.org/wp-content/plugins/OnlineSched/json.php?section=hours&rev=7",
"schema_version": 1,
"enabled": true,
"revision": "7"
},
"info": {
"url": "https://www.furrymigration.org/wp-content/plugins/OnlineSched/json.php?section=info&rev=12",
"schema_version": 1,
"enabled": true,
"revision": "12"
}
},
"links": {}
}
An app can poll meta cheaply. A 304 Not Modified ends the pass. On a changed
response, resources gives each core section's exact revisioned URL, schema,
enabled state, and opaque revision. Clients fetch only resources whose published
revision differs from their last successful local commit. A matching revisioned
URL is immutable. A stale revision returns 409 with Cache-Control: no-store.
Legacy URLs without rev remain available with a 60-second lifetime.
essentials contains the label and tag slugs selected by an administrator on
the Essentials settings page. A deliberately empty tags array remains empty;
clients must not replace it with a conventional default tag.
Site plugins can add independently published resources through the
onlinesched_app_feed_meta_resources filter. The filter must only read completed
local publication state; it must not fetch, render, or mutate data while Meta is
being built. Enabled entries without both a URL and revision are dropped.
links is a site-provided endpoint map, empty by default. A theme or plugin can
add entries through the onlinesched_app_feed_meta_links filter (an associative
array of name => url) to advertise additional site-specific feeds alongside this
one, letting clients discover them from the handshake instead of hardcoding URLs.
schedule — full active-year schedule
{
"schema_version": 1,
"generated": "2026-07-23T14:02:11Z",
"timezone": "America/Chicago",
"year": "2026",
"schedule_published": true,
"rooms": [{ "slug": "main-stage", "name": "Main Stage" }],
"tags": [{ "slug": "essentials", "name": "Essentials" }],
"events": [
{
"event_uid": "2026:OPENCER01",
"wp_post_id": 417,
"title": "Opening Ceremonies",
"start": "2026-09-11T18:00:00-05:00",
"end": "2026-09-11T19:00:00-05:00",
"rooms": ["main-stage"],
"tags": ["essentials"],
"panelists": ["Board"],
"description_html": "<p>Kick off Furry Migration 2026 with the board and special guests.</p>",
"cancelled": false,
"adult": false,
"modified": "2026-07-20T12:00:00Z"
}
]
}
Parameters (same room/tag matching as the ICS schedule feed):
roomorrooms- one or moreos_roomslugs, comma separated. Omit this value or useallto include every room.tagortags- one or moreos_tagslugs, comma separated. Useallto include every tag.group- a named room/tag group (see JSON Groups below). A requested-but-unconfigured group returns an empty schedule rather than guessing.
cancelled and adult are derived from tag names, matched case-insensitively: an
event tagged Cancelled (or Canceled) reports cancelled: true; an event tagged
Restricted reports adult: true. event_uid is a durable identity safe to key
app-side favorites and reminders on — see Event UID below.
When schedule publication is turned off (see App Feed Settings
below), this section still responds 200 OK with schedule_published: false and
empty events/rooms/tags arrays — never an error or a 404.
hours — configured Hours page, losslessly
A direct export of the Hours blocks on the page configured under **Event Scheduling
Event Settings > Hours Page**. Free-form hours/note text is exported as sanitized plain text (
sanitize_text_field) preserving the authored structure; there is no open/close time parsing.
{
"schema_version": 1,
"generated": "2026-07-23T13:40:00Z",
"departments": [
{
"name": "Dealers Den",
"location": "",
"days": [
{ "day": "Friday", "entries": [{ "hours_text": "Noon – 6 PM", "note": "" }] }
]
}
]
}
info — admin-curated pages
/wp-content/plugins/OnlineSched/json.php?section=info
returns the configured page index:
{
"schema_version": 1,
"generated": "2026-07-23T12:00:00Z",
"pages": [
{ "slug": "parking", "title": "Parking", "updated": "2026-07-20T15:04:00Z" }
]
}
Add &page={slug} for one page's sanitized content and image list:
/wp-content/plugins/OnlineSched/json.php?section=info&page=parking
{
"schema_version": 1,
"generated": "2026-07-23T12:00:00Z",
"page": {
"slug": "parking",
"title": "Parking",
"updated": "2026-07-20T15:04:00Z",
"content_html": "<h2>Ramps</h2><p>The closest ramp is attached to the hotel.</p>",
"images": ["https://example.org/wp-content/uploads/2026/07/parking-map.png"]
}
}
An unknown slug returns 404 with {"schema_version": 1, "error": "unknown_info_page"}.
ETag / Last-Modified / 304
Every section response sends ETag and, once a section has moved at least once,
Last-Modified. Send the returned ETag back as If-None-Match on the next request
to get a 304 Not Modified with no body when nothing has changed. ETags combine the
schema version, the section's revision number, the request's resolved filters, and a
hash of the exact response bytes — so an ETag changes if and only if the
representation changes, and identical representations keep identical ETags. Body,
ETag, and Last-Modified are always derived from one coherent revision snapshot,
even when schedule edits land mid-request.
Meta and legacy section URLs send Cache-Control: public, max-age=60. A matching
revisioned Schedule, Hours, or Info URL sends
Cache-Control: public, max-age=31536000, immutable. Cache keys must retain the
complete query string, including Schedule filters and the Info page slug.
Event UID
event_uid is stable across CSV reimports, so it is safe to key app-side favorites
and reminders on. Imported events derive it from the schedule year and the CSV's
external event ID, so deleting and reimporting a schedule year reproduces the same
UID for the same external ID. Manually created events (no external ID) get a UUID
generated once and persisted in post meta.
App Feed Settings
Configured under Event Scheduling > Event Settings > App Feed:
- App Schedule Publication - controls the
schedulesection only, independent of Schedule Calendar Subscriptions (ICS) above. When disabled,scheduleresponds successfully withschedule_published: falseand emptyevents/rooms/tagsso app clients can show an intentional pre-publication state. Themeta,hours, andinfosections, and the public schedule page, are unaffected. - Operational Start/End Date - the convention's operational window, including
pre-con setup and post-con activities such as dead dog. Reported in
metaascon_start/con_end. The start date must be on or before the end date; saving an inverted pair keeps the previously saved dates and shows an error instead. - Public Start/End Date and Time - the official public convention window in
the WordPress site timezone.
public_dates.start/endremain date-only for display compatibility;public_dates.start_at/end_atare offset-bearing instants for app countdowns. Legacy date-only settings are treated as midnight. The same start-before-end rule applies, including times on the same day. - App Info Pages - the pages served by the
infosection (parking, hotel, code of conduct, and similar), picked from a page dropdown and added to an ordered list with an Add button. Use the list's Up/Down/Remove controls to reorder or drop a page; the order shown is the order the app feed serves them in. Only published pages appear in the feed.
Section revisions bump automatically on every relevant change: event saves, publish/trash/restore, taxonomy term edits, CSV imports and year deletes (each as one batch touch, not once per row), and the settings above.
JSON Groups
Groups let a site keep short, readable feed URLs for the schedule section (signs,
kiosks, and other external displays). OnlineSched does not ship organization-specific
groups by default. If a group is requested but not configured, the schedule section
returns an empty result instead of guessing.
Add groups from a theme or small site plugin with the os_json_room_groups filter:
add_filter(
'os_json_room_groups',
function ( $groups ) {
$groups['programming'] = array(
'rooms' => array(
'main-stage',
'panel-room-a',
'panel-room-b',
'workshop-room',
),
);
$groups['gaming'] = array(
'exclude_rooms' => array(
'main-stage',
'panel-room-a',
'panel-room-b',
'registration',
),
'exclude_tags' => array(
'open-gaming',
),
);
return $groups;
}
);
The available group keys are up to your site. For example, a site could use
group=dealers, group=main-events, or group=kids-track as long as those keys are
registered through the filter.
Sites that prefer configuration over code can store an array or JSON object in the
onlinesched_json_room_groups option. The filter still runs after the option is read,
so a theme can add, change, or remove groups for the current site.
Finding Slugs
Room and tag filter values use WordPress term slugs, not display names. For example, a
room named Main Stage may have the slug main-stage.
Admins can place this shortcode on a private utility page to show current endpoint examples and copyable room/tag slugs:
[ical_schedule_cheat_display]
Feed Caching
Calendar clients control how often they refresh subscriptions. Apple, Google, Outlook, and other clients may cache feeds for hours or longer. The schedule page is always the most current source when last-minute changes matter.
Favorites and Privacy
Visitors can star events without logging in. Those logged-out favorites are stored only in that visitor's browser as local schedule state, are not private account data, and are not synced to the server. They can be changed by anyone using the same browser profile.
If Social Login is configured and the visitor logs in, OnlineSched ties synced favorites to the active OAuth session and merges the browser-local favorites into that server-side favorite list. Logging out ends the synced session; the local browser favorites feature continues to work without requiring login.
Customizing the Look
Colors
Go to Event Scheduling → Event Settings → Colors. Every color the plugin uses is configurable there — no CSS required. Changes take effect immediately across the schedule, badges, tabs, and modals.
Fonts
The plugin ships with Metropolis as its default schedule font. It loads this from your server as a self-hosted web font — no Google Fonts, no external requests.
If your theme already provides Metropolis (for example, via Adobe Fonts / Typekit), you can tell the plugin not to load its own copy to avoid downloading the font twice. Add this to your theme's functions.php:
// Our theme already loads Metropolis — skip the plugin's copy.
add_filter( 'onlinesched_load_fonts', '__return_false' );
If you want a completely different font, you don't need to disable anything. Just override the CSS variable after the plugin's stylesheet loads:
// In functions.php or a custom plugin — point the schedule at your own font.
add_action( 'wp_head', function () {
echo '<style>:root { --os-font-family: "Your Font Name", sans-serif; }</style>';
} );
The --os-font-family variable controls the day-header and hour-header typeface. Everything else inherits from your theme.
Icons (Font Awesome)
The schedule uses Font Awesome Free for icons like the calendar, star, copy, and clock symbols. The plugin loads its own copy so it works even if your theme doesn't include Font Awesome.
The Coyote icon used in the Floof Den demo comes from SVGRepo and is available under the CC0 license.
If your theme already loads Font Awesome, add this to your functions.php to prevent loading it twice:
// Our theme already enqueues Font Awesome — skip the plugin's copy.
add_filter( 'onlinesched_load_fontawesome', '__return_false' );
If you're unsure whether your theme loads it, leave the filter off. Loading it twice doesn't break anything visually — it just wastes a network request.
Custom CSS
The plugin exposes CSS custom properties (variables) so you can adjust the look without hunting through the stylesheet. The most useful ones:
/* Drop this in Appearance → Customize → Additional CSS */
:root {
--os-font-size-base: 16px; /* base font size for all em values inside the schedule */
--os-font-family: "Your Font", sans-serif; /* schedule header font */
--os-radius: 0px; /* make corners square */
--os-tabs-height: 48px; /* height of the tab bar */
--os-transition: 0.15s ease; /* speed up animations */
}
--os-font-size-base is the most important one to know about. Every em-relative size inside the schedule (titles, metadata, badges, icons) computes from this value. The default is 16px, which matches most themes. If your theme uses a larger body font — Twenty Twenty-Five ships with 18px, for example — the schedule will look proportionally smaller than surrounding content. Set this to match your body text and everything re-scales correctly:
/* Match a theme that uses 18px body text */
:root { --os-font-size-base: 18px; }
Colors have their own admin UI, but you can also override them with CSS variables if you need values the settings screen doesn't expose:
:root {
--os-green: #00aa55; /* primary color (tabs active, badges, etc.) */
--os-blue: #1a3a5c; /* secondary color (day headers, modal text) */
--os-gold: #ffcc00; /* favorites star color */
}
Header Flare (the paw print in day headers)
Go to Event Scheduling > Event Settings > Header Flare. You can:
- Turn it off completely with the checkbox.
- Choose a built-in icon from the select menu: paw, dog, cat, crow, horse, dragon, otter, hippo, frog, or fish.
- Use your organization's logo, an SVG, an ice cream cone, or anything else that fits by pasting an image URL into the Image field. When an image URL is set, it takes over from the icon selection.
- Leave the icon field blank to hide the icon while keeping the flare enabled (useful if you only want a custom image or specific CSS effects).
For Theme Developers
Template Overrides
Every template the plugin renders can be overridden by your theme — the same pattern WordPress uses for WooCommerce templates.
To override the full schedule page, create this file in your theme:
your-theme/onlinesched/page-schedule.php
To override a single partial (a smaller piece of the page), create the matching file under onlinesched/partials/ in your theme. For example, to replace the tab bar:
your-theme/onlinesched/partials/schedule-tabs.php
Available partials: schedule-tabs, schedule-filters, schedule-event-row, schedule-calendar-actions, schedule-event-modal, login-modal, info-modal, android-google-calendar-modal.
Copy the original from wp-content/plugins/OnlineSched/templates/partials/ as your starting point.
PHP Hooks Reference
The plugin fires these actions and filters so themes and other plugins can extend behaviour without editing plugin files.
| Hook | Type | When it fires |
|---|---|---|
os_before_schedule |
action | Before the schedule wrapper <div> is output |
os_after_schedule |
action | After the schedule wrapper closes |
os_before_schedule_item |
action | Before each event row, receives $post_id |
os_after_schedule_item |
action | After each event row, receives $post_id |
os_event_description |
filter | Filters the event description HTML, receives ($html, $post_id) |
os_event_badge_html |
filter | Filters the badge HTML for a row, receives ($html, $post_id) |
os_event_popup_extra_html |
filter | Appends event-specific HTML to the popup, receives ($html, $post_id) |
os_hours_heading_extra_html |
filter | Appends sanitized site-owned actions beside an Hours department heading, receives ($html, $department, $location) |
os_render_schedule_args |
filter | Filters the full args array before rendering |
os_sticky_offsets |
filter | Array of sticky pixel offsets for the tab bar; use this if your theme has a sticky header |
os_ical_uid_prefix |
filter | Prefix for generated iCal event UIDs; defaults to os- |
os_ical_timezone |
filter | Calendar metadata timezone; defaults to the site's named WordPress timezone or UTC |
os_ical_calendar_description |
filter | Description used in iCal calendar metadata |
os_kiosk_head_styles |
filter | Array of stylesheet URLs injected into the kiosk page <head> |
onlinesched_load_fontawesome |
filter | Return false to skip loading the plugin's Font Awesome bundle |
onlinesched_load_fonts |
filter | Return false to skip loading the plugin's Metropolis font bundle |
Example — bumping the sticky tab offset for a 60px sticky header:
add_filter( 'os_sticky_offsets', function ( $offsets ) {
$offsets['desktop'] = 60;
$offsets['mobile'] = 60;
return $offsets;
} );
Example — adding content above the schedule:
add_action( 'os_before_schedule', function () {
echo '<p class="schedule-notice">Schedule is subject to change.</p>';
} );
Example - adding site-owned fields to an event popup:
add_filter( 'os_event_popup_extra_html', function ( $html, $post_id ) {
$url = get_post_meta( $post_id, 'venue_map_url', true );
if ( ! $url ) {
return $html;
}
return $html
. '<div class="site-event-links">'
. '<a href="' . esc_url( $url ) . '">View on map</a>'
. '</div>';
}, 10, 2 );
Each callback receives the HTML returned by earlier callbacks, so independent
extensions can append their own fields in filter priority order. OnlineSched
sanitizes the final fragment with wp_kses_post() and places it in the selected
event's popup. The theme or consuming plugin owns the markup, icons, wording,
and CSS; OnlineSched intentionally supplies no presentation for this area.
WP-CLI Schedule Maintenance
OnlineSched can import the same nine-column CSV used by the WordPress admin uploader. The format and meaning of its columns do not change:
ID,Name,Date,Time,Description,Room_Type,Speakers,Length,Tags
Import a file into the active schedule year, or select a year without changing the active onlinesched_year option:
wp onlinesched import /absolute/path/events.csv
wp onlinesched import /absolute/path/events.csv --year=2026
wp onlinesched import /absolute/path/events.csv --year=2026 --dry-run
--dry-run validates the complete file and reports planned inserts, updates, and errors without writing anything. Re-importing a CSV updates matching events in place using the schedule year and CSV ID; events absent from the file are left alone.
You can also permanently delete every OnlineSched event assigned to one explicitly named year:
wp onlinesched delete-year 2026 --dry-run
wp onlinesched delete-year 2026
wp onlinesched delete-year 2026 --yes
Run the dry-run first so you can review the exact count. The delete command requires confirmation unless --yes is supplied. It does not change the active schedule year or delete rooms, speakers, tags, or day terms.
Tested Against
- WordPress: 6.4 through 6.8
- PHP: 8.2, 8.3
- Themes: Furry Migration (Classic), Twenty Twenty-Four, Twenty Twenty-Five (Block)
Development and Testing
Release zips include compiled assets and Composer dependencies, so normal WordPress users can install them directly. Source checkouts need Composer and npm before they are ready to use.
In the Furry Migration Docker environment, run PHP, Composer, and npm inside fm-php:
docker exec fm-php bash -c "cd /var/www/html/wp-content/plugins/OnlineSched && composer install --no-dev"
docker exec fm-php bash -c "source /usr/local/nvm/nvm.sh && cd /var/www/html/wp-content/plugins/OnlineSched && npm install"
docker exec fm-php bash -c "source /usr/local/nvm/nvm.sh && cd /var/www/html/wp-content/plugins/OnlineSched && npm run build"
Contributors can find the complete browser, WP-CLI, fixture, environment, and quick-reference instructions in the OnlineSched test guide.