Skip to content

Conversation

@fredupstair
Copy link
Contributor

@fredupstair fredupstair commented Feb 1, 2026

Q A
Bug fix? no
New feature? no
New sample? yes
Related issues? fixes #X, partially #Y, mentioned in #Z

What's in this Pull Request?

This PR adds a new sample to the PnP Extensions repository that shows how to consume the Microsoft Graph Copilot APIs to generate page-level insights. The sample demonstrates how an Application Customizer can analyze SharePoint page content in combination with your emails, chats, meetings, and files to provide instant, personalized insights, surfacing key people, pending actions, decisions, and relevant context that matter to you.

Copilot AI review requested due to automatic review settings February 1, 2026 15:26
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new SPFx Application Customizer sample, “Smart Context”, which calls the Microsoft Graph Copilot API to generate structured, page-level insights and presents them in a rich, Copilot-inspired panel UI in SharePoint Online.

Changes:

  • Introduces a Copilot service layer (CopilotService, typed contracts, error classes, JSON parsing/validation helpers, and system prompt) to call the Microsoft Graph Copilot APIs and normalize responses.
  • Adds a complete React UI for the Smart Context panel (floating trigger button, loader, header/footer, section components, styling) that renders role, actions, decisions, people, timeline, and attribution references.
  • Sets up the SPFx 1.22.1 project scaffolding, configuration, build tooling (Heft), permissions, documentation, and static assets for this sample.

Reviewed changes

Copilot reviewed 51 out of 61 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
samples/react-application-smart-context/tsconfig.json Extends the SPFx web build rig base TypeScript configuration for the sample.
samples/react-application-smart-context/src/extensions/smartContextApp/services/serviceUtils.ts Adds utility to strip inline citation markdown from Copilot responses.
samples/react-application-smart-context/src/extensions/smartContextApp/services/jsonUtils.ts Implements JSON extraction from Copilot text responses and validation/normalization for the Smart Context data model.
samples/react-application-smart-context/src/extensions/smartContextApp/services/index.ts Barrel exports for Copilot-related services, interfaces, errors, and JSON utilities.
samples/react-application-smart-context/src/extensions/smartContextApp/services/errors.ts Defines custom error types and a helper to map errors to user-friendly messages.
samples/react-application-smart-context/src/extensions/smartContextApp/services/ICopilotService.ts Declares Copilot conversation/chat contracts and the Smart Context schema interfaces.
samples/react-application-smart-context/src/extensions/smartContextApp/services/CopilotService.ts Implements MS Graph Copilot conversation creation, chat sending, and Smart Context retrieval, including basic response processing.
samples/react-application-smart-context/src/extensions/smartContextApp/loc/myStrings.d.ts Declares localized string typings for the application customizer.
samples/react-application-smart-context/src/extensions/smartContextApp/loc/en-us.js Provides the English localization resource for the customizer title.
samples/react-application-smart-context/src/extensions/smartContextApp/constants/systemPrompt.ts Defines the structured system prompt instructing Copilot to return a specific JSON schema.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/index.ts Barrel exports for Smart Context section components and icon utilities.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/iconUtils.ts Adds icon selection helpers and role definitions for use across the UI.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/TldrItem.tsx Renders individual TL;DR bullet items with animation.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/TimelineItem.tsx Renders timeline events with source iconography and vertical timeline styling.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/SmartContextHeader.tsx Defines the Smart Context panel header, including AI badge and title/subtitle.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/SmartContextFooter.tsx Defines the Smart Context panel footer with a data source disclosure message.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/Section.tsx Generic section wrapper for titles, icons, content lists, empty state, and “show more” behavior.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/PersonItem.tsx Displays a person card with Persona and optional profile link/details.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/PendingActionItem.tsx Displays pending action cards with urgency styling and due date display.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/MyRoleCard.tsx Renders the “My Role” card with markdown-bold parsing and a role legend.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/KeyDecisionItem.tsx Renders individual key decision items with icon and text.
samples/react-application-smart-context/src/extensions/smartContextApp/components/sections/AttributionItem.tsx Renders content attribution links with icons derived from URL types.
samples/react-application-smart-context/src/extensions/smartContextApp/components/scss.d.ts Provides TypeScript typings for SCSS modules used by React components.
samples/react-application-smart-context/src/extensions/smartContextApp/components/SmartContextPanel.tsx Hosts the Fluent UI Panel, orchestrates Copilot calls, JSON extraction/validation, error handling, and passes data into the content component.
samples/react-application-smart-context/src/extensions/smartContextApp/components/SmartContextPanel.module.scss Styles for the Smart Context panel container, loading state, and attribution list.
samples/react-application-smart-context/src/extensions/smartContextApp/components/SmartContextContent.tsx Composes all Smart Context sections, groups attributions, and controls show-more behavior and entry animations.
samples/react-application-smart-context/src/extensions/smartContextApp/components/SmartContextContent.module.scss Main styling for Smart Context content, including header, sections, cards, timeline, and animations.
samples/react-application-smart-context/src/extensions/smartContextApp/components/SmartContextContainer.tsx Controls the floating button + panel lifecycle and passes necessary props.
samples/react-application-smart-context/src/extensions/smartContextApp/components/ISmartContextPanelProps.ts Defines props for the Smart Context panel component.
samples/react-application-smart-context/src/extensions/smartContextApp/components/ISmartContextContainerProps.ts Defines props for the Smart Context container component.
samples/react-application-smart-context/src/extensions/smartContextApp/components/IFloatingButtonProps.ts Defines props for the floating trigger button.
samples/react-application-smart-context/src/extensions/smartContextApp/components/FloatingButton.tsx Implements the fixed-position Fluent side tab button to open the Smart Context panel.
samples/react-application-smart-context/src/extensions/smartContextApp/components/FloatingButton.module.scss Styles the floating side tab, including focus behavior and hover transitions.
samples/react-application-smart-context/src/extensions/smartContextApp/components/AiLoader.tsx Implements an animated AI “solar system” loader with rotating status messages.
samples/react-application-smart-context/src/extensions/smartContextApp/components/AiLoader.module.scss Styles and animations for the AI loader visual and progress bar.
samples/react-application-smart-context/src/extensions/smartContextApp/SmartContextAppApplicationCustomizer.ts SPFx application customizer entry point that injects and renders the Smart Context container into the page.
samples/react-application-smart-context/src/extensions/smartContextApp/SmartContextAppApplicationCustomizer.manifest.json Defines the SPFx extension manifest, including IDs and metadata for the customizer.
samples/react-application-smart-context/package.json Declares dependencies, devDependencies, scripts, engines, and toolchain configuration for the sample.
samples/react-application-smart-context/docs/architecture.md Documents the overall architecture, API flow, prompt design, and design rationale of the Smart Context sample.
samples/react-application-smart-context/config/write-manifests.json Configures SPFx manifest writing behavior for the sample.
samples/react-application-smart-context/config/typescript.json Extends the SPFx rig TypeScript config and static assets copying settings.
samples/react-application-smart-context/config/serve.json Sets up SPFx serve configurations and debug custom action for the Smart Context customizer.
samples/react-application-smart-context/config/sass.json Extends the SPFx rig SASS configuration.
samples/react-application-smart-context/config/rig.json Points to the @microsoft/spfx-web-build-rig rig package for shared config.
samples/react-application-smart-context/config/package-solution.json Defines the SPFx solution package, features, and required Microsoft Graph permissions.
samples/react-application-smart-context/config/deploy-azure-storage.json Provides configuration for deploying built assets to Azure Storage.
samples/react-application-smart-context/config/config.json Configures SPFx bundling, including the application customizer entrypoint and localized resources.
samples/react-application-smart-context/assets/smart-context-preview-5.png Adds a Smart Context UI preview image used by the README.
samples/react-application-smart-context/assets/smart-context-preview-3.png Adds another Smart Context UI preview image used by the README.
samples/react-application-smart-context/README.md Documents the Smart Context sample, setup instructions, prerequisites, and references.
samples/react-application-smart-context/.yo-rc.json Yeoman generator metadata for the SPFx solution, including versioning and environment info.
samples/react-application-smart-context/.nvmrc Pins the Node.js version for development environments.
samples/react-application-smart-context/.npmignore Defines which build artifacts are published to npm if the package is ever published.
samples/react-application-smart-context/.gitignore Excludes build outputs, dependencies, and other non-source artifacts from version control.
samples/react-application-smart-context/.eslintrc.js Configures ESLint rules for the SPFx project using the SPFx and RushStack configs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +25 to +36

React.useEffect(() => {
const interval = setInterval(() => {
setIsVisible(false);

setTimeout(() => {
setCurrentMessageIndex((prev) => (prev + 1) % messages.length);
setIsVisible(true);
}, 300);
}, 3000);

return () => clearInterval(interval);
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This useEffect sets up an interval that in turn schedules setTimeout callbacks, but only the interval is cleared on unmount; pending timeouts can still fire and attempt to update state on an unmounted component. To avoid potential memory leaks and React warnings, also clear the timeout(s) (or refactor to use a single interval without nested timeouts) when the component unmounts or when messages changes.

Suggested change
React.useEffect(() => {
const interval = setInterval(() => {
setIsVisible(false);
setTimeout(() => {
setCurrentMessageIndex((prev) => (prev + 1) % messages.length);
setIsVisible(true);
}, 300);
}, 3000);
return () => clearInterval(interval);
const timeoutRef = React.useRef<number | null>(null);
React.useEffect(() => {
const interval = setInterval(() => {
setIsVisible(false);
if (timeoutRef.current !== null) {
clearTimeout(timeoutRef.current);
}
timeoutRef.current = window.setTimeout(() => {
setCurrentMessageIndex((prev) => (prev + 1) % messages.length);
setIsVisible(true);
}, 300);
}, 3000);
return () => {
clearInterval(interval);
if (timeoutRef.current !== null) {
clearTimeout(timeoutRef.current);
}
};

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +72
// DEBUG: Log full API response
console.log('[CopilotService] Chat API Response:', JSON.stringify(response, null, 2));
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this console.log of the full Copilot chat API response in the production service can leak verbose data to the browser console and clutter logs in real environments. Consider removing it or wrapping it in a conditional debug/logging utility so it is disabled in production builds.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +22
const jsonMatch = text.match(/\{[\s\S]*\}/);

if (!jsonMatch) {
throw new NoJsonFoundError();
}

try {
return JSON.parse(jsonMatch[0]) as Record<string, unknown>;
} catch (error) {
throw new JsonParseError(error);
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSON extraction regex here is greedy (/\{[\s\S]*\}/), so if the Copilot response contains more than one JSON fragment or additional braces after the JSON object, jsonMatch[0] can include extra trailing content and cause JSON.parse to throw. Consider using a non‑greedy pattern or more robust JSON block detection (e.g., tracking brace depth) so you reliably isolate just the JSON payload before parsing.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +38
const validatedData: ISmartContextData = {
myRole: data.myRole as ISmartContextData['myRole'],
pendingActions: Array.isArray(data.pendingActions) ? data.pendingActions : [],
keyDecisions: Array.isArray(data.keyDecisions) ? data.keyDecisions : [],
timeline: Array.isArray(data.timeline) ? data.timeline : [],
tldr: Array.isArray(data.tldr) ? data.tldr : [],
people: Array.isArray(data.people) ? data.people : [],
attributions: Array.isArray(data.attributions) ? data.attributions : []
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateSmartContextData asserts that data.myRole is an IMyRole, but it does not provide a fallback when myRole is missing or malformed, so callers that rely on the non‑optional ISmartContextData.myRole may receive undefined at runtime. Either validate and provide a default myRole object here or make myRole optional in the interface so the type system reflects the actual behavior.

Copilot uses AI. Check for mistakes.
@fredupstair fredupstair force-pushed the FP-react-application-smart-context branch from f8b1e35 to 3127b9b Compare February 2, 2026 17:29
@hugoabernier hugoabernier merged commit 008b54a into pnp:main Feb 2, 2026
3 checks passed
@hugoabernier
Copy link
Collaborator

Thank you @fredupstair for your sample! Highly appreciated!

We'd love to have your sample featured in one of our future community calls.

If haven't done so yet, and you'd be interested on showing this great sample in a public community call, please fill in following form and we'll get you scheduled - aka.ms/community/request/demo

Thank you for sharing your sample with others - you rock! 👏🥇👩‍💻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants