fraim 2.0.165 → 2.0.167
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/ai-hub/catalog.js +20 -27
- package/dist/src/ai-hub/server.js +418 -2
- package/dist/src/ai-hub/word-sideload.js +95 -0
- package/dist/src/cli/commands/org.js +40 -0
- package/dist/src/cli/commands/test-mcp.js +171 -0
- package/dist/src/cli/fraim.js +2 -0
- package/dist/src/cli/setup/first-run.js +242 -0
- package/dist/src/cli/utils/org-publish.js +98 -0
- package/dist/src/config/ai-manager-hiring.js +121 -0
- package/dist/src/config/compat.js +16 -0
- package/dist/src/config/feature-flags.js +25 -0
- package/dist/src/config/persona-capability-bundles.js +273 -0
- package/dist/src/config/persona-hiring.js +270 -0
- package/dist/src/config/portfolio-slug-overrides.js +17 -0
- package/dist/src/config/pricing.js +37 -0
- package/dist/src/config/stripe.js +43 -0
- package/dist/src/core/config-loader.js +9 -5
- package/dist/src/core/config-writer.js +75 -0
- package/dist/src/core/fraim-config-schema.generated.js +0 -21
- package/dist/src/core/utils/job-aliases.js +47 -0
- package/dist/src/core/utils/local-registry-resolver.js +8 -1
- package/dist/src/core/utils/workflow-parser.js +174 -0
- package/index.js +1 -1
- package/package.json +5 -1
- package/public/ai-hub/index.html +81 -0
- package/public/ai-hub/powerpoint-taskpane/index.html +236 -236
- package/public/ai-hub/powerpoint-taskpane/manifest.xml +29 -29
- package/public/ai-hub/review.css +13 -0
- package/public/ai-hub/script.js +414 -4
- package/public/ai-hub/styles.css +56 -0
- package/public/first-run/styles.css +73 -73
- package/public/portfolio/ashley.html +523 -0
- package/public/portfolio/auditya.html +83 -0
- package/public/portfolio/banke.html +83 -0
- package/public/portfolio/beza.html +659 -0
- package/public/portfolio/careena.html +632 -0
- package/public/portfolio/casey.html +568 -0
- package/public/portfolio/celia.html +490 -0
- package/public/portfolio/deidre.html +642 -0
- package/public/portfolio/gautam.html +597 -0
- package/public/portfolio/hari.html +469 -0
- package/public/portfolio/huxley.html +1354 -0
- package/public/portfolio/index.html +741 -0
- package/public/portfolio/maestro.html +518 -0
- package/public/portfolio/mandy.html +590 -0
- package/public/portfolio/mona.html +597 -0
- package/public/portfolio/pam.html +887 -0
- package/public/portfolio/procella.html +107 -0
- package/public/portfolio/qasm.html +569 -0
- package/public/portfolio/ricardo.html +489 -0
- package/public/portfolio/sade.html +560 -0
- package/public/portfolio/sam.html +654 -0
- package/public/portfolio/sechar.html +580 -0
- package/public/portfolio/sreya.html +599 -0
- package/public/portfolio/swen.html +601 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-theme="light">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>SADE · AI Salesforce Developer · FRAIM Portfolio</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
10
|
+
<style>
|
|
11
|
+
:root {
|
|
12
|
+
--accent: #0ea5e9;
|
|
13
|
+
--accent-2: #0284c7;
|
|
14
|
+
--accent-light: #e0f2fe;
|
|
15
|
+
--text: #0a2240;
|
|
16
|
+
--text-2: #334155;
|
|
17
|
+
--muted: #64748b;
|
|
18
|
+
--bg: #f0f9ff;
|
|
19
|
+
--surface: #ffffff;
|
|
20
|
+
--surface-2: #f8fafc;
|
|
21
|
+
--border: #e2e8f0;
|
|
22
|
+
--shadow: 0 4px 24px rgba(10,34,64,.08);
|
|
23
|
+
--shadow-lg: 0 12px 40px rgba(10,34,64,.14);
|
|
24
|
+
--radius: 18px;
|
|
25
|
+
--radius-sm: 10px;
|
|
26
|
+
--green: #10b981;
|
|
27
|
+
--purple: #8b5cf6;
|
|
28
|
+
--amber: #f59e0b;
|
|
29
|
+
--red: #ef4444;
|
|
30
|
+
--code-bg: #0f172a;
|
|
31
|
+
--code-border: #1e293b;
|
|
32
|
+
}
|
|
33
|
+
[data-theme="dark"] {
|
|
34
|
+
--text: #e2e8f0; --text-2: #cbd5e1; --muted: #94a3b8;
|
|
35
|
+
--bg: #06131c; --surface: #0d2035; --surface-2: #112842;
|
|
36
|
+
--border: #1e3a5f; --shadow: 0 4px 24px rgba(0,0,0,.35);
|
|
37
|
+
--shadow-lg: 0 12px 40px rgba(0,0,0,.5); --accent-light: #0c4a6e;
|
|
38
|
+
--code-bg: #020c14; --code-border: #0d2035;
|
|
39
|
+
}
|
|
40
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
41
|
+
body { font-family: 'Inter', sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; transition: background .3s, color .3s; }
|
|
42
|
+
code, pre, .mono { font-family: 'JetBrains Mono', 'Fira Code', monospace; }
|
|
43
|
+
|
|
44
|
+
.site-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 14px 32px; background: var(--surface); border-bottom: 1px solid var(--border); }
|
|
45
|
+
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; }
|
|
46
|
+
.brand-logo { width: 32px; height: 32px; border-radius: 8px; background: linear-gradient(135deg, #10b981, #059669); display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 14px; color: #fff; }
|
|
47
|
+
.brand-name { font-weight: 700; font-size: 15px; color: var(--text); }
|
|
48
|
+
.header-actions { display: flex; align-items: center; gap: 12px; }
|
|
49
|
+
.theme-btn { background: var(--surface-2); border: 1px solid var(--border); color: var(--muted); cursor: pointer; border-radius: 8px; padding: 7px 10px; font-size: 16px; }
|
|
50
|
+
|
|
51
|
+
.hero { max-width: 900px; margin: 56px auto 0; padding: 0 24px; text-align: center; }
|
|
52
|
+
.avatar-ring { display: inline-flex; align-items: center; justify-content: center; width: 96px; height: 96px; border-radius: 50%; background: linear-gradient(135deg, #0ea5e9, #6366f1); margin-bottom: 24px; box-shadow: 0 0 0 6px var(--accent-light); overflow: hidden; }
|
|
53
|
+
.avatar-initials { font-size: 28px; font-weight: 800; color: #fff; letter-spacing: -1px; font-family: 'JetBrains Mono', monospace; }
|
|
54
|
+
.role-chip { display: inline-block; background: var(--accent-light); color: #0ea5e9; border-radius: 999px; padding: 4px 14px; font-size: 12px; font-weight: 600; letter-spacing: .04em; margin-bottom: 16px; }
|
|
55
|
+
.hero h1 { font-size: clamp(32px, 5vw, 52px); font-weight: 800; color: var(--text); letter-spacing: -1.5px; line-height: 1.1; margin-bottom: 16px; }
|
|
56
|
+
.hero h1 span { color: var(--accent); }
|
|
57
|
+
.hero p { font-size: 17px; color: var(--muted); max-width: 580px; margin: 0 auto 32px; line-height: 1.7; }
|
|
58
|
+
|
|
59
|
+
.section-label { max-width: 900px; margin: 64px auto 0; padding: 0 24px; display: flex; align-items: center; gap: 12px; }
|
|
60
|
+
.section-label h2 { font-size: 13px; font-weight: 700; color: var(--muted); letter-spacing: .08em; text-transform: uppercase; }
|
|
61
|
+
.section-divider { flex: 1; height: 1px; background: var(--border); }
|
|
62
|
+
|
|
63
|
+
.cards-grid { max-width: 900px; margin: 24px auto 0; padding: 0 24px 80px; display: flex; flex-direction: column; gap: 20px; }
|
|
64
|
+
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; transition: box-shadow .2s; }
|
|
65
|
+
.card:hover { box-shadow: var(--shadow-lg); }
|
|
66
|
+
.card-header { display: flex; align-items: flex-start; gap: 16px; padding: 24px; cursor: pointer; user-select: none; }
|
|
67
|
+
.card-icon { width: 48px; height: 48px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 22px; flex-shrink: 0; }
|
|
68
|
+
.card-meta { flex: 1; min-width: 0; }
|
|
69
|
+
.card-tag { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; margin-bottom: 6px; }
|
|
70
|
+
.card-title { font-size: 18px; font-weight: 700; color: var(--text); line-height: 1.25; margin-bottom: 6px; }
|
|
71
|
+
.card-subtitle { font-size: 13px; color: var(--muted); }
|
|
72
|
+
.card-toggle { font-size: 22px; color: var(--muted); transition: transform .3s; flex-shrink: 0; align-self: center; }
|
|
73
|
+
.card.open .card-toggle { transform: rotate(90deg); }
|
|
74
|
+
.card-body { display: none; border-top: 1px solid var(--border); padding: 28px; }
|
|
75
|
+
.card.open .card-body { display: block; }
|
|
76
|
+
|
|
77
|
+
.narrative { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; margin-bottom: 28px; }
|
|
78
|
+
@media (max-width: 640px) { .narrative { grid-template-columns: 1fr; } }
|
|
79
|
+
.narrative-step { background: var(--surface-2); border-radius: var(--radius-sm); padding: 16px; }
|
|
80
|
+
.step-label { font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); margin-bottom: 6px; }
|
|
81
|
+
.step-text { font-size: 13px; color: var(--text-2); line-height: 1.6; }
|
|
82
|
+
.artifact-label { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
|
|
83
|
+
.artifact-label::before { content: ''; display: block; width: 20px; height: 2px; background: var(--accent); border-radius: 2px; }
|
|
84
|
+
.source-ref { margin-top: 16px; font-size: 12px; color: var(--muted); }
|
|
85
|
+
.source-ref a { color: var(--accent); text-decoration: none; }
|
|
86
|
+
.source-ref a:hover { text-decoration: underline; }
|
|
87
|
+
|
|
88
|
+
/* ══ ARTIFACT 1 — Salesforce Lead Routing Rules ══ */
|
|
89
|
+
.sf-panel {
|
|
90
|
+
background: var(--surface);
|
|
91
|
+
border: 1px solid #d4e3f0;
|
|
92
|
+
border-radius: 12px;
|
|
93
|
+
overflow: hidden;
|
|
94
|
+
box-shadow: 0 2px 8px rgba(14,165,233,.08);
|
|
95
|
+
}
|
|
96
|
+
.sf-panel-header {
|
|
97
|
+
background: #0176d3;
|
|
98
|
+
padding: 12px 18px;
|
|
99
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
100
|
+
color: #fff;
|
|
101
|
+
}
|
|
102
|
+
.sf-panel-title { font-size: 13px; font-weight: 700; }
|
|
103
|
+
.sf-active-badge { font-size: 11px; font-weight: 700; background: #04844b; color: #fff; border-radius: 4px; padding: 2px 8px; }
|
|
104
|
+
.sf-table { width: 100%; border-collapse: collapse; }
|
|
105
|
+
.sf-table th {
|
|
106
|
+
font-size: 11px; font-weight: 700; color: #3e3e3c; text-transform: uppercase; letter-spacing: .04em;
|
|
107
|
+
padding: 10px 16px; border-bottom: 2px solid #dddbda; text-align: left;
|
|
108
|
+
background: #f3f3f3;
|
|
109
|
+
}
|
|
110
|
+
[data-theme="dark"] .sf-table th { background: var(--surface-2); color: var(--muted); border-color: var(--border); }
|
|
111
|
+
.sf-table td {
|
|
112
|
+
font-size: 13px; color: var(--text-2); padding: 11px 16px;
|
|
113
|
+
border-bottom: 1px solid var(--border);
|
|
114
|
+
vertical-align: top;
|
|
115
|
+
}
|
|
116
|
+
.sf-table tr:last-child td { border-bottom: none; }
|
|
117
|
+
.sf-rule-name { font-weight: 700; color: #0176d3; }
|
|
118
|
+
[data-theme="dark"] .sf-rule-name { color: #38bdf8; }
|
|
119
|
+
.sf-prio-badge { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; background: #0176d3; color: #fff; font-size: 11px; font-weight: 800; }
|
|
120
|
+
.sf-criteria { font-size: 12px; color: var(--muted); font-family: 'JetBrains Mono', monospace; }
|
|
121
|
+
|
|
122
|
+
/* ══ ARTIFACT 2 — Org Health Dashboard ══ */
|
|
123
|
+
.org-health {
|
|
124
|
+
background: var(--surface-2);
|
|
125
|
+
border: 1px solid var(--border);
|
|
126
|
+
border-radius: 14px;
|
|
127
|
+
padding: 20px;
|
|
128
|
+
}
|
|
129
|
+
.org-health-title { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 4px; }
|
|
130
|
+
.org-health-sub { font-size: 12px; color: var(--muted); margin-bottom: 16px; }
|
|
131
|
+
.org-stats-grid {
|
|
132
|
+
display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-bottom: 18px;
|
|
133
|
+
}
|
|
134
|
+
@media (max-width: 480px) { .org-stats-grid { grid-template-columns: 1fr; } }
|
|
135
|
+
.org-stat-card {
|
|
136
|
+
background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px;
|
|
137
|
+
}
|
|
138
|
+
.org-stat-num { font-size: 22px; font-weight: 800; color: var(--text); margin-bottom: 2px; font-family: 'JetBrains Mono', monospace; }
|
|
139
|
+
.org-stat-label { font-size: 12px; font-weight: 600; color: var(--text-2); margin-bottom: 4px; }
|
|
140
|
+
.org-stat-sub { font-size: 11px; color: var(--muted); }
|
|
141
|
+
.org-stat-sub strong { color: #ef4444; }
|
|
142
|
+
.org-load-impact {
|
|
143
|
+
background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px; margin-bottom: 14px;
|
|
144
|
+
}
|
|
145
|
+
.org-load-label { font-size: 12px; font-weight: 700; color: var(--text-2); margin-bottom: 10px; }
|
|
146
|
+
.org-load-row { display: flex; align-items: center; gap: 10px; }
|
|
147
|
+
.org-load-before { font-size: 12px; color: #ef4444; font-weight: 700; white-space: nowrap; }
|
|
148
|
+
.org-load-after { font-size: 12px; color: #10b981; font-weight: 700; white-space: nowrap; }
|
|
149
|
+
.org-load-bar-wrap { flex: 1; position: relative; height: 12px; background: #fee2e2; border-radius: 6px; overflow: hidden; }
|
|
150
|
+
.org-load-bar-fill { height: 100%; background: linear-gradient(90deg, #10b981, #0ea5e9); border-radius: 6px; }
|
|
151
|
+
.org-score-row {
|
|
152
|
+
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
|
153
|
+
}
|
|
154
|
+
.org-score-ring {
|
|
155
|
+
width: 64px; height: 64px; border-radius: 50%; flex-shrink: 0;
|
|
156
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
157
|
+
border: 4px solid #0ea5e9;
|
|
158
|
+
}
|
|
159
|
+
.org-score-val { font-size: 16px; font-weight: 800; color: #0ea5e9; line-height: 1; }
|
|
160
|
+
.org-score-max { font-size: 9px; color: var(--muted); }
|
|
161
|
+
.org-score-text { font-size: 13px; color: var(--text-2); line-height: 1.5; }
|
|
162
|
+
.org-score-text strong { color: var(--text); }
|
|
163
|
+
|
|
164
|
+
/* ══ ARTIFACT 3 — ARR Dashboard ══ */
|
|
165
|
+
.arr-dashboard {
|
|
166
|
+
background: var(--surface);
|
|
167
|
+
border: 1px solid var(--border);
|
|
168
|
+
border-radius: 14px;
|
|
169
|
+
overflow: hidden;
|
|
170
|
+
}
|
|
171
|
+
.arr-header {
|
|
172
|
+
background: #0d2035;
|
|
173
|
+
padding: 14px 18px;
|
|
174
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
175
|
+
}
|
|
176
|
+
.arr-header-title { font-size: 14px; font-weight: 700; color: #e2e8f0; }
|
|
177
|
+
.arr-live { display: flex; align-items: center; gap: 6px; }
|
|
178
|
+
.arr-live-dot { width: 8px; height: 8px; border-radius: 50%; background: #4ade80; }
|
|
179
|
+
.arr-live-text { font-size: 11px; color: #4ade80; font-weight: 700; }
|
|
180
|
+
.arr-kpi-row {
|
|
181
|
+
display: grid; grid-template-columns: repeat(4, 1fr); gap: 0;
|
|
182
|
+
border-bottom: 1px solid var(--border);
|
|
183
|
+
}
|
|
184
|
+
@media (max-width: 540px) { .arr-kpi-row { grid-template-columns: repeat(2, 1fr); } }
|
|
185
|
+
.arr-kpi {
|
|
186
|
+
padding: 16px; text-align: center;
|
|
187
|
+
border-right: 1px solid var(--border);
|
|
188
|
+
}
|
|
189
|
+
.arr-kpi:last-child { border-right: none; }
|
|
190
|
+
.arr-kpi-val { font-size: 20px; font-weight: 800; color: var(--text); margin-bottom: 2px; font-family: 'JetBrains Mono', monospace; }
|
|
191
|
+
.arr-kpi-label { font-size: 10px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin-bottom: 4px; }
|
|
192
|
+
.arr-kpi-delta { font-size: 11px; font-weight: 700; }
|
|
193
|
+
.delta-up { color: #10b981; }
|
|
194
|
+
.delta-down { color: #ef4444; }
|
|
195
|
+
.arr-chart-section { padding: 18px; }
|
|
196
|
+
.arr-chart-label { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 14px; }
|
|
197
|
+
.arr-chart-bars { display: flex; align-items: flex-end; gap: 8px; height: 80px; }
|
|
198
|
+
.arr-bar-wrap { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; justify-content: flex-end; }
|
|
199
|
+
.arr-bar { width: 100%; border-radius: 4px 4px 0 0; background: linear-gradient(180deg, #0ea5e9, #0284c7); transition: height .3s; }
|
|
200
|
+
.arr-bar-month { font-size: 10px; color: var(--muted); font-weight: 600; }
|
|
201
|
+
|
|
202
|
+
/* Footer */
|
|
203
|
+
.portfolio-footer { background: var(--surface); border-top: 1px solid var(--border); padding: 40px 24px; text-align: center; }
|
|
204
|
+
.footer-sub { margin-top: 20px; font-size: 12px; color: var(--muted); }
|
|
205
|
+
.footer-sub a { color: var(--accent); text-decoration: none; }
|
|
206
|
+
|
|
207
|
+
@media (max-width: 640px) {
|
|
208
|
+
.site-header { padding: 12px 16px; }
|
|
209
|
+
.hero { margin-top: 36px; }
|
|
210
|
+
.cards-grid { padding: 0 16px 60px; }
|
|
211
|
+
.card-header { padding: 18px; }
|
|
212
|
+
.card-body { padding: 18px; }
|
|
213
|
+
.section-label { margin-top: 40px; padding: 0 16px; }
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
216
|
+
</head>
|
|
217
|
+
<body>
|
|
218
|
+
|
|
219
|
+
<header class="site-header">
|
|
220
|
+
<a class="brand" href="/">
|
|
221
|
+
<div class="brand-logo">F</div>
|
|
222
|
+
<span class="brand-name">FRAIM</span>
|
|
223
|
+
</a>
|
|
224
|
+
<div class="header-actions">
|
|
225
|
+
<button class="theme-btn" onclick="toggleTheme()" title="Toggle dark mode">☾</button>
|
|
226
|
+
</div>
|
|
227
|
+
</header>
|
|
228
|
+
|
|
229
|
+
<section class="hero">
|
|
230
|
+
<div class="avatar-ring">
|
|
231
|
+
<img src="https://api.dicebear.com/9.x/notionists/svg?seed=SADE-salesforce&backgroundColor=bae6fd&radius=50" width="96" height="96" alt="SADE-salesforce avatar" style="border-radius:50%;">
|
|
232
|
+
</div>
|
|
233
|
+
<div class="role-chip">AI Salesforce Developer</div>
|
|
234
|
+
<h1>Clean orgs.<br><span>Automations</span> that actually run.</h1>
|
|
235
|
+
<p>Reports that tell the truth.</p>
|
|
236
|
+
</section>
|
|
237
|
+
|
|
238
|
+
<div class="section-label">
|
|
239
|
+
<h2>Selected Work</h2>
|
|
240
|
+
<div class="section-divider"></div>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
<div class="cards-grid">
|
|
244
|
+
|
|
245
|
+
<!-- Card 1: Lead Routing Automation -->
|
|
246
|
+
<div class="card open" id="card1">
|
|
247
|
+
<div class="card-header" onclick="toggleCard(1)">
|
|
248
|
+
<div class="card-icon" style="background:#e0f2fe;">⚡</div>
|
|
249
|
+
<div class="card-meta">
|
|
250
|
+
<div class="card-tag" style="color:#0ea5e9;">Salesforce Automation</div>
|
|
251
|
+
<div class="card-title">0-touch lead routing — right rep, right lead, every time</div>
|
|
252
|
+
<div class="card-subtitle">Salesforce · Lead Assignment Rules · Account Segmentation</div>
|
|
253
|
+
</div>
|
|
254
|
+
<div class="card-toggle">›</div>
|
|
255
|
+
</div>
|
|
256
|
+
<div class="card-body">
|
|
257
|
+
<div class="narrative">
|
|
258
|
+
<div class="narrative-step">
|
|
259
|
+
<div class="step-label">Context</div>
|
|
260
|
+
<div class="step-text"><em>A B2B sales team of 12 reps was manually routing 200+ monthly inbound leads, with senior reps getting easy leads and junior reps getting enterprise accounts — backwards from optimal.</em></div>
|
|
261
|
+
</div>
|
|
262
|
+
<div class="narrative-step">
|
|
263
|
+
<div class="step-label">The Broken State</div>
|
|
264
|
+
<div class="step-text">The existing routing was round-robin by default. Enterprise accounts ($500K+ ACV) landed on a junior rep if they happened to be next in rotation. High-velocity SMB leads (close rate 40% in week 1) went cold waiting for senior reps to clear their enterprise pipeline.</div>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="narrative-step">
|
|
267
|
+
<div class="step-label">What SADE Did</div>
|
|
268
|
+
<div class="step-text">A multi-criteria assignment rule in Salesforce: segment by annual revenue (> $1M → Enterprise team), employee count (> 500 → Strategic team), source (inbound web = SDR, referral = AE direct), and lead score (> 80 = immediate high-touch). Rules fire on creation — zero rep intervention required.</div>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
<div class="narrative" style="margin-top:-12px;">
|
|
272
|
+
<div class="narrative-step" style="grid-column: 1 / -1;">
|
|
273
|
+
<div class="step-label">The Outcome</div>
|
|
274
|
+
<div class="step-text">Lead-to-contact conversion rose 28% in Q1 after deployment. Enterprise account misrouting dropped to 0%. Senior AE capacity freed by 6 hours/week previously spent on re-routing.</div>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
<div class="artifact-label">Live Artifact — Salesforce Lead Assignment Rules</div>
|
|
279
|
+
|
|
280
|
+
<div class="sf-panel">
|
|
281
|
+
<div class="sf-panel-header">
|
|
282
|
+
<span class="sf-panel-title">Lead Assignment Rules — Active</span>
|
|
283
|
+
<span class="sf-active-badge">● Active</span>
|
|
284
|
+
</div>
|
|
285
|
+
<table class="sf-table">
|
|
286
|
+
<thead>
|
|
287
|
+
<tr>
|
|
288
|
+
<th>Priority</th>
|
|
289
|
+
<th>Rule Name</th>
|
|
290
|
+
<th>Criteria</th>
|
|
291
|
+
<th>Assign To</th>
|
|
292
|
+
</tr>
|
|
293
|
+
</thead>
|
|
294
|
+
<tbody>
|
|
295
|
+
<tr>
|
|
296
|
+
<td><span class="sf-prio-badge">1</span></td>
|
|
297
|
+
<td><span class="sf-rule-name">Enterprise Accounts</span></td>
|
|
298
|
+
<td><span class="sf-criteria">Revenue > $1M OR Employees > 500</span></td>
|
|
299
|
+
<td>Enterprise Team</td>
|
|
300
|
+
</tr>
|
|
301
|
+
<tr>
|
|
302
|
+
<td><span class="sf-prio-badge">2</span></td>
|
|
303
|
+
<td><span class="sf-rule-name">High-Score SDR</span></td>
|
|
304
|
+
<td><span class="sf-criteria">Lead Score > 80 AND Source = Web</span></td>
|
|
305
|
+
<td>SDR Queue</td>
|
|
306
|
+
</tr>
|
|
307
|
+
<tr>
|
|
308
|
+
<td><span class="sf-prio-badge">3</span></td>
|
|
309
|
+
<td><span class="sf-rule-name">Referral Direct</span></td>
|
|
310
|
+
<td><span class="sf-criteria">Source = Referral</span></td>
|
|
311
|
+
<td>Sr. AE (Round Robin)</td>
|
|
312
|
+
</tr>
|
|
313
|
+
<tr>
|
|
314
|
+
<td><span class="sf-prio-badge" style="background:#64748b;">4</span></td>
|
|
315
|
+
<td><span class="sf-rule-name">Default SMB</span></td>
|
|
316
|
+
<td><span class="sf-criteria">All others</span></td>
|
|
317
|
+
<td>SMB Team</td>
|
|
318
|
+
</tr>
|
|
319
|
+
</tbody>
|
|
320
|
+
</table>
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
<div class="source-ref">
|
|
324
|
+
📎 Source: <a href="#">Salesforce · Lead Assignment Rules · Setup > Lead Assignment Rules</a>
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<!-- Card 2: Org Health Audit -->
|
|
330
|
+
<div class="card" id="card2">
|
|
331
|
+
<div class="card-header" onclick="toggleCard(2)">
|
|
332
|
+
<div class="card-icon" style="background:#fef9c3;">🏥</div>
|
|
333
|
+
<div class="card-meta">
|
|
334
|
+
<div class="card-tag" style="color:#0ea5e9;">Org Governance</div>
|
|
335
|
+
<div class="card-title">847 inactive fields. Gone.</div>
|
|
336
|
+
<div class="card-subtitle">Salesforce · sf-org-health-check · metadata cleanup</div>
|
|
337
|
+
</div>
|
|
338
|
+
<div class="card-toggle">›</div>
|
|
339
|
+
</div>
|
|
340
|
+
<div class="card-body">
|
|
341
|
+
<div class="narrative">
|
|
342
|
+
<div class="narrative-step">
|
|
343
|
+
<div class="step-label">Context</div>
|
|
344
|
+
<div class="step-text"><em>A 5-year-old Salesforce org had accumulated 1,200+ custom fields, 340 workflow rules (200 inactive), and a page layout that took 8 seconds to load.</em></div>
|
|
345
|
+
</div>
|
|
346
|
+
<div class="narrative-step">
|
|
347
|
+
<div class="step-label">The Hidden Debt</div>
|
|
348
|
+
<div class="step-text">Technical debt in Salesforce is invisible until it causes pain: slow page loads, confused reps who can't find the right fields, and automation conflicts when legacy workflow rules fire alongside new Flow rules. Nobody had audited the org in 3 years.</div>
|
|
349
|
+
</div>
|
|
350
|
+
<div class="narrative-step">
|
|
351
|
+
<div class="step-label">What SADE Did</div>
|
|
352
|
+
<div class="step-text">SADE ran the org health audit: exported all custom field metadata, filtered for fields with 0 usage in the last 365 days (847 fields), cross-referenced with active page layouts to identify safe deletes, and exported inactive workflow rules for review. Provided a phased cleanup plan: delete null-usage fields in sprint 1, deactivate redundant WFRs in sprint 2, migrate active WFRs to Flow in sprint 3.</div>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
<div class="narrative" style="margin-top:-12px;">
|
|
356
|
+
<div class="narrative-step" style="grid-column: 1 / -1;">
|
|
357
|
+
<div class="step-label">The Outcome</div>
|
|
358
|
+
<div class="step-text">Page load time dropped from 8.2s to 1.9s after sprint 1. Reps reported finding the fields they needed on first scroll (vs. searching previously). Sprint 2 deactivated 200 workflow rules with zero business logic loss.</div>
|
|
359
|
+
</div>
|
|
360
|
+
</div>
|
|
361
|
+
|
|
362
|
+
<div class="artifact-label">Live Artifact — Org Health Dashboard</div>
|
|
363
|
+
|
|
364
|
+
<div class="org-health">
|
|
365
|
+
<div class="org-health-title">Salesforce Org Health — Pre/Post Cleanup</div>
|
|
366
|
+
<div class="org-health-sub">sf-org-health-check · metadata/CustomField__c · 5-year-old org</div>
|
|
367
|
+
<div class="org-stats-grid">
|
|
368
|
+
<div class="org-stat-card">
|
|
369
|
+
<div class="org-stat-num">1,247</div>
|
|
370
|
+
<div class="org-stat-label">Custom Fields</div>
|
|
371
|
+
<div class="org-stat-sub"><strong>847 unused</strong> = 68% can be deleted</div>
|
|
372
|
+
</div>
|
|
373
|
+
<div class="org-stat-card">
|
|
374
|
+
<div class="org-stat-num">340</div>
|
|
375
|
+
<div class="org-stat-label">Workflow Rules</div>
|
|
376
|
+
<div class="org-stat-sub"><strong>200 inactive</strong> = 59% ready to deactivate</div>
|
|
377
|
+
</div>
|
|
378
|
+
<div class="org-stat-card">
|
|
379
|
+
<div class="org-stat-num">24</div>
|
|
380
|
+
<div class="org-stat-label">Page Layouts</div>
|
|
381
|
+
<div class="org-stat-sub">8 oversized (>50 fields/section)</div>
|
|
382
|
+
</div>
|
|
383
|
+
<div class="org-stat-card">
|
|
384
|
+
<div class="org-stat-num">156</div>
|
|
385
|
+
<div class="org-stat-label">Apex Classes</div>
|
|
386
|
+
<div class="org-stat-sub">23 with 0% test coverage</div>
|
|
387
|
+
</div>
|
|
388
|
+
</div>
|
|
389
|
+
<div class="org-load-impact">
|
|
390
|
+
<div class="org-load-label">Cleanup Impact — Page Load Time</div>
|
|
391
|
+
<div class="org-load-row">
|
|
392
|
+
<span class="org-load-before">Before: 8.2s</span>
|
|
393
|
+
<div class="org-load-bar-wrap">
|
|
394
|
+
<div class="org-load-bar-fill" style="width:23.2%;"></div>
|
|
395
|
+
</div>
|
|
396
|
+
<span class="org-load-after">After: 1.9s</span>
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
399
|
+
<div class="org-score-row">
|
|
400
|
+
<div>
|
|
401
|
+
<div style="font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px;">Before cleanup</div>
|
|
402
|
+
<div class="org-score-ring" style="border-color:#ef4444;">
|
|
403
|
+
<div class="org-score-val" style="color:#ef4444;">47</div>
|
|
404
|
+
<div class="org-score-max">/100</div>
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
<div style="font-size:24px;color:var(--muted);padding-top:20px;">→</div>
|
|
408
|
+
<div>
|
|
409
|
+
<div style="font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px;">After cleanup</div>
|
|
410
|
+
<div class="org-score-ring" style="border-color:#10b981;">
|
|
411
|
+
<div class="org-score-val" style="color:#10b981;">78</div>
|
|
412
|
+
<div class="org-score-max">/100</div>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
<div class="org-score-text">
|
|
416
|
+
<strong>+31 point improvement</strong> in org health score.<br>
|
|
417
|
+
Sprint 1 alone recovered 76% of the gain<br>
|
|
418
|
+
by eliminating unused field metadata.
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
421
|
+
</div>
|
|
422
|
+
|
|
423
|
+
<div class="source-ref">
|
|
424
|
+
📎 Source: <a href="#">Salesforce · sf-org-health-check · metadata/CustomField__c</a>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
|
|
429
|
+
<!-- Card 3: Revenue Dashboard Build -->
|
|
430
|
+
<div class="card" id="card3">
|
|
431
|
+
<div class="card-header" onclick="toggleCard(3)">
|
|
432
|
+
<div class="card-icon" style="background:#e0f2fe;">📊</div>
|
|
433
|
+
<div class="card-meta">
|
|
434
|
+
<div class="card-tag" style="color:#0ea5e9;">Analytics</div>
|
|
435
|
+
<div class="card-title">The CFO stopped asking for spreadsheets</div>
|
|
436
|
+
<div class="card-subtitle">Salesforce · Reports & Dashboards · ARR Analytics</div>
|
|
437
|
+
</div>
|
|
438
|
+
<div class="card-toggle">›</div>
|
|
439
|
+
</div>
|
|
440
|
+
<div class="card-body">
|
|
441
|
+
<div class="narrative">
|
|
442
|
+
<div class="narrative-step">
|
|
443
|
+
<div class="step-label">Context</div>
|
|
444
|
+
<div class="step-text"><em>A SaaS CFO was manually assembling a monthly revenue report from 4 Salesforce report exports, one Stripe CSV, and a Google Sheet — a 4-hour task performed every month.</em></div>
|
|
445
|
+
</div>
|
|
446
|
+
<div class="narrative-step">
|
|
447
|
+
<div class="step-label">The Data Problem</div>
|
|
448
|
+
<div class="step-text">Data lived in three places. None of them talked to each other. The CFO's "source of truth" was a manually maintained Google Sheet that was outdated by definition — built from last month's exports, reviewed this month.</div>
|
|
449
|
+
</div>
|
|
450
|
+
<div class="narrative-step">
|
|
451
|
+
<div class="step-label">What SADE Did</div>
|
|
452
|
+
<div class="step-text">A real-time ARR dashboard in Salesforce: MRR from closed-won opportunities grouped by product line, churn from closed-lost/downgrade opportunities, expansion from upgrade opportunities, and net ARR trend by month. All sourced from Opportunity records — no export, no manual step. Drill-down by segment, rep, and product.</div>
|
|
453
|
+
</div>
|
|
454
|
+
</div>
|
|
455
|
+
<div class="narrative" style="margin-top:-12px;">
|
|
456
|
+
<div class="narrative-step" style="grid-column: 1 / -1;">
|
|
457
|
+
<div class="step-label">The Outcome</div>
|
|
458
|
+
<div class="step-text">The CFO decommissioned her monthly spreadsheet ritual after the dashboard launched. Board prep time reduced from 1.5 days to 3 hours. First investor deck built entirely from Salesforce dashboard screenshots.</div>
|
|
459
|
+
</div>
|
|
460
|
+
</div>
|
|
461
|
+
|
|
462
|
+
<div class="artifact-label">Live Artifact — ARR Dashboard</div>
|
|
463
|
+
|
|
464
|
+
<div class="arr-dashboard">
|
|
465
|
+
<div class="arr-header">
|
|
466
|
+
<span class="arr-header-title">ARR Dashboard — FY2026</span>
|
|
467
|
+
<div class="arr-live">
|
|
468
|
+
<div class="arr-live-dot"></div>
|
|
469
|
+
<span class="arr-live-text">Live</span>
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
<div class="arr-kpi-row">
|
|
473
|
+
<div class="arr-kpi">
|
|
474
|
+
<div class="arr-kpi-label">MRR</div>
|
|
475
|
+
<div class="arr-kpi-val">$487K</div>
|
|
476
|
+
<div class="arr-kpi-delta delta-up">▲ +12% MoM</div>
|
|
477
|
+
</div>
|
|
478
|
+
<div class="arr-kpi">
|
|
479
|
+
<div class="arr-kpi-label">Churn Rate</div>
|
|
480
|
+
<div class="arr-kpi-val">2.1%</div>
|
|
481
|
+
<div class="arr-kpi-delta delta-up">▼ -0.3%</div>
|
|
482
|
+
</div>
|
|
483
|
+
<div class="arr-kpi">
|
|
484
|
+
<div class="arr-kpi-label">Net ARR</div>
|
|
485
|
+
<div class="arr-kpi-val">$5.84M</div>
|
|
486
|
+
<div class="arr-kpi-delta delta-up">▲ +$420K</div>
|
|
487
|
+
</div>
|
|
488
|
+
<div class="arr-kpi">
|
|
489
|
+
<div class="arr-kpi-label">NRR</div>
|
|
490
|
+
<div class="arr-kpi-val">118%</div>
|
|
491
|
+
<div class="arr-kpi-delta delta-up">▲ +3 pts</div>
|
|
492
|
+
</div>
|
|
493
|
+
</div>
|
|
494
|
+
<div class="arr-chart-section">
|
|
495
|
+
<div class="arr-chart-label">ARR Growth — Jan–Jun FY2026</div>
|
|
496
|
+
<div class="arr-chart-bars">
|
|
497
|
+
<div class="arr-bar-wrap">
|
|
498
|
+
<div class="arr-bar" style="height:42%;opacity:.7;"></div>
|
|
499
|
+
<div class="arr-bar-month">Jan</div>
|
|
500
|
+
</div>
|
|
501
|
+
<div class="arr-bar-wrap">
|
|
502
|
+
<div class="arr-bar" style="height:52%;opacity:.75;"></div>
|
|
503
|
+
<div class="arr-bar-month">Feb</div>
|
|
504
|
+
</div>
|
|
505
|
+
<div class="arr-bar-wrap">
|
|
506
|
+
<div class="arr-bar" style="height:60%;opacity:.8;"></div>
|
|
507
|
+
<div class="arr-bar-month">Mar</div>
|
|
508
|
+
</div>
|
|
509
|
+
<div class="arr-bar-wrap">
|
|
510
|
+
<div class="arr-bar" style="height:72%;opacity:.85;"></div>
|
|
511
|
+
<div class="arr-bar-month">Apr</div>
|
|
512
|
+
</div>
|
|
513
|
+
<div class="arr-bar-wrap">
|
|
514
|
+
<div class="arr-bar" style="height:84%;opacity:.92;"></div>
|
|
515
|
+
<div class="arr-bar-month">May</div>
|
|
516
|
+
</div>
|
|
517
|
+
<div class="arr-bar-wrap">
|
|
518
|
+
<div class="arr-bar" style="height:100%;"></div>
|
|
519
|
+
<div class="arr-bar-month">Jun</div>
|
|
520
|
+
</div>
|
|
521
|
+
</div>
|
|
522
|
+
</div>
|
|
523
|
+
</div>
|
|
524
|
+
|
|
525
|
+
<div class="source-ref">
|
|
526
|
+
📎 Source: <a href="#">Salesforce · Reports & Dashboards · ARR_Dashboard_v3</a>
|
|
527
|
+
</div>
|
|
528
|
+
</div>
|
|
529
|
+
</div>
|
|
530
|
+
|
|
531
|
+
</div>
|
|
532
|
+
|
|
533
|
+
<footer class="portfolio-footer">
|
|
534
|
+
<div class="footer-sub">
|
|
535
|
+
Part of the <a href="/">FRAIM</a> · 18 AI employees available ·
|
|
536
|
+
<a href="/">Back to FRAIM</a>
|
|
537
|
+
</div>
|
|
538
|
+
</footer>
|
|
539
|
+
|
|
540
|
+
<script>
|
|
541
|
+
function toggleTheme() {
|
|
542
|
+
const html = document.documentElement;
|
|
543
|
+
const isDark = html.getAttribute('data-theme') === 'dark';
|
|
544
|
+
html.setAttribute('data-theme', isDark ? 'light' : 'dark');
|
|
545
|
+
document.querySelector('.theme-btn').textContent = isDark ? '☾' : '☀';
|
|
546
|
+
}
|
|
547
|
+
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
548
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
549
|
+
document.querySelector('.theme-btn').textContent = '☀';
|
|
550
|
+
}
|
|
551
|
+
function toggleCard(num) {
|
|
552
|
+
const card = document.getElementById('card' + num);
|
|
553
|
+
const isOpen = card.classList.contains('open');
|
|
554
|
+
document.querySelectorAll('.card').forEach(c => c.classList.remove('open'));
|
|
555
|
+
if (!isOpen) { card.classList.add('open'); card.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }
|
|
556
|
+
}
|
|
557
|
+
</script>
|
|
558
|
+
|
|
559
|
+
</body>
|
|
560
|
+
</html>
|