This prototype is to demonstrate that SharePoint Online can support this requirement without requiring users to manually copy a Contact value and perform a separate search.
The current cross-reference table is intentionally used as a non-invasive proof of concept. It allows us to demonstrate the routing logic without changing the existing Playbook or Contacts structures.
For production, the final design would depend on the existing data and business rules. For example, the relationship could remain in a mapping table, or the Contacts library could be extended with additional metadata such as a ContactKey or group classification.
The important point is that SharePoint can support the pattern:
Play selected → routing value identified → matching Contacts returned
A single Play can return multiple Contacts, and the design does not require manually maintained hyperlinks between individual Playbook pages and individual Contact pages.
The next step is therefore not to redesign the data immediately, but to review the existing Playbook and Contacts metadata and determine the most appropriate way to represent the business relationship.
Thursday Demo
Play selected
↓
[Contacts]
↓
`SoC` is passed automatically
↓
SharePoint applies the filter/search
↓
matching Contact pages are shownSo the Contacts button is the user action that triggers the handoff.
And the rule still fits:
No Contact value
→ no [Contacts] button
Contact value present
→ show [Contacts] buttonThat is probably the clearest way to explain it to the page owner tomorrow: the user sees a Contacts button only when the Play has a Contact reference, and clicking it performs the lookup they currently do manually.
SharePoint Playbook → Contacts Prototype
1. What problem are we solving?
|
Current user experience |
Desired experience |
|---|---|
|
User opens a Play |
User opens a Play |
|
Sees a Contact reference |
Sees a Contacts option |
|
Copies the Contact value |
Clicks once |
|
Searches SharePoint manually |
Matching Contacts are shown |
|
Interprets results |
No manual search required |
Core requirement:
Play selected → routing value identified → matching Contacts returned
2. What has been built so far?
|
Component |
Current state |
|---|---|
|
Playbook |
Existing SharePoint content |
|
Contacts |
Existing SharePoint pages |
|
Cross-reference / mapping table |
Prototype helper |
|
JSON formatting |
Working |
|
Passed value |
|
|
Filtering |
Proven against pseudo Contacts data |
|
Manual links |
Not required |
|
JavaScript |
No custom JavaScript |
|
Power Apps / Power Automate / SPFx |
Not required for prototype |
Current prototype flow:
Playbook ToC
↓
Selected Play
↓
JSON passes routing value
↓
Mapping / xref
↓
Pseudo Contacts
↓
filtered resultsExample:
Security Incident
↓
SoC
↓
Security Operations Centre
Bob, Station 2
Security Duty Officer3. Why the xref / mapping table exists
The mapping table was created deliberately so the prototype could be built without changing the existing Playbook or Contacts structures.
It can represent relationships such as:
|
Play |
Contact Group |
|---|---|
|
Security Incident |
SoC |
|
Security Incident |
NOC |
|
Network Outage |
NOC |
This also allows one Play to route to more than one Contact group.
The mapping table therefore answers:
Which Contact groups are relevant to this Play?
4. Important design distinction
The Play does not need to point directly to individual Contacts.
Instead:
Play
↓
routing/classification value
↓
Contact group
↓
matching ContactsExample:
Security Incident
↓
SoC + NOC
↓
all Contacts classified as SoC or NOCThis avoids:
Security Incident → Bob
Security Incident → Jane
Security Incident → SOC pageand therefore avoids maintaining individual Contact relationships across hundreds of Plays.
5. What the real Contacts source looks like
Contacts are SharePoint pages, not conventional list rows.
That is fine.
The likely production improvement is to add structured metadata to the Contact page library / Contact Page Template.
Possible fields:
|
Field |
Purpose |
|---|---|
|
ContactKey |
Routing/classification value |
|
Contact Type |
Team / individual / role |
|
Support Level |
L2 / L3 |
|
|
Optional |
|
Phone |
Optional |
|
Status |
Active / inactive |
Example:
|
Contact Page |
ContactKey |
|
Phone |
|---|---|---|---|
|
Security Operations Centre |
SoC |
soc@... |
555-0199 |
|
Bob, Station 2 |
SoC |
555-0003 |
|
|
Security Duty Officer |
SoC |
duty@... |
|
|
Network Operations Centre |
NOC |
noc@... |
555-0123 |
The Contact page itself remains free-form.
The metadata simply makes it searchable/filterable.
6. Likely production flow
Playbook
↓
selected Play
↓
mapping identifies SoC / NOC / etc.
↓
parameter passed
↓
Contacts pages filtered by ContactKey
↓
matching Contact pages displayedEventually:
Something Happened
↓
[Contacts]
↓
SoC + NOC
↓
┌────────────────────────────┐
│ Contacts │
│ │
│ Security Operations Centre │
│ Bob, Station 2 │
│ Network Operations Centre │
└────────────────────────────┘7. What the prototype proves
|
Question |
Answer |
|---|---|
|
Can SharePoint pass a value from the Playbook? |
Yes |
|
Can JSON construct the navigation/filter request? |
Yes |
|
Can the destination be filtered dynamically? |
Yes |
|
Can one Play route to multiple Contact groups? |
Yes, through the mapping model |
|
Do users need to copy and search manually? |
No |
|
Do we need hard-coded Contact hyperlinks? |
No |
|
Does the final business taxonomy need to be known yet? |
No |
The prototype demonstrates technical feasibility.
It does not attempt to define the client's final business model.
8. Next technical steps
|
Priority |
Task |
|---|---|
|
1 |
Demo the current prototype |
|
2 |
Confirm the business likes the parameter-driven behaviour |
|
3 |
Review the real Contacts page library |
|
4 |
Determine what metadata already exists |
|
5 |
Propose a structured metadata block for the Contact Page Template |
|
6 |
Decide whether |
|
7 |
Test filtering real Contact pages instead of pseudo Contacts |
|
8 |
Test multiple routing values such as |
|
9 |
Determine the cleanest native SharePoint presentation for filtered Contact pages |
|
10 |
Decide whether the mapping table remains permanent or becomes a migration/translation layer |
9. Questions for the client after the demo
These are the business questions you do not need to answer yourself:
|
Question |
Why it matters |
|---|---|
|
What makes a Contact relevant to a Play? |
Defines the routing rule |
|
Are Contact groups already defined? |
May avoid inventing new taxonomy |
|
Can one Play require multiple groups? |
Likely yes |
|
Can one Contact belong to multiple groups? |
Affects metadata design |
|
Is there existing metadata in Contacts that can be reused? |
Avoids unnecessary schema changes |
|
Who maintains the classifications? |
Determines governance |
|
Should the mapping table remain? |
Depends on business complexity |
10. One-sentence architecture summary
The Playbook supplies a routing value, the mapping layer resolves the relevant Contact classification, and SharePoint returns the Contact pages whose metadata matches that classification.
And the most important sentence for tomorrow:
We have demonstrated the behaviour without changing the existing Playbook or Contacts structures; the next step is to determine how the client's existing data should represent that relationship in production.
Friday User Experience Design
Let's keep the xref/mapping table for now.
The reason is simple: we do not know the business rules well enough yet to confidently bake the relationship directly into the real Contacts library.
The current prototype has already proven a useful pattern:
|
Layer |
Role |
|---|---|
|
Play |
Provides the selected Play/title/acronym |
|
Xref / mapping table |
Translates that Play value into the relevant Contact classification/value |
|
Contacts |
Holds the actual Contact pages |
|
JSON |
Passes the selected value into the query/filter |
The production version can therefore become:
Selected Play
↓
mapping/xref
↓
ContactKey(s)
↓
ProdCopy Contacts library
↓
filter Contact pagesThat is safer than jumping straight to:
Play acronym = ContactKeybecause you already know the naming is not necessarily clean. Sometimes the title is the filename-derived value; sometimes you had to manually create acronyms. That is exactly the kind of mismatch a mapping table is good at absorbing.
What I would do with ProdCopy Contacts
Add one structured metadata field to the copied Contacts library, something like:
ContactKeyThen populate a small test set only:
|
Contact page |
ContactKey |
|---|---|
|
Security Operations Centre.aspx |
SoC |
|
Bob Station 2.aspx |
SoC |
|
Network Operations Centre.aspx |
NOC |
Now your xref can say:
|
PlayKey |
ContactKey |
|---|---|
|
Security Incident |
SoC |
|
Major Incident |
SoC |
|
Major Incident |
NOC |
That gives you a genuine many-to-many model without forcing you to alter hundreds of Plays.
The Contacts library can then be filtered on a real column. SharePoint supports filtering lists and libraries on columns, and views can be built around those filters. (Microsoft Support)
Why I prefer xref + ContactKey right now
Because they solve different problems:
xref
= which Contact classifications apply to this Play?
ContactKey on Contacts
= which Contact pages belong to that classification?That separation is valuable while you are still discovering the client's data.
Later, after you understand the business, you may discover:
The Play acronym already is the ContactKey everywhere.
If that proves true, fabulous. The xref becomes unnecessary and you can simplify to:
Play acronym
↓
Contacts.ContactKeyBut I would discover that, not assume it.
So my recommendation for the ProdCopy experiment is:
- Keep your working xref.
-
Add
ContactKeyto ProdCopy Contacts. - Tag perhaps 5 to 10 Contact pages.
- Point the current JSON/filter flow at those real pages.
- Test one Play → one ContactKey.
-
Test one Play → multiple ContactKeys such as
SoC + NOC. - Only then decide whether the xref is architectural or merely scaffolding.
That gives you the most useful answer for the client:
We can make this work without restructuring the existing Playbook. The prototype uses a mapping layer, while the Contacts copy uses structured metadata. Once we understand the actual business relationships, we can determine whether the mapping layer is still needed.
That is where I think you are now.
Yes. You have crossed from Proof of Concept into credible sandbox implementation.
And six is a very good number. Enough variation to prove the design, small enough that you can hand-curate the data and make the experience convincing.
I would change the objective now:
Do not prove that the mechanism works. Prove that this is what the production user experience could look like. ⚽️
Sandbox Demo: six real Plays 🏀
Build six representative Plays from the production copy, preferably chosen to exercise different Contact patterns:
|
Play |
Contact routing |
Why include it |
|---|---|---|
|
Play A |
SoC |
Simple single group |
|
Play B |
NOC |
Different single group |
|
Play C |
SoC + NOC |
Multiple Contact groups |
|
Play D |
Service Desk / another real group |
Different Contact type |
|
Play E |
No Contacts |
Proves |
|
Play F |
One of the messier real cases |
Demonstrates that this isn't just a toy example |
Use the real Play titles, real layout, real page style and real Contact pages from ProdCopy. You can hard-code or manually configure the routing for these six. At this stage that's not cheating. You are validating the user experience and the proposed data structure, not designing the bulk migration yet.
Still keep the xref for this demo
Don't make structural modifications before knowing the final business model!!
For six Plays:
REAL PLAY
↓
existing Play identifier
↓
XREF / mapping
↓
SoC / NOC / etc.
↓
[Contacts]
↓
real ProdCopy Contacts
↓
matching real Contact pages
Then add ContactKey to the ProdCopy Contacts library, not production.
Populate it only for the Contacts needed by those six Plays.
For example:
|
Real Contact page |
ContactKey |
|---|---|
|
Security Operations Centre |
SoC |
|
Security Duty Officer |
SoC |
|
Network Operations Centre |
NOC |
|
Network Duty Officer |
NOC |
Now you have the real end-to-end chain without pretending you've solved 500 Plays.
Make the destination look real too
I would absolutely create a dedicated Contacts view in ProdCopy.
The user should click:
[Contacts]
and land on something that looks intentional:
Contacts for this Play
|
Contact |
|
Phone |
|---|---|---|
|
Security Operations Centre |
soc@... |
555-0199 |
|
Bob, Station 2 |
555-0003 |
The Contact name should open the actual Contact page.
If Email and Phone aren't structured metadata yet, don't invent a large migration project just for the demo. For the six cases, populate enough metadata to demonstrate what the future view could expose. The full Contact page remains available behind the title.
One case I really want in the six
Include one Play with no Contacts.
That proves an important UX rule:
Play has Contact mapping
→ [Contacts]
Play has no Contact mapping
→ nothingThat is much more convincing than six happy-path records all behaving identically.
What you are not committing to
This sandbox does not establish that:
-
ContactKeyis definitely the final field name. - the xref must remain forever.
- somebody will manually classify 500 Plays.
- every Contact needs restructuring.
- the six manually configured relationships represent the final taxonomy.
Instead:
We are using six representative production examples to validate the complete user experience and determine what metadata and mapping are required before designing the production-scale implementation.
That is a very defensible next stage.
And crucially, Business gets to see:
real Play
↓
real [Contacts] button
↓
real routing
↓
real Contacts library
↓
real Contact pagesNo pseudo-Contacts. No abstract “imagine this is production.” The plumbing behind those six can be partially hand-tuned because the thing under evaluation now is the proposed interface and information model.
Your POC proved can we do it?
The six-Play sandbox now answers:
Is this actually how we want it to work?
That is the right next question.
🟢🟢🟢🟢🟢 Friday Build 🟢🟢🟢🟢🟢
Yes. That explains why the swap failed.
Your original PoC quietly depended on something the production copy did not preserve in the same shape:
the acronym was the routing key.
The previous prototype already had the right business key hiding in plain sight. Users were doing this manually:
Play
↓
read acronym
↓
copy acronym
↓
query ContactsYour PoC automated the middle:
Play
↓
acronym
↓
JSON passes acronym
↓
Contacts querySo if the original Excel contains the authoritative Play-to-acronym mapping, then that Excel data needs to feed the sandbox PlaysToC.
Revised sandbox model
|
Source |
Role |
|---|---|
|
Original Excel |
Authoritative Play + acronym source |
|
PlaysToC |
Presents the six selected Plays and retains acronym |
|
JSON |
Passes acronym when |
|
ProdCopy Contacts |
Real Contact pages |
|
Contact metadata/search |
Matches the passed acronym |
So:
Original Excel
↓
Play title + acronym
↓
Sandbox PlaysToC
↓
user selects Play
↓
[Contacts]
↓
JSON passes acronym
↓
ProdCopy Contacts
↓
matching real Contact pagesThat also changes how I would think about the xref.
If Excel already says:
Play X → SoC
Play Y → NOCthen you may not need to invent a second mapping table for those six. Excel is already carrying the mapping.
Your earlier xref was useful because you needed somewhere to manufacture the relationship in the PoC. Now you have discovered the actual source of that relationship.
So the immediate task is probably:
- Take the original Excel as the source for the six sandbox Plays.
-
Preserve both Play title and acronym when building
PlaysToC. - Make sure the JSON passes the acronym, not a filename-derived title.
- Point the resulting Contacts action at the real ProdCopy Contacts source.
- See whether the existing Contact pages can already be found reliably by that acronym.
-
Only add
ContactKeymetadata to ProdCopy Contacts if the existing Contacts search is too loose or inconsistent.
That last point matters.
You may have been racing toward ContactKey before confirming whether the existing acronym is already the production key on both sides.
If it is, the production concept may be beautifully small:
Excel / PlaysToC acronym
↓
[Contacts]
↓
existing Contacts acronym/search
↓
matching pagesThen the real improvement is simply:
Automate the acronym lookup users already perform manually.
That is a much stronger story because you are not proposing a new business relationship at all. You are using the one they already have.
Parse the URL Path for the actual FILENAME
Yes. That is a sensible next check.
If the production PlayToC already stores a Product/Play URL, and the actual file name embedded in that URL is the stable value that corresponds to the Contact lookup, then you may be able to derive the routing key from the URL instead of depending on a manually maintained acronym list.
Conceptually:
Prod PlayToC
Product URL
↓
extract file name
↓
derive stable Play key
↓
[Contacts]
↓
query/filter ContactsFor example:
.../SitePages/Security-Incident.aspxcould yield:
Security-Incidentor, if your convention supports it:
SoCThe important question is not whether you can strip the filename. You can.
The important question is whether that filename is 100% reliable as the business key across the production data.
I would test exactly that before changing the sandbox design.
What to validate
|
Check |
Why it matters |
|---|---|
|
Every Play has a URL |
Otherwise extraction fails |
|
Filename is stable |
Renaming a page could break routing |
|
Filename uniquely identifies the intended Contact lookup |
Avoid false matches |
|
Naming convention is consistent |
No |
|
Existing Contacts query understands the derived value |
Confirms end-to-end compatibility |
|
Special characters / spaces are predictable |
Important for JSON URL construction |
If those all hold, you may have found a very clean production key that already exists.
If they do not hold, then the acronym from Excel is probably still the safer authoritative routing value.
Yes. This is exactly where Python earns its lunch. 🐍
You have a very suitable little validation job:
Input:
production Play URLs + existing acronym/source data
Python checks:
- extract folder classification
- extract page filename / identity
- normalize values
- compare against existing acronym data
- flag exceptions
- summarize consistencyFor example, from:
https://tenant.sharepoint.com/sites/Playbook/SECURE/SomePlay.aspxPython can derive:
PlayType = SECURE
PlayIdentity = SomePlayThen you can compare that against the existing Excel row:
Acronym = SoCand produce something useful like:
|
URL |
PlayType |
PlayIdentity |
Acronym |
Status |
|---|---|---|---|---|
|
.../SECURE/SomePlay.aspx |
SECURE |
SomePlay |
SoC |
OK |
|
.../ADMIN/OtherPlay.aspx |
ADMIN |
OtherPlay |
NOC |
OK |
|
.../PUBLIC/Weird%20Name.aspx |
PUBLIC |
Weird Name |
DBA |
Review |
That lets you answer the real architecture question with evidence:
Are folder, filename, and acronym reliable enough to become three separate derived attributes?
And Python is ideal because this is analysis and validation, not something that has to run inside SharePoint.
So the pattern would be:
Excel / export
↓
Python audit
↓
confidence report + exceptions
↓
decide SharePoint rulesMuch better than eyeballing 500 rows until the alphabet starts moving.
SUMMARY
Absolutely. Here’s the revised “morning re-entry” summary.
Playbook → Contacts Sandbox Demo
Where we are
The Proof of Concept passed.
Business now wants to see a realistic sandbox version using production-like data and a real-looking interface.
The next demo should use six real Plays. It does not need to cover all Plays yet.
The purpose of the sandbox demo is to prove the real user experience, not to complete the production migration.
Current user problem
Today, the user must:
Open a Play
↓
read the Contact acronym
↓
copy the acronym
↓
navigate to the Contacts folder
↓
paste the acronym into SharePoint search
↓
open the matching Contact pageThe requirement is to remove those manual copy-and-search steps.
Desired behaviour:
Play selected
↓
[Contacts]
↓
Contact acronym passed automatically
↓
Contacts queried
↓
matching Contact pages returnedThe existing acronym is therefore important.
It is not something newly invented by the prototype. It is already part of the current business process.
Why the original PoC worked
The first PoC was based on the previous designer's prototype data.
That data already contained the acronym relationship needed for Contact lookup.
The PoC then automated the manual process:
Play
↓
acronym
↓
JSON
↓
filtered pseudo-ContactsWhen the PoC data was simply replaced with production-copy data, the relationship stopped working because the production version did not expose the acronym in the same way.
That explains the failure.
Source for the sandbox Plays
The original Excel appears to contain the important Play information, including the Contact acronym.
For the six sandbox Plays, use that Excel as the source for the PlayToC data.
Preserve:
|
Value |
Purpose |
|---|---|
|
Play title |
Display / identification |
|
Play URL |
Navigation and possible derived metadata |
|
Contact acronym |
Contact lookup |
|
Other existing fields |
As required |
Production-style sandbox flow
Original Excel
↓
six real Plays
↓
Sandbox PlayToC
↓
user selects Play
↓
[Contacts]
↓
JSON passes Contact acronym
↓
ProdCopy Contacts
↓
matching real Contact pagesThe six Plays should look and behave like the real system.
Hard-coding or manually configuring those six is acceptable for this demo.
The goal is to validate the experience.
Contacts
The real Contacts are SharePoint pages stored in the Contacts folder/library.
They remain pages.
Do not redesign them yet.
The immediate question is:
Is the existing acronym lookup against ProdCopy Contacts reliable enough to use directly?
If yes, very little new structure may be required.
If not, a future ContactKey metadata field on the Contacts library remains an option.
Mapping / xref
The xref proved useful in the PoC because it allowed the relationship to be demonstrated without changing existing production structures.
For the next sandbox demo:
- keep the xref if needed;
- do not remove it merely for architectural neatness;
- use the actual acronym source where possible;
- determine later whether the xref is permanent or only scaffolding.
The decision depends on the real data.
Three useful values now emerging
We now have three different concepts that should not be collapsed into one field.
|
Value |
Likely role |
|---|---|
|
Folder name |
Primary Play classification |
|
Page filename |
Play identity |
|
Acronym |
Contact routing / lookup |
This is a much cleaner model.
Primary Play classification
Business is planning the folder structure.
The requested folder classifications are:
ADMIN
SECURE
PUBLICThese can be treated as the primary Play classification.
That means the Play URL may eventually contain useful structured information:
/.../SECURE/SomePlay.aspx
↑ ↑
PlayType Play identityPotential derived values:
PlayType = SECURE
PlayIdentity = SomePlayThe acronym remains separate:
ContactAcronym = SoCTomorrow morning: checks to perform
|
Check |
Purpose |
|---|---|
|
Confirm acronym in original Excel |
Verify the existing Contact routing value |
|
Compare acronym against six real Plays |
Ensure the sandbox uses real relationships |
|
Test ProdCopy Contact search |
Determine whether acronym lookup is reliable |
|
Parse Play URL filename |
Determine whether filename can serve as Play identity |
|
Parse Play URL folder |
Confirm |
|
Check unusual URLs |
Spaces, encoded characters, renamed pages, odd paths |
|
Check duplicates |
Duplicate acronyms or filenames |
|
Check missing values |
Plays without acronym or URL |
|
Select six representative Plays |
Build a convincing sandbox demo |
|
Include one no-Contact case if possible |
Demonstrate button behaviour |
Six sandbox Plays
Choose six real examples that exercise different scenarios.
Ideally include:
|
Example |
Reason |
|---|---|
|
ADMIN Play |
Tests classification |
|
SECURE Play |
Tests classification |
|
PUBLIC Play |
Tests classification |
|
Play with one Contact acronym |
Simple case |
|
Play with multiple relevant Contact groups if applicable |
More complex case |
|
Play with no Contact |
Tests |
The exact business combinations can be chosen after inspecting the data.
Contacts button rule
Desired behaviour:
Play has Contact value
↓
show [Contacts]
Play has no Contact value
↓
do not show [Contacts]The button should trigger the lookup the user currently performs manually.
Python audit
Yes: use Python to validate the data before deciding the final SharePoint rules.
Input:
production-style Play URLs
+ original Excel
+ acronym dataPython should:
extract folder classification
extract page filename
decode URL values
normalize identifiers
compare against acronym data
flag exceptions
identify duplicates
identify missing values
summarize consistencyExample output:
|
Play URL |
PlayType |
PlayIdentity |
Acronym |
Status |
|---|---|---|---|---|
|
.../SECURE/SomePlay.aspx |
SECURE |
SomePlay |
SoC |
OK |
|
.../ADMIN/OtherPlay.aspx |
ADMIN |
OtherPlay |
NOC |
OK |
|
.../PUBLIC/Weird%20Name.aspx |
PUBLIC |
Weird Name |
DBA |
Review |
The Python exercise answers:
Are folder, filename, and acronym reliable enough to become three separate attributes?
Likely architecture if the checks pass
Play URL
├── folder → PlayType
└── filename → PlayIdentity
Original Play data
└── acronym → Contact routing
Play selected
↓
[Contacts]
↓
acronym passed automatically
↓
ProdCopy Contacts queried
↓
matching Contact pages shownWhat not to decide yet
Do not commit yet to:
- removing the xref;
- manually updating hundreds of Plays;
-
adding
ContactKeyto all Contact pages; - restructuring Contacts;
- introducing SPFx;
- Power Apps;
- Power Automate;
- custom JavaScript.
The sandbox exists to determine what is actually necessary.
What the sandbox demo should prove
The existing Contact acronym can be used to automate the Contact lookup users currently perform manually.
And, separately:
The planned folder structure can provide a primary Play classification such as
ADMIN,SECURE, orPUBLIC.
The six-Play sandbox should answer:
Does this look and behave like something Business would accept as the real solution?
One-sentence morning reminder
Use the original Excel to restore the real acronym relationship, use six real Plays, point the Contacts button at ProdCopy Contacts, and use Python to validate whether folder, filename, and acronym can become reliable derived attributes before designing anything larger.
That should be enough to get you moving again in the morning without reopening the entire archaeology pit.