πΊοΈ M365 Roadmap Tracker¶
Live at: aguidetocloud.com/m365-roadmap/ Repo:
susanthgit/m365-roadmapBuilt: April 10, 2026 Cost: $0/month (GitHub Actions Free + Azure SWA Free + Azure OpenAI ~$0.01/day)
What It Does¶
An automated tracker that pulls all ~1,900 items from Microsoft's official M365 roadmap API, detects changes daily, generates AI summaries, and displays everything in an "Amber Command" dark dashboard β complete with delay detection, favourites, RSS feed, and CSV export.
Think of it like having a personal radar that watches the Microsoft 365 roadmap for you and highlights what changed overnight.
Architecture Overview¶
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GitHub Actions (daily at 5:00 UTC) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββββ ββββββββββββββββ βββββββββββββββββ β
β βfetch_roadmap.pyβββΆβ summarise.py βββΆβgenerate_data β β
β β API + changes β β GPT-4o mini β β .py β β
β ββββββββββββββββββ ββββββββββββββββ βββββββββββββββββ β
β β β β β
β items.json summaries.json latest.json β
β previous_state.json cache.json weekly/monthly β
β changelog.json feed.xml β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Clone main site repo β copy data β hugo build β deploy β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β aguidetocloud.com/m365-roadmap/ β
β β
β βββββββββββββ ββββββββββββββ ββββββββββββββββββββββββ β
β βroadmap.js β βroadmap.css β βm365-roadmap/list.htmlβ β
β β ~260 loc β β ~165 loc β βHugo template β β
β βββββββββββββ ββββββββββββββ ββββββββββββββββββββββββ β
β β
β "Amber Command" palette: #E5A00D gold on #141118 dark β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data Source¶
Microsoft Roadmap API β free, no auth required:
Returns all ~1,900 roadmap items as JSON. Updated by Microsoft daily. The pipeline makes a single GET request with a custom User-Agent: M365RoadmapTracker/1.0 (aguidetocloud.com).
Pipeline Scripts¶
1. fetch_roadmap.py¶
| Feature | Detail |
|---|---|
| API call | Single GET to Microsoft roadmap API (timeout: 30s) |
| Change detection | Compares each item against site/previous_state.json |
| Change types | new, status_changed, date_changed, updated |
| Content hash | md5(title + description + status + GA dates) for meaningful change detection |
| Delay flagging | If GA date < current month AND status β Launched/Cancelled β is_delayed = true |
| Changelog | Accumulates changes into site/changelog.json with timestamps |
| First run | Suppresses all change flags (treats everything as baseline) |
| Output | site/items.json, site/previous_state.json, site/changelog.json |
2. summarise.py¶
| Feature | Detail |
|---|---|
| Model | Azure OpenAI gpt-4o-mini |
| Endpoint | ainews-openai.openai.azure.com (shared with AI News) |
| Auth | OIDC β Azure AD token (same service principal as AI News) |
| Cache key | item.id + md5(description)[:12] β only re-summarises when content changes |
| Cache file | site/summaries_cache.json |
| Batch size | 10 items per API call |
| Temperature | 0.2 |
| Max tokens | 200 Γ batch size |
| Fallback | Single-item mode if batch parse fails; cache-only mode if no token |
3. generate_data.py¶
| Feature | Detail |
|---|---|
| Daily archive | site/data/YYYY-MM-DD.json (raw item snapshots) |
| Index files | site/latest.json, site/weekly.json, site/monthly.json |
| RSS feed | site/feed.xml (100 items max, changed first then active) |
| latest.json shape | generated_at, total_items, active_items, summarised, changes_summary, product_categories, status_counts, items |
GitHub Actions Workflow¶
File: .github/workflows/daily-roadmap.yml (~98 lines)
Schedule: Daily at 5:00 UTC
Triggers: cron + manual dispatch
Steps:
1. Checkout repo
2. Setup Python 3.12
3. Install requirements
4. Run fetch_roadmap.py
5. Azure OIDC login (azure/login@v2)
6. Get Azure OpenAI token
7. Run summarise.py
8. Run generate_data.py
9. Commit site/ back to pipeline repo
10. Clone main site repo β copy data β hugo build β swa deploy
11. On failure β create GitHub Issue
Shared OIDC Service Principal¶
Uses the same ainews service principal as AI News:
- Client ID:
51b70f10-db98-4c14-84ef-2ca661e51b6d - Federated credential:
m365-roadmap-github-actions-oidc - Scoped to: Azure OpenAI resource (
ainews-openai)
Frontend Implementation¶
Hugo Templates¶
| Template | Purpose |
|---|---|
layouts/m365-roadmap/list.html |
Main page β search, status/product filters, RSS/CSV links |
layouts/m365-roadmap-category/list.html |
Category SEO pages β pre-filtered by roadmap_filter, CollectionPage JSON-LD |
JavaScript β roadmap.js (~260 lines)¶
| Feature | How it works |
|---|---|
| Data source | Fetches /data/roadmap/latest.json |
| sessionStorage cache | Key: rdmap_v7, caches full JSON if < 2MB, 30-min freshness |
| Product filter | Dropdown populated from product_categories in JSON |
| Category chips | Horizontal bar with per-category item counts |
| Status filter | Dropdown β "In Progress" excludes Launched + Cancelled |
| Search | Matches title + AI summary + products |
| AI summaries | Rendered inline in each row if present |
| Pagination | PAGE_SIZE = 50, "Load more (N remaining)" button |
| Favourites | localStorage key rdmap_favourites β star toggle per item |
| CSV export | Client-side generation: ID,Title,Status,Product,GA Date,Delayed,Summary,URL |
| URL state | Reads/writes ?product=, ?status=, ?q= for shareable views |
| Category pages | Respects window.__roadmapCategoryFilter for pre-filtering |
| Keyboard | / focuses search box |
CSS β roadmap.css (~165 lines)¶
| Element | Detail |
|---|---|
| Accent colour | Gold #E5A00D |
| Background | #1a1510 β #141118 gradient |
| Cards | #1C1924 bg, #2A2533 borders |
| Text | #E8E4ED primary, #8B8594 muted |
| Chips | Horizontal scroll on overflow |
| Mobile | @media (max-width: 768px) β stacked controls, 1-column rows |
| CSS namespace | .rdmap-* classes throughout |
SEO Category Landing Pages¶
11 pages under content/m365-roadmap/:
| Page | Product Filter |
|---|---|
/m365-roadmap/copilot/ |
Copilot |
/m365-roadmap/teams/ |
Teams |
/m365-roadmap/outlook/ |
Outlook |
/m365-roadmap/sharepoint/ |
SharePoint |
/m365-roadmap/office-apps/ |
Office Apps |
/m365-roadmap/purview/ |
Purview |
/m365-roadmap/intune/ |
Intune |
/m365-roadmap/viva/ |
Viva |
/m365-roadmap/entra/ |
Entra |
/m365-roadmap/admin/ |
Admin |
/m365-roadmap/edge-media/ |
Edge & Media |
Each uses type: "m365-roadmap-category" + roadmap_filter param in front matter.
Key Design Decisions¶
| Decision | Rationale |
|---|---|
| "Amber Command" palette | Military radar aesthetic β gold on charcoal conveys authority + monitoring |
| Same OIDC as AI News | One service principal for both pipelines β simpler governance |
| Hash-based summary cache | Only re-summarise items whose content actually changed β saves API costs |
| Delay flagging | Automatically highlights items past their GA date β useful for customer conversations |
| Change detection | Customers want to know "what changed since yesterday" β changelog answers this |
| sessionStorage v7 | Bump CACHE_VERSION when changing JSON schema to invalidate stale cached data |
Maintenance¶
| Task | How |
|---|---|
| Force a refresh | Trigger daily-roadmap.yml manually via GitHub Actions |
| Bump cache version | Edit CACHE_VERSION in roadmap.js when JSON schema changes |
| Add a category page | Create content/m365-roadmap/<slug>/_index.md with type: "m365-roadmap-category" |
| Check for failures | Look at GitHub Issues in m365-roadmap repo (auto-created on failure) |
| Update OIDC | Same service principal as AI News β Federated credentials in Entra ID |
| Cache headers | staticwebapp.config.json sets /data/roadmap/* to max-age=1800 (30 min) |
Last updated: 11 April 2026