showpane 0.4.14 → 0.4.15
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/bundle/meta/scaffold-manifest.json +8 -8
- package/bundle/scaffold/VERSION +1 -1
- package/bundle/scaffold/prisma/seed.ts +40 -35
- package/bundle/scaffold/src/app/(portal)/client/example/example-client.tsx +1 -2
- package/bundle/scaffold/src/app/(portal)/client/page.tsx +5 -4
- package/bundle/scaffold/src/app/page.tsx +2 -2
- package/bundle/scaffold/src/components/portal-shell.tsx +1 -1
- package/bundle/toolchain/CLI_VERSION +1 -1
- package/bundle/toolchain/VERSION +1 -1
- package/bundle/toolchain/skills/VERSION +1 -1
- package/bundle/toolchain/skills/portal-analytics/SKILL.md +9 -12
- package/bundle/toolchain/skills/portal-analytics/SKILL.md.tmpl +4 -4
- package/bundle/toolchain/skills/portal-create/SKILL.md +13 -16
- package/bundle/toolchain/skills/portal-create/SKILL.md.tmpl +8 -8
- package/bundle/toolchain/skills/portal-credentials/SKILL.md +15 -18
- package/bundle/toolchain/skills/portal-credentials/SKILL.md.tmpl +10 -10
- package/bundle/toolchain/skills/portal-delete/SKILL.md +14 -17
- package/bundle/toolchain/skills/portal-delete/SKILL.md.tmpl +9 -9
- package/bundle/toolchain/skills/portal-deploy/SKILL.md +5 -8
- package/bundle/toolchain/skills/portal-dev/SKILL.md +10 -13
- package/bundle/toolchain/skills/portal-dev/SKILL.md.tmpl +5 -5
- package/bundle/toolchain/skills/portal-list/SKILL.md +15 -18
- package/bundle/toolchain/skills/portal-list/SKILL.md.tmpl +10 -10
- package/bundle/toolchain/skills/portal-onboard/SKILL.md +50 -30
- package/bundle/toolchain/skills/portal-onboard/SKILL.md.tmpl +46 -23
- package/bundle/toolchain/skills/portal-preview/SKILL.md +16 -19
- package/bundle/toolchain/skills/portal-preview/SKILL.md.tmpl +11 -11
- package/bundle/toolchain/skills/portal-setup/SKILL.md +15 -13
- package/bundle/toolchain/skills/portal-setup/SKILL.md.tmpl +11 -6
- package/bundle/toolchain/skills/portal-share/SKILL.md +17 -20
- package/bundle/toolchain/skills/portal-share/SKILL.md.tmpl +12 -12
- package/bundle/toolchain/skills/portal-status/SKILL.md +9 -12
- package/bundle/toolchain/skills/portal-status/SKILL.md.tmpl +4 -4
- package/bundle/toolchain/skills/portal-update/SKILL.md +9 -12
- package/bundle/toolchain/skills/portal-update/SKILL.md.tmpl +4 -4
- package/bundle/toolchain/skills/portal-upgrade/SKILL.md +6 -9
- package/bundle/toolchain/skills/portal-upgrade/SKILL.md.tmpl +1 -1
- package/bundle/toolchain/skills/portal-verify/SKILL.md +6 -9
- package/bundle/toolchain/skills/portal-verify/SKILL.md.tmpl +1 -1
- package/bundle/toolchain/skills/shared/runtime-principles.md +4 -4
- package/bundle/toolchain/templates/sales-followup/sales-followup-client.tsx +1 -1
- package/dist/index.js +28 -5
- package/package.json +1 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-04-
|
|
4
|
-
"scaffoldVersion": "0.2.
|
|
3
|
+
"generatedAt": "2026-04-11T21:50:01.081Z",
|
|
4
|
+
"scaffoldVersion": "0.2.6",
|
|
5
5
|
"files": {
|
|
6
6
|
".env.example": "ed105f2bdcd1888a98181d55e3c9f7d6eff3ae9c3e2366c2e777a12e3caddfa7",
|
|
7
7
|
".gitignore": "998e5f43865ea56ac79a05acfd5d4b0d696f310bd5325a1ed458c3d40154d437",
|
|
8
|
-
"VERSION": "
|
|
8
|
+
"VERSION": "be3c6d2c6c406a64d44f0b6464a887e290416dd90c524094485b1be00936d6d7",
|
|
9
9
|
"next.config.ts": "cf27999cc274cce79bc4c8df11789807719abf40752b60e4b4967a3d2f0ed013",
|
|
10
10
|
"package-lock.json": "d8e30eb86f08e70787d4459a084b4ab2a9f119696bbd3146ec4ba5675fffd3c2",
|
|
11
11
|
"package.json": "b095e17e7fc181c630e87fe9f473c5a4ef969afcd4b110f9f9c6d6a6d93f1c0b",
|
|
12
12
|
"postcss.config.js": "fa650b380adfabb151a0b352f7135e107e6352345f899060f1c5c231228f94bf",
|
|
13
13
|
"prisma.config.ts": "36f56fd74eae70632e484443e38d08665158d72d5c978dc456651d8d5e1a636e",
|
|
14
14
|
"prisma/schema.local.prisma": "f5d6f3cb17d6d229f46ef82eef7c0ff4261596924f0173fef075ac394f423073",
|
|
15
|
-
"prisma/seed.ts": "
|
|
15
|
+
"prisma/seed.ts": "bb8eb3bc189fabbab3be83d3909afee583a5b724d258139feda22af504bed134",
|
|
16
16
|
"public/example-avatar.svg": "0edeb0d3fbefa89cc27ffe6564d20e3ee0fd073cb6d9f2a025248ef3b3f277fd",
|
|
17
17
|
"public/example-logo.svg": "bc5cd933aff2a17698dee66a7b4ea940ad12238e9d813474d643b459b1e8d6da",
|
|
18
18
|
"public/robots.txt": "331ea9090db0c9f6f597bd9840fd5b171830f6e0b3ba1cb24dfa91f0c95aedc1",
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"src/__tests__/portal-contracts.test.ts": "9562b67f84f528ee0bb0bc4c0225adaf1dcc38c59b7629bda7c44e374a020eac",
|
|
25
25
|
"src/app/(portal)/client/[slug]/page.tsx": "4f2f9253b2ad5d37a0f13759db52c786ae9c401f50fae9431da1417e9736e000",
|
|
26
26
|
"src/app/(portal)/client/[slug]/s/[token]/route.ts": "a445e54b9139e40dfe0bc039e34e6af224a27f75a614741ab224d317ad4d3ec9",
|
|
27
|
-
"src/app/(portal)/client/example/example-client.tsx": "
|
|
27
|
+
"src/app/(portal)/client/example/example-client.tsx": "ed32b111acea861f448d865338f8841d47c6ca7c2f87ed30d85bb0804940d4ec",
|
|
28
28
|
"src/app/(portal)/client/example/page.tsx": "f330864f63c9feea76c8a62c3eba3ce57578627e0d4abd929fd7fefdfc7af058",
|
|
29
29
|
"src/app/(portal)/client/layout.tsx": "4f43871510408a81da229d48ae316ec1d1c1beda93121922246300a2c8fd0999",
|
|
30
|
-
"src/app/(portal)/client/page.tsx": "
|
|
30
|
+
"src/app/(portal)/client/page.tsx": "7b4e3e5b286672f83581e24349e98ac930d8bbf5dfed02793754be2ddadf430f",
|
|
31
31
|
"src/app/api/client-auth/route.ts": "ce1858559b1e944d5b1dc719d1f03bebf66286671700b1b5397382109f0f1e0d",
|
|
32
32
|
"src/app/api/client-auth/share/route.ts": "ed82414212dcd26af8c6c0f2bd44d9d79a727ed35cfedbac8c4077a6220aad14",
|
|
33
33
|
"src/app/api/client-events/route.ts": "13d545537b7e8ce421e6169d25c105adf2a2de3d978ae0a2c6751ff5f7d2eb33",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"src/app/api/health/route.ts": "78fff55707372ce0cd6e9e49ef4f049622bc43cc42916d3f83e0162409d678b1",
|
|
39
39
|
"src/app/globals.css": "28dcda76006d0e6af01b6dcf1a315dc5b5b6931c880fc53fd6565ff09d5dd13a",
|
|
40
40
|
"src/app/layout.tsx": "c17aabeb2b486f023e777230343ace6cc06840f641a10b9dd9f65e092018f82f",
|
|
41
|
-
"src/app/page.tsx": "
|
|
41
|
+
"src/app/page.tsx": "1f71205c3ae30bf6929d37947b0c94ae53aed33b6689b7d6b13066ad51c1bc14",
|
|
42
42
|
"src/components/copy-button.tsx": "2f3d1d8a6a0a570c8d78e19c3c15519c44af17b5d8893ae5a5f57db5ecce7077",
|
|
43
43
|
"src/components/portal-login.tsx": "8b0d91bb28674e1102fd2e5b5ddcc3a93755dd806fbd3d1b2dbea2646cffca5e",
|
|
44
|
-
"src/components/portal-shell.tsx": "
|
|
44
|
+
"src/components/portal-shell.tsx": "f46a0f753a4a0318f06c8b4e46295febb84b03ea082c95057a6da50c737b4e21",
|
|
45
45
|
"src/lib/abuse-controls.ts": "d79d58d93267aca48ad0b7b9b91f753c9a3c27263e4e98daf768a950c44a6fc6",
|
|
46
46
|
"src/lib/branding.ts": "cc55f40e02bc3e486b227988f95739ca1cda8012c97b591295995eb4465efd57",
|
|
47
47
|
"src/lib/client-auth.ts": "b9bdfe77dbe5d6ec6c6a930627fc43d3253f0d76fd8fc4093af5a75742bebe42",
|
package/bundle/scaffold/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.2.
|
|
1
|
+
0.2.6
|
|
@@ -1,49 +1,54 @@
|
|
|
1
1
|
import { PrismaClient } from "@/lib/prisma-client";
|
|
2
|
-
import bcrypt from "bcryptjs";
|
|
3
2
|
|
|
4
3
|
const prisma = new PrismaClient();
|
|
5
4
|
|
|
5
|
+
function normalizeSlug(value: string): string {
|
|
6
|
+
return value
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.trim()
|
|
9
|
+
.replace(/[^a-z0-9\s-]/g, "")
|
|
10
|
+
.replace(/\s+/g, "-")
|
|
11
|
+
.replace(/-+/g, "-")
|
|
12
|
+
.replace(/^-|-$/g, "");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizeWebsiteUrl(value: string | undefined): string | null {
|
|
16
|
+
if (!value) return null;
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
if (!trimmed) return null;
|
|
19
|
+
return trimmed.startsWith("http://") || trimmed.startsWith("https://")
|
|
20
|
+
? trimmed
|
|
21
|
+
: `https://${trimmed}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
6
24
|
async function main() {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
slug: "demo",
|
|
13
|
-
contactName: "Jane Smith",
|
|
14
|
-
contactTitle: "Account Manager",
|
|
15
|
-
contactEmail: "jane@example.com",
|
|
16
|
-
supportEmail: "support@example.com",
|
|
17
|
-
websiteUrl: "https://example.com",
|
|
18
|
-
},
|
|
19
|
-
});
|
|
25
|
+
const organizationName = process.env.SHOWPANE_ORG_NAME?.trim();
|
|
26
|
+
if (!organizationName) {
|
|
27
|
+
console.log("Seed skipped: no organization details provided");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
20
30
|
|
|
21
|
-
const
|
|
31
|
+
const organizationSlug =
|
|
32
|
+
process.env.SHOWPANE_ORG_SLUG?.trim() || normalizeSlug(organizationName);
|
|
33
|
+
const contactName = process.env.SHOWPANE_CONTACT_NAME?.trim() || null;
|
|
34
|
+
const contactEmail = process.env.SHOWPANE_CONTACT_EMAIL?.trim() || null;
|
|
35
|
+
const websiteUrl = normalizeWebsiteUrl(process.env.SHOWPANE_WEBSITE_URL);
|
|
22
36
|
|
|
23
|
-
await prisma.
|
|
24
|
-
where: {
|
|
25
|
-
|
|
26
|
-
organizationId: org.id,
|
|
27
|
-
slug: "example",
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
update: {
|
|
31
|
-
companyName: "Acme Health",
|
|
32
|
-
username: "example",
|
|
33
|
-
passwordHash,
|
|
34
|
-
lastUpdated: "2 April 2026",
|
|
35
|
-
},
|
|
37
|
+
const org = await prisma.organization.upsert({
|
|
38
|
+
where: { slug: organizationSlug },
|
|
39
|
+
update: {},
|
|
36
40
|
create: {
|
|
37
|
-
|
|
38
|
-
slug:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
name: organizationName,
|
|
42
|
+
slug: organizationSlug,
|
|
43
|
+
contactName,
|
|
44
|
+
contactTitle: null,
|
|
45
|
+
contactEmail,
|
|
46
|
+
supportEmail: contactEmail,
|
|
47
|
+
websiteUrl,
|
|
43
48
|
},
|
|
44
49
|
});
|
|
45
50
|
|
|
46
|
-
console.log(
|
|
51
|
+
console.log(`Seed complete: org '${org.slug}'`);
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
main()
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Reference portal — the /portal
|
|
4
|
+
* Reference portal — the /portal-create skill reads this file as the quality
|
|
5
5
|
* and style guide when generating new portals. Keep it polished.
|
|
6
|
-
* Login: username "example", password "demo-only-password" (seeded by prisma/seed.ts)
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
import { type ReactNode } from "react";
|
|
@@ -5,14 +5,15 @@ import { PortalLogin } from "@/components/portal-login";
|
|
|
5
5
|
export default function ClientLogin() {
|
|
6
6
|
return (
|
|
7
7
|
<PortalLogin
|
|
8
|
-
companyName="
|
|
8
|
+
companyName="Your Portal"
|
|
9
9
|
companyLogo={
|
|
10
10
|
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-gray-900">
|
|
11
|
-
<span className="text-xs font-bold text-white">
|
|
11
|
+
<span className="text-xs font-bold text-white">P</span>
|
|
12
12
|
</div>
|
|
13
13
|
}
|
|
14
|
-
companyUrl="https://
|
|
15
|
-
supportEmail="support@
|
|
14
|
+
companyUrl="https://showpane.com"
|
|
15
|
+
supportEmail="support@showpane.com"
|
|
16
|
+
description="Private portal access. Sign in with the credentials you were sent."
|
|
16
17
|
/>
|
|
17
18
|
);
|
|
18
19
|
}
|
|
@@ -118,10 +118,10 @@ export default async function Home() {
|
|
|
118
118
|
Recommended
|
|
119
119
|
</p>
|
|
120
120
|
<p className="mt-3 font-mono text-sm leading-6 text-slate-700">
|
|
121
|
-
/portal
|
|
121
|
+
/portal-onboard
|
|
122
122
|
</p>
|
|
123
123
|
</div>
|
|
124
|
-
<CopyButton text="/portal
|
|
124
|
+
<CopyButton text="/portal-onboard" />
|
|
125
125
|
</div>
|
|
126
126
|
</section>
|
|
127
127
|
|
|
@@ -248,7 +248,7 @@ export function PortalShell({
|
|
|
248
248
|
<span>
|
|
249
249
|
This portal is local only. Tell Claude{" "}
|
|
250
250
|
<code className="rounded bg-white px-1.5 py-0.5 font-mono text-[11px] text-amber-950 sm:text-xs">
|
|
251
|
-
/portal
|
|
251
|
+
/portal-deploy
|
|
252
252
|
</code>{" "}
|
|
253
253
|
to publish it to Showpane Cloud.
|
|
254
254
|
</span>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.4.
|
|
1
|
+
0.4.15
|
package/bundle/toolchain/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.
|
|
1
|
+
1.1.6 (requires app >= 0.2.6)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.
|
|
1
|
+
1.1.6 (requires app >= 0.2.6)
|
|
@@ -15,7 +15,7 @@ SHOWPANE_HOME="$HOME/.showpane"
|
|
|
15
15
|
SHOWPANE_BIN="$SHOWPANE_HOME/bin"
|
|
16
16
|
CONFIG="$SHOWPANE_HOME/config.json"
|
|
17
17
|
if [ ! -f "$CONFIG" ]; then
|
|
18
|
-
echo "Showpane not configured. Run /portal
|
|
18
|
+
echo "Showpane not configured. Run /portal-setup first."
|
|
19
19
|
exit 1
|
|
20
20
|
fi
|
|
21
21
|
|
|
@@ -68,16 +68,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
|
68
68
|
|
|
69
69
|
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
70
70
|
|
|
71
|
-
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal
|
|
71
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
72
72
|
|
|
73
|
-
If `TEL_PROMPTED` is `no`,
|
|
73
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
- off — local analytics only, no remote sync
|
|
77
|
-
|
|
78
|
-
After the user chooses, run:
|
|
75
|
+
Run:
|
|
79
76
|
```bash
|
|
80
|
-
"$SHOWPANE_BIN/showpane-config" set telemetry
|
|
77
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
81
78
|
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
82
79
|
```
|
|
83
80
|
|
|
@@ -147,7 +144,7 @@ For all portals, the response includes a `portals` array with the same fields pe
|
|
|
147
144
|
|
|
148
145
|
If the script exits with a non-zero code, read stderr for the error JSON. Common errors:
|
|
149
146
|
|
|
150
|
-
- `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal
|
|
147
|
+
- `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal-list` to see available portals.
|
|
151
148
|
- `no_analytics_data`: The portal exists but has zero recorded events. This is normal for brand-new portals.
|
|
152
149
|
|
|
153
150
|
### Step 3: Format the output as an ASCII table
|
|
@@ -251,7 +248,7 @@ A portal with zero views is not necessarily a problem. Context matters:
|
|
|
251
248
|
- **New portal (created in last 7 days)**: Zero views is expected if the hosted portal has not been sent yet. Note: "Portal was created recently. Publish it first, then share hosted access with the client to start tracking engagement."
|
|
252
249
|
- **Portal with credentials but no views**: The client may not have received the hosted portal yet, or the email landed in spam. Suggest: "Credentials exist but no one has logged in. Consider publishing first or resending the hosted portal details."
|
|
253
250
|
- **Portal that previously had views but now has zero**: The client relationship may have gone cold. This is the most actionable signal -- suggest a follow-up.
|
|
254
|
-
- **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal
|
|
251
|
+
- **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal-share`.
|
|
255
252
|
|
|
256
253
|
## Telemetry
|
|
257
254
|
|
|
@@ -265,8 +262,8 @@ If telemetry is enabled, the analytics skill records a minimal event after each
|
|
|
265
262
|
|
|
266
263
|
- If the preamble fails (no config, no Prisma), stop and show the error. Do not attempt to query analytics.
|
|
267
264
|
- If `query-analytics.ts` returns a non-zero exit code, display the error message from stderr and suggest a fix.
|
|
268
|
-
- If DATABASE_URL is empty, tell the user: "No database configured. Run /portal
|
|
269
|
-
- If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal
|
|
265
|
+
- If DATABASE_URL is empty, tell the user: "No database configured. Run /portal-setup to connect your database."
|
|
266
|
+
- If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal-analytics whzan --period 7d"
|
|
270
267
|
|
|
271
268
|
## Learnings Integration
|
|
272
269
|
|
|
@@ -60,7 +60,7 @@ For all portals, the response includes a `portals` array with the same fields pe
|
|
|
60
60
|
|
|
61
61
|
If the script exits with a non-zero code, read stderr for the error JSON. Common errors:
|
|
62
62
|
|
|
63
|
-
- `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal
|
|
63
|
+
- `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal-list` to see available portals.
|
|
64
64
|
- `no_analytics_data`: The portal exists but has zero recorded events. This is normal for brand-new portals.
|
|
65
65
|
|
|
66
66
|
### Step 3: Format the output as an ASCII table
|
|
@@ -164,7 +164,7 @@ A portal with zero views is not necessarily a problem. Context matters:
|
|
|
164
164
|
- **New portal (created in last 7 days)**: Zero views is expected if the hosted portal has not been sent yet. Note: "Portal was created recently. Publish it first, then share hosted access with the client to start tracking engagement."
|
|
165
165
|
- **Portal with credentials but no views**: The client may not have received the hosted portal yet, or the email landed in spam. Suggest: "Credentials exist but no one has logged in. Consider publishing first or resending the hosted portal details."
|
|
166
166
|
- **Portal that previously had views but now has zero**: The client relationship may have gone cold. This is the most actionable signal -- suggest a follow-up.
|
|
167
|
-
- **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal
|
|
167
|
+
- **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal-share`.
|
|
168
168
|
|
|
169
169
|
## Telemetry
|
|
170
170
|
|
|
@@ -178,8 +178,8 @@ If telemetry is enabled, the analytics skill records a minimal event after each
|
|
|
178
178
|
|
|
179
179
|
- If the preamble fails (no config, no Prisma), stop and show the error. Do not attempt to query analytics.
|
|
180
180
|
- If `query-analytics.ts` returns a non-zero exit code, display the error message from stderr and suggest a fix.
|
|
181
|
-
- If DATABASE_URL is empty, tell the user: "No database configured. Run /portal
|
|
182
|
-
- If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal
|
|
181
|
+
- If DATABASE_URL is empty, tell the user: "No database configured. Run /portal-setup to connect your database."
|
|
182
|
+
- If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal-analytics whzan --period 7d"
|
|
183
183
|
|
|
184
184
|
## Learnings Integration
|
|
185
185
|
|
|
@@ -20,7 +20,7 @@ SHOWPANE_HOME="$HOME/.showpane"
|
|
|
20
20
|
SHOWPANE_BIN="$SHOWPANE_HOME/bin"
|
|
21
21
|
CONFIG="$SHOWPANE_HOME/config.json"
|
|
22
22
|
if [ ! -f "$CONFIG" ]; then
|
|
23
|
-
echo "Showpane not configured. Run /portal
|
|
23
|
+
echo "Showpane not configured. Run /portal-setup first."
|
|
24
24
|
exit 1
|
|
25
25
|
fi
|
|
26
26
|
|
|
@@ -73,16 +73,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
|
73
73
|
|
|
74
74
|
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
75
75
|
|
|
76
|
-
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal
|
|
76
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
77
77
|
|
|
78
|
-
If `TEL_PROMPTED` is `no`,
|
|
78
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
- off — local analytics only, no remote sync
|
|
82
|
-
|
|
83
|
-
After the user chooses, run:
|
|
80
|
+
Run:
|
|
84
81
|
```bash
|
|
85
|
-
"$SHOWPANE_BIN/showpane-config" set telemetry
|
|
82
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
86
83
|
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
87
84
|
```
|
|
88
85
|
|
|
@@ -104,7 +101,7 @@ If `skills/shared/platform-constraints.md` exists, read it once near the start o
|
|
|
104
101
|
|
|
105
102
|
### Step 1: Determine the portal slug
|
|
106
103
|
|
|
107
|
-
If the user provided a slug (e.g., `/portal
|
|
104
|
+
If the user provided a slug (e.g., `/portal-create acme-health`), use it. Otherwise, infer from context — the company name mentioned in conversation, a meeting transcript, or ask the user directly.
|
|
108
105
|
|
|
109
106
|
Validate the slug by running:
|
|
110
107
|
|
|
@@ -145,7 +142,7 @@ Never fail or block because Granola is unavailable. It is purely additive.
|
|
|
145
142
|
### Step 3: Template selection
|
|
146
143
|
|
|
147
144
|
Ask which template to use as a starting point. Keep this brief and practical —
|
|
148
|
-
the user chose `/portal
|
|
145
|
+
the user chose `/portal-create` because they want the fast path, not a wizard.
|
|
149
146
|
|
|
150
147
|
1. **sales-followup** — Meeting notes, next steps, documents. Best after a sales call.
|
|
151
148
|
2. **consulting** — Project overview, deliverables, timeline. Best for ongoing engagements.
|
|
@@ -286,7 +283,7 @@ Run the create-portal script to register the portal in the database:
|
|
|
286
283
|
cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/create-portal.ts" --slug <slug> --company "<client_company_name>" --org-id <org_id>
|
|
287
284
|
```
|
|
288
285
|
|
|
289
|
-
This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal
|
|
286
|
+
This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal-credentials`.
|
|
290
287
|
|
|
291
288
|
### Step 7: Self-review
|
|
292
289
|
|
|
@@ -319,7 +316,7 @@ open "http://localhost:3000/client/<slug>"
|
|
|
319
316
|
|
|
320
317
|
If not running, suggest:
|
|
321
318
|
|
|
322
|
-
> "Start the dev server with `/portal
|
|
319
|
+
> "Start the dev server with `/portal-dev` to preview your portal at http://localhost:3000/client/<slug>"
|
|
323
320
|
|
|
324
321
|
### Step 9: Summary and next steps
|
|
325
322
|
|
|
@@ -334,10 +331,10 @@ Portal created: <slug>
|
|
|
334
331
|
src/app/(portal)/client/<slug>/<slug>-client.tsx
|
|
335
332
|
|
|
336
333
|
Next steps:
|
|
337
|
-
1. Create login credentials: /portal
|
|
338
|
-
2. Preview the portal: /portal
|
|
339
|
-
3. Edit content: /portal
|
|
340
|
-
4. Deploy: /portal
|
|
334
|
+
1. Create login credentials: /portal-credentials <slug>
|
|
335
|
+
2. Preview the portal: /portal-preview <slug>
|
|
336
|
+
3. Edit content: /portal-update <slug>
|
|
337
|
+
4. Deploy: /portal-deploy
|
|
341
338
|
```
|
|
342
339
|
|
|
343
340
|
### Step 10: Record learning
|
|
@@ -17,7 +17,7 @@ capabilities, read `skills/shared/platform-constraints.md` and apply the relevan
|
|
|
17
17
|
|
|
18
18
|
### Step 1: Determine the portal slug
|
|
19
19
|
|
|
20
|
-
If the user provided a slug (e.g., `/portal
|
|
20
|
+
If the user provided a slug (e.g., `/portal-create acme-health`), use it. Otherwise, infer from context — the company name mentioned in conversation, a meeting transcript, or ask the user directly.
|
|
21
21
|
|
|
22
22
|
Validate the slug by running:
|
|
23
23
|
|
|
@@ -58,7 +58,7 @@ Never fail or block because Granola is unavailable. It is purely additive.
|
|
|
58
58
|
### Step 3: Template selection
|
|
59
59
|
|
|
60
60
|
Ask which template to use as a starting point. Keep this brief and practical —
|
|
61
|
-
the user chose `/portal
|
|
61
|
+
the user chose `/portal-create` because they want the fast path, not a wizard.
|
|
62
62
|
|
|
63
63
|
1. **sales-followup** — Meeting notes, next steps, documents. Best after a sales call.
|
|
64
64
|
2. **consulting** — Project overview, deliverables, timeline. Best for ongoing engagements.
|
|
@@ -199,7 +199,7 @@ Run the create-portal script to register the portal in the database:
|
|
|
199
199
|
cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/create-portal.ts" --slug <slug> --company "<client_company_name>" --org-id <org_id>
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal
|
|
202
|
+
This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal-credentials`.
|
|
203
203
|
|
|
204
204
|
### Step 7: Self-review
|
|
205
205
|
|
|
@@ -232,7 +232,7 @@ open "http://localhost:3000/client/<slug>"
|
|
|
232
232
|
|
|
233
233
|
If not running, suggest:
|
|
234
234
|
|
|
235
|
-
> "Start the dev server with `/portal
|
|
235
|
+
> "Start the dev server with `/portal-dev` to preview your portal at http://localhost:3000/client/<slug>"
|
|
236
236
|
|
|
237
237
|
### Step 9: Summary and next steps
|
|
238
238
|
|
|
@@ -247,10 +247,10 @@ Portal created: <slug>
|
|
|
247
247
|
src/app/(portal)/client/<slug>/<slug>-client.tsx
|
|
248
248
|
|
|
249
249
|
Next steps:
|
|
250
|
-
1. Create login credentials: /portal
|
|
251
|
-
2. Preview the portal: /portal
|
|
252
|
-
3. Edit content: /portal
|
|
253
|
-
4. Deploy: /portal
|
|
250
|
+
1. Create login credentials: /portal-credentials <slug>
|
|
251
|
+
2. Preview the portal: /portal-preview <slug>
|
|
252
|
+
3. Edit content: /portal-update <slug>
|
|
253
|
+
4. Deploy: /portal-deploy
|
|
254
254
|
```
|
|
255
255
|
|
|
256
256
|
### Step 10: Record learning
|
|
@@ -25,7 +25,7 @@ SHOWPANE_HOME="$HOME/.showpane"
|
|
|
25
25
|
SHOWPANE_BIN="$SHOWPANE_HOME/bin"
|
|
26
26
|
CONFIG="$SHOWPANE_HOME/config.json"
|
|
27
27
|
if [ ! -f "$CONFIG" ]; then
|
|
28
|
-
echo "Showpane not configured. Run /portal
|
|
28
|
+
echo "Showpane not configured. Run /portal-setup first."
|
|
29
29
|
exit 1
|
|
30
30
|
fi
|
|
31
31
|
|
|
@@ -78,16 +78,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
|
78
78
|
|
|
79
79
|
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
80
80
|
|
|
81
|
-
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal
|
|
81
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
82
82
|
|
|
83
|
-
If `TEL_PROMPTED` is `no`,
|
|
83
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
- off — local analytics only, no remote sync
|
|
87
|
-
|
|
88
|
-
After the user chooses, run:
|
|
85
|
+
Run:
|
|
89
86
|
```bash
|
|
90
|
-
"$SHOWPANE_BIN/showpane-config" set telemetry
|
|
87
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
91
88
|
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
92
89
|
```
|
|
93
90
|
|
|
@@ -109,7 +106,7 @@ If `skills/shared/platform-constraints.md` exists, read it once near the start o
|
|
|
109
106
|
|
|
110
107
|
### Step 1: Identify the portal
|
|
111
108
|
|
|
112
|
-
If the user provided a slug (e.g., `/portal
|
|
109
|
+
If the user provided a slug (e.g., `/portal-credentials acme-health`), use it. Otherwise, list available portals to help the user choose:
|
|
113
110
|
|
|
114
111
|
```bash
|
|
115
112
|
cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/list-portals.ts" --org-id <org_id>
|
|
@@ -117,9 +114,9 @@ cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PA
|
|
|
117
114
|
|
|
118
115
|
Present the list and ask which portal needs credentials. If there is only one portal, confirm it rather than asking.
|
|
119
116
|
|
|
120
|
-
Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal
|
|
117
|
+
Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal-create` to register the portal. If no DB record exists, inform the user:
|
|
121
118
|
|
|
122
|
-
> "No portal record found for '<slug>'. Run `/portal
|
|
119
|
+
> "No portal record found for '<slug>'. Run `/portal-create <slug>` first to register it."
|
|
123
120
|
|
|
124
121
|
Also check the portal's current credential status from the list output. If credentials already exist, inform the user before proceeding:
|
|
125
122
|
|
|
@@ -156,7 +153,7 @@ The script returns JSON on stdout:
|
|
|
156
153
|
|
|
157
154
|
If the script returns an error, handle it based on the error type:
|
|
158
155
|
|
|
159
|
-
- `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal
|
|
156
|
+
- `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal-create <slug>` first.
|
|
160
157
|
- `database_error` — Connection or query failure. Check DATABASE_URL and re-apply the local schema with `cd $APP_PATH && npm run prisma:db-push`.
|
|
161
158
|
- `auth_secret_missing` — The AUTH_SECRET environment variable is not set in `$APP_PATH/.env`. The rotate-credentials script needs this to function. Suggest adding `AUTH_SECRET=<random-string>` to the .env file.
|
|
162
159
|
|
|
@@ -183,7 +180,7 @@ The ASCII box ensures the credentials stand out clearly in terminal output. Do n
|
|
|
183
180
|
|
|
184
181
|
Immediately after displaying credentials, show this warning:
|
|
185
182
|
|
|
186
|
-
> **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal
|
|
183
|
+
> **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal-credentials <slug>` again to rotate to a new password.
|
|
187
184
|
|
|
188
185
|
If this was a rotation (`"rotated": true`), add:
|
|
189
186
|
|
|
@@ -196,8 +193,8 @@ Provide guidance on how to share the credentials with the client:
|
|
|
196
193
|
> **How to share with your client:**
|
|
197
194
|
> - Send the username and password via a secure channel (encrypted email, Signal, etc.)
|
|
198
195
|
> - The login page is at `/client` — the client enters the portal slug as the "company" field, then the username and password
|
|
199
|
-
> - For external access, publish the portal first with `/portal
|
|
200
|
-
> - After publish, you can use `/portal
|
|
196
|
+
> - For external access, publish the portal first with `/portal-deploy`
|
|
197
|
+
> - After publish, you can use `/portal-share <slug>` if you want a direct hosted link instead of asking the client to log in
|
|
201
198
|
|
|
202
199
|
Recommend against sharing credentials via:
|
|
203
200
|
- Unencrypted email (can be intercepted)
|
|
@@ -236,8 +233,8 @@ Credentials created for: acme-health
|
|
|
236
233
|
|
|
237
234
|
Next steps:
|
|
238
235
|
1. Send credentials to the client via a secure channel
|
|
239
|
-
2. Deploy if not already live: /portal
|
|
240
|
-
3. Optional hosted direct link after publish: /portal
|
|
236
|
+
2. Deploy if not already live: /portal-deploy
|
|
237
|
+
3. Optional hosted direct link after publish: /portal-share <slug>
|
|
241
238
|
```
|
|
242
239
|
|
|
243
240
|
### Step 9: Record credential event
|
|
@@ -259,7 +256,7 @@ echo '{"skill":"portal-credentials","key":"credentials-created","insight":"Creat
|
|
|
259
256
|
|
|
260
257
|
## Error Handling
|
|
261
258
|
|
|
262
|
-
- **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal
|
|
259
|
+
- **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal-upgrade` or checking the Showpane installation.
|
|
263
260
|
- **Prisma connection error**: DATABASE_URL may be wrong or the database may be down. Check the .env file and database status.
|
|
264
261
|
- **Permission denied on .env**: The preamble sources `$APP_PATH/.env`. If this file is not readable, the DATABASE_URL will not be set. Check file permissions.
|
|
265
262
|
- **Script timeout**: If the script takes more than 30 seconds, something is wrong. The most common cause is a database connection timeout — check network connectivity to the database host.
|
|
@@ -22,7 +22,7 @@ hooks:
|
|
|
22
22
|
|
|
23
23
|
### Step 1: Identify the portal
|
|
24
24
|
|
|
25
|
-
If the user provided a slug (e.g., `/portal
|
|
25
|
+
If the user provided a slug (e.g., `/portal-credentials acme-health`), use it. Otherwise, list available portals to help the user choose:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/list-portals.ts" --org-id <org_id>
|
|
@@ -30,9 +30,9 @@ cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PA
|
|
|
30
30
|
|
|
31
31
|
Present the list and ask which portal needs credentials. If there is only one portal, confirm it rather than asking.
|
|
32
32
|
|
|
33
|
-
Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal
|
|
33
|
+
Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal-create` to register the portal. If no DB record exists, inform the user:
|
|
34
34
|
|
|
35
|
-
> "No portal record found for '<slug>'. Run `/portal
|
|
35
|
+
> "No portal record found for '<slug>'. Run `/portal-create <slug>` first to register it."
|
|
36
36
|
|
|
37
37
|
Also check the portal's current credential status from the list output. If credentials already exist, inform the user before proceeding:
|
|
38
38
|
|
|
@@ -69,7 +69,7 @@ The script returns JSON on stdout:
|
|
|
69
69
|
|
|
70
70
|
If the script returns an error, handle it based on the error type:
|
|
71
71
|
|
|
72
|
-
- `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal
|
|
72
|
+
- `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal-create <slug>` first.
|
|
73
73
|
- `database_error` — Connection or query failure. Check DATABASE_URL and re-apply the local schema with `cd $APP_PATH && npm run prisma:db-push`.
|
|
74
74
|
- `auth_secret_missing` — The AUTH_SECRET environment variable is not set in `$APP_PATH/.env`. The rotate-credentials script needs this to function. Suggest adding `AUTH_SECRET=<random-string>` to the .env file.
|
|
75
75
|
|
|
@@ -96,7 +96,7 @@ The ASCII box ensures the credentials stand out clearly in terminal output. Do n
|
|
|
96
96
|
|
|
97
97
|
Immediately after displaying credentials, show this warning:
|
|
98
98
|
|
|
99
|
-
> **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal
|
|
99
|
+
> **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal-credentials <slug>` again to rotate to a new password.
|
|
100
100
|
|
|
101
101
|
If this was a rotation (`"rotated": true`), add:
|
|
102
102
|
|
|
@@ -109,8 +109,8 @@ Provide guidance on how to share the credentials with the client:
|
|
|
109
109
|
> **How to share with your client:**
|
|
110
110
|
> - Send the username and password via a secure channel (encrypted email, Signal, etc.)
|
|
111
111
|
> - The login page is at `/client` — the client enters the portal slug as the "company" field, then the username and password
|
|
112
|
-
> - For external access, publish the portal first with `/portal
|
|
113
|
-
> - After publish, you can use `/portal
|
|
112
|
+
> - For external access, publish the portal first with `/portal-deploy`
|
|
113
|
+
> - After publish, you can use `/portal-share <slug>` if you want a direct hosted link instead of asking the client to log in
|
|
114
114
|
|
|
115
115
|
Recommend against sharing credentials via:
|
|
116
116
|
- Unencrypted email (can be intercepted)
|
|
@@ -149,8 +149,8 @@ Credentials created for: acme-health
|
|
|
149
149
|
|
|
150
150
|
Next steps:
|
|
151
151
|
1. Send credentials to the client via a secure channel
|
|
152
|
-
2. Deploy if not already live: /portal
|
|
153
|
-
3. Optional hosted direct link after publish: /portal
|
|
152
|
+
2. Deploy if not already live: /portal-deploy
|
|
153
|
+
3. Optional hosted direct link after publish: /portal-share <slug>
|
|
154
154
|
```
|
|
155
155
|
|
|
156
156
|
### Step 9: Record credential event
|
|
@@ -172,7 +172,7 @@ echo '{"skill":"portal-credentials","key":"credentials-created","insight":"Creat
|
|
|
172
172
|
|
|
173
173
|
## Error Handling
|
|
174
174
|
|
|
175
|
-
- **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal
|
|
175
|
+
- **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal-upgrade` or checking the Showpane installation.
|
|
176
176
|
- **Prisma connection error**: DATABASE_URL may be wrong or the database may be down. Check the .env file and database status.
|
|
177
177
|
- **Permission denied on .env**: The preamble sources `$APP_PATH/.env`. If this file is not readable, the DATABASE_URL will not be set. Check file permissions.
|
|
178
178
|
- **Script timeout**: If the script takes more than 30 seconds, something is wrong. The most common cause is a database connection timeout — check network connectivity to the database host.
|