A MagicMirror² module that shows your upcoming episodes and releases from Seek, the self-hosted TV, film and book tracker.
If you have been using MMM-trakt and have since moved to self-hosted tracking, this is a drop-in replacement. Same layout and column rhythm — your own server instead of Trakt, and no OAuth to reconnect when it eventually expires.
Ted Lasso S04E04 Today
The Great British Sewing Bee S12E07 Today 3:00 PM
Re:ZERO -Starting Life in ... S01E80 Tomorrow
Silo S03E09 Thursday
Below Deck Mediterranean S11E13 Monday 8:00 PM
Ted Lasso S04E05 September 1
- No account, no OAuth. Seek gives each person a private feed URL, so there is no pairing flow, no token refresh, and nothing to reconnect at 2am.
- No dependencies. Uses
fetch(built into Node 18+) and themomentMagicMirror already ships, sonpm installis not part of the setup. - Honest air times. Real air times where Seek has them (from TVmaze); a streaming drop with only a date shows the day alone rather than an invented time. Or hide times entirely with one setting.
- Sensible grouping. When a show drops several episodes at once, they collapse into one row instead of filling the mirror.
- Stays correct overnight. The visible window is recomputed every minute, so "Today" stops meaning yesterday at midnight without waiting for the next fetch.
- Keeps your feed URL server-side. The URL is the credential, so it's only used in the node helper and never reaches the browser — not even in debug logs.
- MagicMirror² running on Node 18 or newer
- A Seek the mirror can reach
cd ~/MagicMirror/modules
git clone https://github.com/nerdspar/MMM-seekThat is the whole installation. There is nothing to npm install.
In Seek, open Settings → Your accounts → Upcoming feed and copy the address. It looks like https://seek.example.com/feed/abc123…/upcoming.json. Each person in the household has their own.
Important
That URL is a credential — anyone holding it can read your schedule (and nothing else). Keep it in config.js and out of anywhere public. The module only ever uses it server-side.
Add to ~/MagicMirror/config/config.js:
{
module: "MMM-seek",
position: "top_left",
header: "TV Schedule",
config: {
feedUrl: "https://seek.example.com/feed/abc123…/upcoming.json",
days: 7,
maxItems: 10
}
}| Option | Type | Default | Description |
|---|---|---|---|
feedUrl |
string |
— | Required. Your Upcoming feed address from Seek's Settings. |
days |
number |
1 |
How far ahead to look. 0 is today only, 1 is today and tomorrow. |
maxItems |
number |
0 |
Maximum rows to draw. 0 means no limit. |
mediaTypes |
string[] |
["tv","movie"] |
"tv" for episodes, "movie" for film releases. |
updateInterval |
number |
3600000 |
How often to refetch, in ms. Release schedules barely move; hourly is plenty. |
initialLoadDelay |
number |
0 |
Delay before the first fetch, in ms. Useful when several modules start at once. |
debug |
boolean |
false |
Logs event counts. Never logs the feed URL — it's your credential. |
styling.moduleSize |
string |
"small" |
xsmall, small, medium, large or xlarge. |
styling.dateFormat |
string |
"MMMM D" |
Used once an event is more than a week out. Format reference. |
styling.timeFormat |
string |
"h:mm A" |
Air time format. Set to "" to hide times entirely. |
styling.collapseSameDay |
boolean |
true |
Collapse several episodes of one show on one day into a single row. |
A quiet, day-only list — no clock times, just what is coming:
config: {
feedUrl: "https://seek.example.com/feed/…/upcoming.json",
days: 30,
maxItems: 10,
styling: { moduleSize: "medium", timeFormat: "" }
}Tonight only, in larger type:
config: {
feedUrl: "https://seek.example.com/feed/…/upcoming.json",
days: 0,
styling: { moduleSize: "large" }
}A 24-hour clock:
styling: { timeFormat: "HH:mm" }Replace serverUrl and calendarToken with feedUrl. Until you do, the module says so on the mirror.
Seek takes air times from TVmaze where it has them. Streaming drops usually have a date but no time; those rows show the day alone. Set timeFormat: "" if you would rather no row showed one.
| What you see | What it means |
|---|---|
Seek feed returned 404 |
feedUrl is wrong — copy it again from Seek's Settings. |
Set feedUrl in config.js |
The required option is missing or empty. |
MMM-seek now reads Seek… |
An old config: replace serverUrl and calendarToken with feedUrl. |
fetch failed |
The mirror cannot reach the server. Check the URL and port, and that the mirror is on a network that can see it. |
Nothing airing |
The feed loaded but holds no events inside your window. Try a larger days. |
| Nothing at all, and no error | The module is still loading. If it persists, set debug: true and check the MagicMirror log. |
If Seek is on the same network as the mirror, use its local address in feedUrl (e.g. http://192.168.1.10:8100/feed/…/upcoming.json). There is no reason for an hourly poll to travel out to a reverse proxy and back.
npm install # only needed for the tests
npm test # feed and render logicnpm run preview runs the module's real getDom() against a saved feed and prints the resulting table as text. It is far quicker than restarting the mirror to see what a config change does:
curl -s "$FEED_URL" -o /tmp/seek-feed.json
npm run preview -- /tmp/seek-feed.json 30 10 # feed, days, maxItems
npm run preview -- /tmp/seek-feed.json 30 10 "" # …and hide air timesIssues and pull requests are welcome. Please run npm test before opening a PR, and add a test for anything that changes how the feed is read or how rows are chosen.