A MagicMirror² module that displays upcoming fixtures for any football team. It uses TheSportsDB API as the primary data source and can complement missing data with a reputable scraper (FootballWebPages) to ensure away fixtures always appear. User can choose which fixtures to display from "All", "Domestic","European". "Home" and "Away" fixtures and auto cycle through the chosen lists if desired.
- Works with any team: Scottish, English, European, or any team in TheSportsDB
- Primary API: TheSportsDB (v3)
- Optional supplement: FootballWebPages (FWP) when API lacks away fixtures (n.b free API only returns home fixtures)
- Features: Auto season detection, caching, H/A indicator, optional competition name, optional countdown, client-side filters, source footer
Examples shown for Celtic / Liverpool / Bayern Munich & Roma configurations
- Features
- Screenshots
- Installation
- Configuration
- Options (config table)
- How data fetching works
- Minimum config example
- Dependencies
- To Do
- License
- Universal Team Support: Works with any team from TheSportsDB (Scottish, English, European, etc.)
- Shows date, time, opponent, H/A, competition
- Live countdown (optional)
- Client-side filters: All, Domestic, European, Home, Away
- Auto-detect season (e.g., 2025-2026)
- Caching to avoid rate limits
- Clear footer with source and timestamp
- Dynamic title displays your configured team name
-
Navigate to your MagicMirror modules folder:
cd ~/MagicMirror/modules
-
Clone or copy this module into
MMM-MyTeams-Fixtures:git clone https://github.com/gitgitaway/MMM-MyTeams-Fixtures
-
Install dependencies
npm install-
Add the config to ~/MagicMirror/config/config.js`
-
Restart MagicMirror.
Simply change teamName and teamId to configure for your team:
{
module: "MMM-MyTeams-Fixtures",
position: "bottom_right",
config: {
teamName: "Manchester United", // Change to your team
teamId: "133612", // Find your team ID at thesportsdb.com
leagueIds: ["4328", "4480"], // Premier League + Champions League
// ... other options below
}
}{
module: "MMM-MyTeams-Fixtures",
position: "bottom_right",
config: {
source: "api",
teamName: "Celtic",
teamId: "133647",
apiUrl: "https://www.thesportsdb.com/api/v1/json/3",
season: "auto",
fallbackSeason: "2025-2026",
updateInterval: 10 * 60 * 1000,
requestTimeoutMs: 15000,
maxFixtures: 12,
showCompetition: true,
showCountdown: true,
defaultFilter: "all",
cacheTTL: 5 * 60 * 1000,
fallbackChain: true,
// Filtering helpers - customize for your team's leagues
leagueIds: ["4330", "4364", "4363", "4888"], // Scottish leagues
uefaLeagueIds: ["4480", "4481", "5071"],
// API fallback behavior
useSearchEventsFallback: true,
strictLeagueFiltering: true,
// Scrapers (used only as needed)
scrapeFWP: true,
scrapeBBC: false,
scrapeLFOTV: false,
scrapeCFC: false,
scrapeSportsDB: false,
// Locale
locale: "en-GB",
// Debug
debug: false,
// Theme overrides
darkMode: null, // null=auto, true=force dark, false=force light
fontColorOverride: null, // e.g., "#FFFFFF" to force white text
opacityOverride: null // e.g., 1.0 to force full opacity
}
}See test-team-config.js for ready-to-use configurations for:
- Scottish: Celtic, Rangers, Aberdeen, Hearts
- English: Manchester United, Liverpool, Arsenal
- European: Barcelona, Bayern Munich
Finding Team IDs: Visit TheSportsDB.com, search for your team, and the ID is in the URL (e.g., /team/133647-Celtic)
| Option | Type | Default | Description |
|---|---|---|---|
| source | string | "api" | Primary source: "api" or scrapers via fallbackChain |
| teamName | string | "Celtic" | Your team's display name (e.g., "Manchester United", "Barcelona") |
| teamId | string | "133647" | TheSportsDB team ID - find at thesportsdb.com |
| apiUrl | string | https://www.thesportsdb.com/api/v1/json/3 | API base URL |
| season | string | "auto" | Season string (e.g., "2025-2026") or "auto" |
| fallbackSeason | string | "2025-2026" | Secondary season for API fallback |
| updateInterval | number | 600000 | Refresh interval in ms |
| requestTimeoutMs | number | 15000 | Fetch timeout in ms |
| maxFixtures | number | 10 | Max fixtures shown |
| showCompetition | boolean | true | Show competition column |
| showCountdown | boolean | true | Show countdown to each match |
| defaultFilter | string | "all" | "all" | "domestic" | "european" | "home" | "away" |
| cacheTTL | number | 300000 | Cache duration in ms |
| fallbackChain | boolean | true | Try scrapers if API empty |
| leagueIds | string[] | [4330,4364,4363,4888] | Your team's domestic league IDs (defaults to Scottish) |
| uefaLeagueIds | string[] | [4480,4481,5071] | UEFA competition IDs (Champions/Europa/Conference League) |
| useSearchEventsFallback | boolean | true | Try searchevents patterns if API returns no data |
| strictLeagueFiltering | boolean | true | Enforce league IDs for filtering in API stage |
| scrapeFWP | boolean | true | Enable FWP scraper (for supplement/fallback) |
| scrapeBBC | boolean | true | Enable BBC scraper (fallback) |
| scrapeLFOTV | boolean | true | Enable LiveFootballOnTV scraper (fallback) |
| scrapeCFC | boolean | true | Enable team-specific site scraper (fallback) |
| scrapeSportsDB | boolean | true | Enable TheSportsDB site scraper (fallback) |
| autoCycleFilters | boolean | false | Automatically rotate through enabled filters |
| autoCycleIntervalMs | number | 20000 | Time to display each filter when auto-cycling (ms) |
| cycleAll | boolean | true | Include "All" filter in auto-cycle rotation |
| cycleHome | boolean | true | Include "Home" filter in auto-cycle rotation |
| cycleAway | boolean | true | Include "Away" filter in auto-cycle rotation |
| cycleDomestic | boolean | false | Include "Domestic" filter in auto-cycle rotation |
| cycleEuropean | boolean | false | Include "European" filter in auto-cycle rotation |
| locale | string | "en-GB" | Date/time formatting locale |
| debug | boolean | false | Verbose logging |
- The module asks the helper for fixtures. The helper first calls TheSportsDB: eventsnext (upcoming) and eventsseason (season list). It filters to your configured team's matches and specified leagues.
- If TheSportsDB returns only home games (common with free tier), the helper will check FootballWebPages for away games and merge them in (with date inference so they sort correctly). You’ll see "Source: api+fwp" in the footer when this happens.
- If everything is empty (rare), optional scrapers (BBC, LiveFootballOnTV, team site, SportsDB site) can be tried in order if enabled.
- The front-end sorts and displays the merged list, and you can filter it with the buttons.
Note: The module dynamically generates scraper URLs based on your teamName configuration, so it works for any team without hardcoded references.
The module can automatically rotate through different fixture views at a configurable interval. This is useful for displaying different perspectives of your team's schedule without manual interaction.
config: {
autoCycleFilters: true, // Enable auto-cycling
autoCycleIntervalMs: 20000, // Show each filter for 20 seconds
// Choose which filters to include in the rotation
cycleAll: true, // Include "All fixtures" view
cycleHome: true, // Include "Home fixtures" view
cycleAway: true, // Include "Away fixtures" view
cycleDomestic: false, // Include "Domestic fixtures" view
cycleEuropean: false, // Include "European fixtures" view
}- When
autoCycleFiltersistrue, the module will automatically switch between enabled filters - Only filters set to
truewill be included in the rotation - The cycle starts with your
defaultFilterif it's enabled, otherwise starts with the first enabled filter - Default configuration cycles through: All → Home → Away (backward compatible with previous behavior)
- You can customize to cycle through any combination of filters
Cycle only Home and Away (previous default behavior):
autoCycleFilters: true,
cycleAll: false,
cycleHome: true,
cycleAway: true,
cycleDomestic: false,
cycleEuropean: falseCycle through all filter types:
autoCycleFilters: true,
cycleAll: true,
cycleHome: true,
cycleAway: true,
cycleDomestic: true,
cycleEuropean: trueCycle only Domestic and European (for teams in multiple competitions):
autoCycleFilters: true,
cycleAll: false,
cycleHome: false,
cycleAway: false,
cycleDomestic: true,
cycleEuropean: true- MagicMirror² (runtime)
- Node.js 18+
- npm packages: cheerio, node-fetch (or global fetch in Node 18), fs (built-in)
- Removed all hardcoded Celtic references - module now works for any team
- Fixed critical bugs:
- Undefined
scottishLeagueIdsvariable (now usesleagueIdsparameter) - Legacy SOURCES object with hardcoded Celtic URLs removed
- Undefined
- Dynamic URL generation for all scrapers based on
teamName - Generic team ID resolution without team-specific scoring
- Enhanced league detection - now supports Scottish, English, and other domestic leagues
- Parameterized HTML parsers - all scrapers accept team name dynamically
- Dynamic UI title - displays your configured team name
See FIXES_APPLIED.md for complete technical details of all changes.
- Supplement API data with FWP to include away fixtures
- Add robust debug logging and cache metadata
- Remove hardcoded Celtic references - make module work for any team
- Fix undefined variable bugs and legacy code issues
- Add logo mapping for more clubs and competitions
- Add per-league toggle to hide specific competitions
This is the 3rd module in my Celtic themed man cave magicmirror, but now works for any team!
The other modules can be found here:-
- Module 1: MyTeams-Clock https://github.com/gitgitaway/MMM-MyTeams-Clock
- Module 2: MyTeams-Clock https://github.com/gitgitaway/MMM-MyTeams-LeagueTable
- Module 4: MyTeams-Clock https://github.com/gitgitaway/MMM-JukeBox
Thanks to the MagicMirror community for inspiration and guidance! Special thanks to @jclarke0000 for his work on MMM-MyScoreboard which served as a starting point.
MIT




