) {
- {ICONS[source.type] ?? source.type.slice(0, 2)}
+
- {humanize(source.type)}
+ {typeLabel}
{source.name}
@@ -144,6 +186,21 @@ function Canvas({
return () => document.removeEventListener("keydown", onKey);
}, []);
+ useEffect(() => {
+ const element = wrapper.current;
+ if (!element) return;
+ let hasFittedVisibleCanvas = false;
+ const observer = new ResizeObserver(([entry]) => {
+ const { width, height } = entry.contentRect;
+ if (!hasFittedVisibleCanvas && width > 0 && height > 0) {
+ hasFittedVisibleCanvas = true;
+ requestAnimationFrame(() => void fitView({ padding: 0.18, duration: 0 }));
+ }
+ });
+ observer.observe(element);
+ return () => observer.disconnect();
+ }, [fitView, graph]);
+
const hiddenIds = useMemo(
() => new Set(showNotes ? [] : graph.nodes.filter((node) => node.type === "canvasNote").map((node) => node.id)),
[graph.nodes, showNotes],
@@ -165,14 +222,19 @@ function Canvas({
.map((node) => ({
id: node.id,
type: "catalog",
- position: node.position,
+ position: variant === "workflow"
+ ? {
+ x: node.position.x * WORKFLOW_LAYOUT_SCALE_X,
+ y: node.position.y * WORKFLOW_LAYOUT_SCALE_Y,
+ }
+ : node.position,
data: { source: node, primary: primaryAgentIds.has(node.id) },
width: node.type === "start" || node.type === "end" ? 160 : 224,
height: 72,
draggable: false,
selectable: !compact,
})),
- [compact, graph.nodes, hiddenIds, primaryAgentIds],
+ [compact, graph.nodes, hiddenIds, primaryAgentIds, variant],
);
const graphNodeById = useMemo(() => new Map(graph.nodes.map((node) => [node.id, node])), [graph.nodes]);
const edges = useMemo
(
@@ -185,7 +247,7 @@ function Canvas({
? graphVisualColor(graphVisualKind(sourceNode))
: "var(--cp-border-strong)";
const targetNode = graphNodeById.get(edge.target);
- const handles = variant === "agent" && sourceNode && targetNode
+ const handles = sourceNode && targetNode
? nearestHandles(sourceNode, targetNode)
: {};
return {
@@ -193,9 +255,9 @@ function Canvas({
source: edge.source,
target: edge.target,
label: edge.label ?? branchLabel(edge.sourceHandle),
- type: variant === "agent" ? "straight" : "smoothstep",
+ type: "smoothstep",
...handles,
- markerEnd: { type: MarkerType.ArrowClosed, color },
+ markerEnd: { type: MarkerType.ArrowClosed, color, width: 18, height: 18 },
style: { strokeWidth: 1.8, stroke: color },
};
}),
diff --git a/src/content/solutions/blastbox-demo-agents.json b/src/content/solutions/blastbox-demo-agents.json
index cfc576a..d6edb95 100644
--- a/src/content/solutions/blastbox-demo-agents.json
+++ b/src/content/solutions/blastbox-demo-agents.json
@@ -72,8 +72,8 @@
"name": "Inventory & Fullfilment Agent",
"type": "agent",
"position": {
- "x": 563,
- "y": -396
+ "x": 508,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -89,7 +89,7 @@
"name": "Returns & Service Assistant",
"type": "agent",
"position": {
- "x": -787,
+ "x": -1012,
"y": -36
},
"details": {
@@ -106,7 +106,7 @@
"name": "Store Associate Assistant",
"type": "agent",
"position": {
- "x": 563,
+ "x": 788,
"y": -36
},
"details": {
@@ -125,8 +125,8 @@
"name": "Store Policy Agent",
"type": "agent",
"position": {
- "x": 905.3803458662553,
- "y": -147.24611797498108
+ "x": 1068,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -142,8 +142,8 @@
"name": "card-reissue",
"type": "skill",
"position": {
- "x": -787,
- "y": -256
+ "x": -672,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -156,8 +156,8 @@
"name": "membership-card-png",
"type": "skill",
"position": {
- "x": -596.4744111674235,
- "y": 73.99999999999996
+ "x": -1012,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -170,8 +170,8 @@
"name": "points-reconciliation",
"type": "skill",
"position": {
- "x": 692.3127555043441,
- "y": 141.98373876248843
+ "x": 1128,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -184,8 +184,8 @@
"name": "prorated-refund-calculator",
"type": "skill",
"position": {
- "x": 433.68724449565593,
- "y": 141.98373876248843
+ "x": 788,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -198,8 +198,8 @@
"name": "slip-pdf-generator",
"type": "skill",
"position": {
- "x": 353.7675664150662,
- "y": -103.9837387624884
+ "x": 448,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -212,8 +212,8 @@
"name": "Membership MCP v2 — Membership MCP v2 Server",
"type": "tool",
"position": {
- "x": -977.5255888325764,
- "y": 74.00000000000007
+ "x": -1352,
+ "y": 324
},
"details": {
"kind": "tool",
@@ -227,8 +227,8 @@
"name": "Warehouse MCP — Warehouse MCP Server",
"type": "tool",
"position": {
- "x": 563,
- "y": -566
+ "x": 508,
+ "y": -856
},
"details": {
"kind": "tool",
diff --git a/src/content/solutions/blastbox-deploy.json b/src/content/solutions/blastbox-deploy.json
index ad84ce9..3f93586 100644
--- a/src/content/solutions/blastbox-deploy.json
+++ b/src/content/solutions/blastbox-deploy.json
@@ -72,8 +72,8 @@
"name": "Inventory & Fullfilment Agent",
"type": "agent",
"position": {
- "x": 563,
- "y": -396
+ "x": 508,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -89,7 +89,7 @@
"name": "Returns & Service Assistant",
"type": "agent",
"position": {
- "x": -787,
+ "x": -1012,
"y": -36
},
"details": {
@@ -106,7 +106,7 @@
"name": "Store Associate Assistant",
"type": "agent",
"position": {
- "x": 563,
+ "x": 788,
"y": -36
},
"details": {
@@ -125,8 +125,8 @@
"name": "Store Policy Agent",
"type": "agent",
"position": {
- "x": 905.3803458662553,
- "y": -147.24611797498108
+ "x": 1068,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -142,8 +142,8 @@
"name": "card-reissue",
"type": "skill",
"position": {
- "x": -567,
- "y": -36
+ "x": -842,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -156,8 +156,8 @@
"name": "membership-card-png",
"type": "skill",
"position": {
- "x": -1007,
- "y": -35.99999999999997
+ "x": -1182,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -170,8 +170,8 @@
"name": "points-reconciliation",
"type": "skill",
"position": {
- "x": 692.3127555043441,
- "y": 141.98373876248843
+ "x": 1128,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -184,8 +184,8 @@
"name": "prorated-refund-calculator",
"type": "skill",
"position": {
- "x": 433.68724449565593,
- "y": 141.98373876248843
+ "x": 788,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -198,8 +198,8 @@
"name": "slip-pdf-generator",
"type": "skill",
"position": {
- "x": 353.7675664150662,
- "y": -103.9837387624884
+ "x": 448,
+ "y": 324
},
"details": {
"kind": "skill",
diff --git a/src/content/solutions/blastbox-omega.json b/src/content/solutions/blastbox-omega.json
index 10cc204..0c49b5d 100644
--- a/src/content/solutions/blastbox-omega.json
+++ b/src/content/solutions/blastbox-omega.json
@@ -63,8 +63,8 @@
"name": "Inventory & Fullfilment Agent",
"type": "agent",
"position": {
- "x": -111.99999999999997,
- "y": -396
+ "x": -391.99999999999994,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -99,8 +99,8 @@
"name": "Store Policy Agent",
"type": "agent",
"position": {
- "x": 169.45933368849074,
- "y": -260.45632866914406
+ "x": 168.00000000000006,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -116,8 +116,8 @@
"name": "points-reconciliation",
"type": "skill",
"position": {
- "x": 102.48414068000119,
- "y": 12.954605470389168
+ "x": 568,
+ "y": 323.99999999999994
},
"details": {
"kind": "skill",
@@ -130,8 +130,8 @@
"name": "prorated-refund-calculator",
"type": "skill",
"position": {
- "x": -16.545577394137197,
- "y": 162.2131509385322
+ "x": 228,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -144,8 +144,8 @@
"name": "slip-pdf-generator",
"type": "skill",
"position": {
- "x": -207.45442260586276,
- "y": 162.2131509385322
+ "x": -111.99999999999997,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -158,8 +158,8 @@
"name": "Membership MCP v2 — Membership MCP v2 Server",
"type": "tool",
"position": {
- "x": -326.4841406800012,
- "y": 12.95460547038919
+ "x": -452,
+ "y": 324
},
"details": {
"kind": "tool",
@@ -173,8 +173,8 @@
"name": "Order Management MCP — Order Management MCP Server",
"type": "tool",
"position": {
- "x": -284.00292614296654,
- "y": -173.16775640892135
+ "x": -792,
+ "y": 324.00000000000006
},
"details": {
"kind": "tool",
@@ -188,8 +188,8 @@
"name": "Policy RAG MCP v2 — Policy RAG MCP v2 Server",
"type": "tool",
"position": {
- "x": 302.3706857080558,
- "y": -366.4495949851288
+ "x": 168.00000000000006,
+ "y": -856
},
"details": {
"kind": "tool",
@@ -203,8 +203,8 @@
"name": "Warehouse MCP — Warehouse MCP Server",
"type": "tool",
"position": {
- "x": -111.99999999999993,
- "y": -566
+ "x": -391.99999999999994,
+ "y": -856
},
"details": {
"kind": "tool",
diff --git a/src/content/solutions/store-modern-agent.json b/src/content/solutions/store-modern-agent.json
index b554ad8..e23ff9c 100644
--- a/src/content/solutions/store-modern-agent.json
+++ b/src/content/solutions/store-modern-agent.json
@@ -56,8 +56,8 @@
"name": "Inventory & Fullfilment Agent",
"type": "agent",
"position": {
- "x": -111.99999999999997,
- "y": -396
+ "x": -391.99999999999994,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -88,8 +88,8 @@
"name": "Store Policy Agent",
"type": "agent",
"position": {
- "x": 248,
- "y": -36
+ "x": 168.00000000000006,
+ "y": -536
},
"details": {
"model": "Sonnet46",
@@ -104,8 +104,8 @@
"name": "skill1",
"type": "skill",
"position": {
- "x": -111.99999999999999,
- "y": 184
+ "x": 58.00000000000003,
+ "y": 324
},
"details": {
"kind": "skill",
@@ -118,8 +118,8 @@
"name": "skill2",
"type": "skill",
"position": {
- "x": -332,
- "y": -35.99999999999997
+ "x": -282,
+ "y": 324
},
"details": {
"kind": "skill",
diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro
index f289e11..7bc5133 100644
--- a/src/layouts/Layout.astro
+++ b/src/layouts/Layout.astro
@@ -36,15 +36,13 @@ const fullTitle =
-
+
-
-
-
+
Copilot Studio Gallery
@@ -132,7 +132,7 @@ const featuredSolutions = solutions.filter((solution) => solution.data.featured)
diff --git a/src/pages/solutions/[slug].astro b/src/pages/solutions/[slug].astro
index 122ffa3..738028a 100644
--- a/src/pages/solutions/[slug].astro
+++ b/src/pages/solutions/[slug].astro
@@ -40,7 +40,7 @@ const heroGraph = data.workflows[0]?.graph ?? data.agentGraph;
{data.name}
{data.description}
-
by {data.author}
+
by {data.author}
Version {data.version}
{updated &&
Updated {updated}}
@@ -54,7 +54,7 @@ const heroGraph = data.workflows[0]?.graph ?? data.agentGraph;
label={`${data.name} topology preview`}
variant={data.workflows.length ? "workflow" : "agent"}
compact
- client:visible
+ client:load
/>
@@ -99,7 +99,7 @@ const heroGraph = data.workflows[0]?.graph ?? data.agentGraph;
Select an agent, tool, or skill to inspect the published configuration.
-
+
{data.agents.map((agent) => (
@@ -127,7 +127,7 @@ const heroGraph = data.workflows[0]?.graph ?? data.agentGraph;
Workflow canvases
These positions and connections come from the saved designer graph in the exported solution.
-
+
diff --git a/src/styles/global.css b/src/styles/global.css
index 4081fa8..e03c911 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -67,6 +67,8 @@
--graph-content: #8764b8;
--graph-action: #ca5010;
--graph-tool: #6b69d6;
+ --graph-mcp: #5c2d91;
+ --graph-connector: #0078d4;
--graph-skill: #008272;
--graph-end: #707070;
--graph-note: #986f0b;
@@ -113,6 +115,8 @@ html[data-theme="dark"] {
--graph-content: #c6a7e2;
--graph-action: #f0a15f;
--graph-tool: #aaa7ff;
+ --graph-mcp: #c6a7e2;
+ --graph-connector: #60a5fa;
--graph-skill: #5dd5c8;
--graph-end: #adadad;
--graph-note: #f5d47a;
@@ -148,8 +152,10 @@ textarea {
font: inherit;
}
-a {
- color: inherit;
+@layer base {
+ a {
+ color: inherit;
+ }
}
:focus-visible {
@@ -180,32 +186,6 @@ a {
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}
-.studio-mark {
- position: relative;
- isolation: isolate;
- overflow: hidden;
- background: var(--cp-brand-gradient);
- box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35), 0 2px 5px rgba(78, 70, 180, 0.24);
-}
-
-.studio-mark::before,
-.studio-mark::after {
- position: absolute;
- content: "";
- border-radius: 38%;
- background: rgba(255, 255, 255, 0.72);
- mix-blend-mode: soft-light;
- transform: rotate(32deg);
-}
-
-.studio-mark::before {
- inset: 15% 48% 15% -8%;
-}
-
-.studio-mark::after {
- inset: 15% -8% 15% 48%;
-}
-
.studio-gradient-text {
background: var(--cp-brand-gradient);
background-clip: text;