Skip to content

Commit 526a0fc

Browse files
author
Jukka Niiranen
committed
Roadmap planning
1 parent 3776e5b commit 526a0fc

23 files changed

Lines changed: 731 additions & 0 deletions

ROADMAP.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# offi.ceo Roadmap
2+
3+
**Goal**: Evolve from a waffle-menu replacement into the best possible Microsoft 365 home page — one that shows users what *they* care about, not what Microsoft wants to promote.
4+
5+
**Current version**: 1.2.0 — configurable app launcher, no auth, localStorage only
6+
7+
---
8+
9+
## The vision
10+
11+
A personal M365 dashboard that loads in seconds, shows your actual work context (recent files, next meeting, unread messages), and gets out of the way. No Copilot push. No upsells. No dark patterns. Built around the principle that the user decides what a homepage is for.
12+
13+
Technically: still a static app hosted on GitHub Pages. Microsoft Graph API runs entirely in the browser via MSAL.js — no server, no backend, no stored credentials. Tokens live in sessionStorage only.
14+
15+
---
16+
17+
## Phase 1 — Better launcher (no auth required)
18+
*Incremental improvements on top of v1.2.0. Ship quickly to justify domain renewal.*
19+
20+
### 1.1 Quick-create deep links
21+
Replace pure launch URLs with action-oriented shortcuts where possible:
22+
- New Word document → `https://word.new`
23+
- New Excel sheet → `https://excel.new`
24+
- New PowerPoint → `https://powerpoint.new`
25+
- New Teams meeting → deep link to calendar compose
26+
- Each tile gets an optional secondary "New" badge/button alongside the launch link
27+
28+
### 1.2 Keyboard navigation
29+
- Single-key shortcuts when no input is focused: `O` = Outlook, `T` = Teams, `W` = Word, `E` = Excel, `P` = PowerPoint, `D` = OneDrive, etc.
30+
- `?` opens shortcut cheat-sheet overlay
31+
- Makes the page genuinely faster than clicking the waffle
32+
33+
### 1.3 IT Admin portals section
34+
An optional second tile section for IT pros, hidden by default, toggled on from settings:
35+
- Microsoft 365 Admin Center, Entra ID, Purview, Security & Compliance, Power Platform Admin Center (PPAC), Azure Portal, Intune, Exchange Admin, Teams Admin
36+
37+
### 1.4 Power Platform section
38+
A dedicated tile section for Power Platform makers and admins — one of the most underserved groups when it comes to navigation:
39+
- Quick links to the main makers: Power Apps (`make.powerapps.com`), Power Automate (`make.powerautomate.com`), Power Pages (`make.powerpages.microsoft.com`), Copilot Studio (`copilotstudio.microsoft.com`)
40+
- **Environment switcher**: users can save their named environments (display name + environment URL) in localStorage; selecting one updates all environment-scoped links to that environment's base URL
41+
- Direct editor launch links per environment: canvas app editor, model-driven app list, Dataverse table editor, solution list
42+
- This section is hidden by default, enabled via a toggle for users who identify as makers/admins
43+
44+
---
45+
46+
## Phase 2 — Graph API integration (the real homepage)
47+
*This is the strategic moat. Everything from here requires Microsoft sign-in.*
48+
49+
**Technical approach**: MSAL.js (`@azure/msal-browser`) registered as a public client app in Azure AD. Scopes requested on demand (not upfront). All Graph calls run from the browser. No backend, no server, GitHub Pages hosting unchanged.
50+
51+
**Privacy stance**: Nothing leaves the browser. Tokens in sessionStorage, cleared on tab close. No analytics on personal data. This must be stated clearly on the page.
52+
53+
### 2.1 Sign-in and identity
54+
- "Sign in with Microsoft" button — optional, launcher works without it
55+
- On sign-in: show user's name, avatar, tenant name in header
56+
- Graceful fallback: unsigned state = today's v1 launcher experience
57+
- Token refresh handled silently; logout clears all local state
58+
59+
### 2.2 Recent files widget
60+
- Graph: `GET /me/drive/recent` — show last 8–10 files with icon, name, modified time, direct open link
61+
- Filter: Office file types only (Word, Excel, PowerPoint, OneNote) — ignore `.zip`, images, etc.
62+
- One-click open in browser (online editors), optional "open in desktop app" link
63+
- This is the single feature that makes people return daily
64+
65+
### 2.3 Next meeting widget
66+
- Graph: `GET /me/calendarView` — show next 1–3 upcoming events
67+
- Display: title, time, organizer, join link if Teams meeting
68+
- "Join" button for active/imminent meetings — the most useful thing to have on a homepage
69+
- Within 15 min of start: highlight the meeting card
70+
71+
### 2.4 Unread email count
72+
- Graph: `GET /me/mailFolders/inbox` — show unread count only, no email content
73+
- Clicking navigates to Outlook Web
74+
- Intentionally minimal — this is a count, not an inbox preview. Keep the homepage fast and focused.
75+
76+
### 2.5 Pinned SharePoint / Teams sites
77+
- Graph: `GET /me/followedSites` and `GET /me/joinedTeams`
78+
- Show followed sites and Teams as a separate tile section
79+
- User can pin/unpin from the list (stored in localStorage alongside custom tiles)
80+
81+
### 2.6 Power Platform: environment and app discovery (research required)
82+
The goal is to reconstruct a useful "my apps" view for Power Platform — the one that disappeared from the M365 portal and never worked well anyway.
83+
84+
**What to investigate:**
85+
- **Power Apps API** (`api.powerapps.com`) is separate from Microsoft Graph. It exposes environments, canvas apps, and model-driven apps but is undocumented/unofficial in places and has historically been the backend for `make.powerapps.com` itself
86+
- **Graph `GET /me/appCatalogs`** and related endpoints — unlikely to surface Power Apps but worth confirming
87+
- **`/providers/Microsoft.PowerApps/apps`** via Azure Resource Manager — may require `Azure Service Management` scope, which is heavy
88+
- **What's realistically retrievable**: environments list (`GET /providers/Microsoft.PowerApps/environments`), canvas apps per environment, model-driven apps less clear
89+
- **Scope implications**: Power Apps API uses `https://service.powerapps.com/.default` — a different resource from Graph, requiring a second token request; feasible with MSAL but needs to be declared upfront in the app registration
90+
91+
**Target outcome if feasible**: show the user's environments as cards, each expandable to list their apps with direct play/edit links — replacing the fragmented "my apps" experience across make.powerapps.com, the M365 waffle, and the old office.com apps list.
92+
93+
---
94+
95+
## Phase 3 — Personalization and sharing
96+
*Making offi.ceo something people share with colleagues and set as their homepage.*
97+
98+
### 3.1 Dashboard layout control
99+
- Drag-and-drop section ordering: widgets (recent files, calendar, email) vs. tile grid
100+
- Collapsible widget sections
101+
- Compact vs. comfortable tile density toggle
102+
- All layout prefs in localStorage
103+
104+
### 3.2 Org-wide shareable configs (no server needed)
105+
- Generate a URL-encoded config string: `offi.ceo/?config=<base64>`
106+
- IT admins can distribute a pre-configured launcher to their team via a single link
107+
- On arrival, user is prompted to import the org config or keep their own
108+
- No server required — config lives entirely in the URL
109+
110+
### 3.3 PWA refinement
111+
- Current PWA install already works; add proper offline fallback screen
112+
- Home screen icon, splash screen, standalone display mode
113+
- Encourage "Add to home screen" / "Install app" for desktop and mobile
114+
- Push notification opt-in for meeting reminders (Web Push API)
115+
116+
---
117+
118+
## Technical decisions
119+
120+
| Decision | Choice | Reason |
121+
|----------|--------|--------|
122+
| Auth library | `@azure/msal-browser` | Official, maintained, no server needed |
123+
| Graph calls | Fetch via `@microsoft/microsoft-graph-client` | Clean typed interface |
124+
| Token storage | SessionStorage (MSAL default) | Privacy — cleared on tab close |
125+
| Hosting | GitHub Pages (unchanged) | Free, zero infra |
126+
| Azure AD app reg | Single-tenant → multi-tenant | Start single, flip when stable |
127+
| Scopes | Incremental — request per feature | Minimizes permission surface shown to user |
128+
129+
### Azure AD app registration (Phase 2 prerequisite)
130+
- Register at portal.azure.com as a Single-page Application (SPA)
131+
- Redirect URI: `https://offi.ceo` (and `http://localhost:5173` for dev)
132+
- Scopes needed: `User.Read`, `Files.Read`, `Calendars.Read`, `Mail.Read` (read-only throughout)
133+
- No client secret — public client only
134+
135+
---
136+
137+
## What this is not
138+
- Not a Microsoft product or affiliated with Microsoft
139+
- Not storing user data anywhere
140+
- Not a Copilot competitor — Copilot can stay in Teams/M365 where users choose it
141+
- Not trying to replace SharePoint intranets or Viva Connections — this is the personal layer
142+
143+
---
144+
145+
## Success metrics
146+
- People install it as their browser homepage / new tab
147+
- IT admins share org configs with their teams
148+
- Newsletter subscribers discover it and connect the author to the tool
149+
- Gets covered in Power Platform / M365 community media as the "anti-Copilot-homepage"
150+
151+
---
152+
153+
*Last updated: 2026-06-09*
154+
*Maintained by: Jukka Niiranen — [perspectives.plus](https://perspectives.plus)*

docs/architecture.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Source architecture
2+
3+
## Directory map
4+
5+
```
6+
src/
7+
├── pages/ # Route-level components only
8+
│ ├── Index.tsx # Main dashboard page
9+
│ └── NotFound.tsx
10+
11+
├── components/
12+
│ ├── ui/ # shadcn primitives — do not edit directly
13+
│ ├── tiles/ # Tile grid, tile card, tile edit form
14+
│ ├── sections/ # Named collapsible sections: AdminSection, PowerPlatformSection
15+
│ └── widgets/ # Graph API data widgets: RecentFiles, NextMeeting, EmailCount, SitesList
16+
17+
├── data/ # Static data and config — no logic
18+
│ ├── tilesDefault.ts # Default M365 app tiles (moved from pages/)
19+
│ ├── tilesAdmin.ts # IT admin portal links
20+
│ └── tilesPowerPlatform.ts # Power Platform maker/admin links
21+
22+
├── auth/ # MSAL authentication (Phase 2)
23+
│ ├── msalConfig.ts # PublicClientApplication config
24+
│ ├── AuthProvider.tsx # Context provider wrapping the app
25+
│ └── useAuth.ts # Hook: { account, signIn, signOut, getToken }
26+
27+
├── graph/ # Microsoft Graph API calls (Phase 2)
28+
│ ├── graphClient.ts # Authenticated fetch wrapper
29+
│ ├── useRecentFiles.ts # Hook: recent OneDrive/SPO files
30+
│ ├── useNextMeeting.ts # Hook: upcoming calendar events
31+
│ ├── useEmailCount.ts # Hook: unread inbox count
32+
│ └── useFollowedSites.ts # Hook: followed SharePoint sites + joined Teams
33+
34+
├── powerplatform/ # Power Platform API calls (Phase 2, pending research)
35+
│ ├── ppClient.ts # Authenticated fetch wrapper (service.powerapps.com)
36+
│ ├── useEnvironments.ts # Hook: list of PP environments
37+
│ └── useApps.ts # Hook: canvas + model-driven apps per environment
38+
39+
├── hooks/ # General-purpose hooks
40+
│ ├── use-mobile.tsx # Existing
41+
│ ├── use-toast.ts # Existing
42+
│ └── useLocalStorage.ts # Typed localStorage get/set with JSON parse
43+
44+
└── lib/
45+
└── utils.ts # Existing shadcn utility
46+
```
47+
48+
## Key conventions
49+
50+
- **Graph hooks** return `{ data, isLoading, error }` — same shape as TanStack Query (use it underneath)
51+
- **Sections** are self-contained: own their toggle state, read from localStorage for enabled/collapsed
52+
- **Widgets** gracefully degrade: if not signed in, they render nothing or a "sign in to see X" prompt
53+
- **data/** files are pure config — arrays and constants only, no React, no imports from other src folders
54+
- **auth/** is the only place that touches MSAL — nothing else imports from `@azure/msal-browser` directly
55+
56+
## Current code that needs moving (when touching those files)
57+
58+
| File now | Should be |
59+
|----------|-----------|
60+
| `src/pages/OfficeLauncherControls.tsx` | `src/components/OfficeLauncherControls.tsx` |
61+
| `src/pages/OfficeLauncherStyles.tsx` | `src/components/OfficeLauncherStyles.tsx` |
62+
| `src/pages/tilesDefault.ts` | `src/data/tilesDefault.ts` |
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# 1.1 Quick-create deep links
2+
3+
## Goal
4+
Tiles for document apps show a secondary "New" action alongside the existing launch link, so users can jump straight to a blank document without navigating inside the app.
5+
6+
## Accepted `.new` shortcuts (verified)
7+
| App | Launch URL | Quick-create URL |
8+
|-----|-----------|-----------------|
9+
| Word | `https://office.com/launch/word` | `https://word.new` |
10+
| Excel | `https://office.com/launch/excel` | `https://excel.new` |
11+
| PowerPoint | `https://office.com/launch/powerpoint` | `https://powerpoint.new` |
12+
| OneNote | `https://onenote.com` | `https://onenote.new` |
13+
| Forms | `https://forms.office.com` | no equivalent |
14+
| Teams | `https://teams.microsoft.com` | deep link to calendar compose (see below) |
15+
16+
Teams new meeting deep link: `https://teams.microsoft.com/l/meeting/new`
17+
18+
## UI pattern
19+
- Tile card gets a small "+" button in the top-right corner, visible on hover (desktop) or always visible (mobile)
20+
- Clicking "+" opens the quick-create URL; clicking the tile body still opens the app normally
21+
- Only tiles that have a `createUrl` in their data show the button — no UI change for tiles without one
22+
23+
## Data change
24+
Add optional `createUrl` field to `AppTile` interface in `src/data/tilesDefault.ts`:
25+
```ts
26+
export interface AppTile {
27+
name: string;
28+
icon: string;
29+
url: string;
30+
createUrl?: string; // new
31+
isEditing?: boolean;
32+
}
33+
```
34+
35+
## Open questions
36+
- Should custom tiles support `createUrl` in the edit form? (Probably yes — add the field as optional input)
37+
- Verify `.new` redirects still work as of build date — Google owns the `.new` TLD and grants these to partners; they have been stable but worth confirming
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# 1.2 Keyboard navigation
2+
3+
## Goal
4+
Single-key shortcuts to launch apps when no input element is focused. Makes the page faster than mouse navigation for power users.
5+
6+
## Default key map
7+
| Key | Action |
8+
|-----|--------|
9+
| `O` | Outlook |
10+
| `T` | Teams |
11+
| `W` | Word |
12+
| `E` | Excel |
13+
| `P` | PowerPoint |
14+
| `D` | OneDrive |
15+
| `N` | OneNote |
16+
| `B` | Power BI |
17+
| `A` | Power Apps |
18+
| `F` | Power Automate (Flow) |
19+
| `?` | Open shortcut cheat-sheet overlay |
20+
| `Esc` | Close overlay / cancel edit mode |
21+
22+
## Implementation notes
23+
- Listen for `keydown` on `document`; skip if `event.target` is an input, textarea, or has `contenteditable`
24+
- Keys are case-insensitive (`w` and `W` both work)
25+
- Shortcut triggers `window.open(url, '_blank', 'noopener,noreferrer')` — same behaviour as tile click
26+
- `AppTile` gets an optional `shortcut` field in the data; the key map is derived from tile data, not hardcoded
27+
- Hook: `useKeyboardShortcuts(tiles)` in `src/hooks/` — registers and cleans up the listener
28+
29+
## Overlay
30+
- Modal or slide-up panel listing all active shortcuts in a two-column grid
31+
- Triggered by `?` key or a small `?` icon in the controls bar
32+
- Should not show shortcuts for tiles the user has deleted
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# 1.3 IT Admin portals section
2+
3+
## Goal
4+
A second tile section for IT administrators and power users, hidden by default. Contains direct links to admin portals that are otherwise scattered and hard to find.
5+
6+
## Links to include
7+
| Name | URL |
8+
|------|-----|
9+
| M365 Admin Center | `https://admin.microsoft.com` |
10+
| Entra ID | `https://entra.microsoft.com` |
11+
| Exchange Admin | `https://admin.exchange.microsoft.com` |
12+
| Teams Admin | `https://admin.teams.microsoft.com` |
13+
| Intune | `https://intune.microsoft.com` |
14+
| Purview | `https://purview.microsoft.com` |
15+
| Security & Compliance | `https://security.microsoft.com` |
16+
| Defender | `https://security.microsoft.com` (same portal, tab) |
17+
| Azure Portal | `https://portal.azure.com` |
18+
| Power Platform Admin Center | `https://admin.powerplatform.microsoft.com` |
19+
20+
## UI pattern
21+
- Section sits below the main tile grid, collapsed by default
22+
- Section header: "Admin portals" with a toggle arrow and a lock/shield icon
23+
- Enabled state (shown/hidden) persisted in localStorage under key `section_admin_enabled`
24+
- Collapsed state persisted separately under `section_admin_collapsed`
25+
- Tiles in this section are not editable in the same way as main tiles — static list (v1), user-editable later
26+
27+
## Component
28+
`src/components/sections/AdminSection.tsx` — self-contained, reads its own localStorage keys
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# 1.4 Power Platform section
2+
3+
## Goal
4+
A dedicated section for Power Platform makers and admins. Solving the real pain: jumping to the right environment's editor, solution list, or Dataverse tables without going through the make.powerapps.com navigation every time.
5+
6+
## Static quick-launch links (always shown)
7+
| Name | URL |
8+
|------|-----|
9+
| Power Apps maker | `https://make.powerapps.com` |
10+
| Power Automate maker | `https://make.powerautomate.com` |
11+
| Power Pages | `https://make.powerpages.microsoft.com` |
12+
| Copilot Studio | `https://copilotstudio.microsoft.com` |
13+
| Power BI | `https://app.powerbi.com` |
14+
| Power Platform Admin Center | `https://admin.powerplatform.microsoft.com` |
15+
16+
## Environment switcher
17+
The key feature. Users save named environments; selecting one updates all environment-scoped deep links.
18+
19+
### Data model (localStorage key: `pp_environments`)
20+
```ts
21+
interface PPEnvironment {
22+
id: string; // user-assigned, slug-friendly
23+
name: string; // display name e.g. "Production", "Dev"
24+
url: string; // environment base URL e.g. https://org1234.crm.dynamics.com
25+
region?: string; // optional e.g. "europe"
26+
}
27+
```
28+
29+
### Environment-scoped deep links (update when environment is selected)
30+
| Name | URL pattern |
31+
|------|------------|
32+
| Solution list | `https://make.powerapps.com/environments/{envId}/solutions` |
33+
| Canvas apps list | `https://make.powerapps.com/environments/{envId}/apps` |
34+
| Model-driven apps | `https://make.powerapps.com/environments/{envId}/modelApps` |
35+
| Dataverse tables | `https://make.powerapps.com/environments/{envId}/entities` |
36+
| Dataflows | `https://make.powerapps.com/environments/{envId}/dataflows` |
37+
| Power Automate flows | `https://make.powerautomate.com/environments/{envId}/flows` |
38+
| PPAC environment detail | `https://admin.powerplatform.microsoft.com/environments/{envId}` |
39+
40+
Note: `{envId}` here is the GUID environment ID, not the org URL. Users will need to know their environment ID or we derive it. See Phase 2 research (2.6) for whether this can be retrieved automatically.
41+
42+
### UI
43+
- Dropdown to select active environment (or "No environment selected")
44+
- "+ Add environment" opens a small form: name + base URL (from which we can derive the env ID if needed)
45+
- Selected environment persisted in localStorage under `pp_active_environment`
46+
- Env-scoped links only show when an environment is selected
47+
48+
## Component
49+
`src/components/sections/PowerPlatformSection.tsx`
50+
`src/data/tilesPowerPlatform.ts` — static links array

0 commit comments

Comments
 (0)