Skip to content

Commit 73ebffa

Browse files
committed
Match business campaign landings to specific workflows and track meaningful starts
1 parent 2c05461 commit 73ebffa

4 files changed

Lines changed: 321 additions & 114 deletions

File tree

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import {EXAMPLES, type Brief} from './_brief';
2+
3+
export const LANDING_VERSION = 'business-2026-10-26-v1';
4+
5+
export type BusinessVariant = {
6+
id: string;
7+
campaign: string;
8+
label: string;
9+
heading: string;
10+
description: string;
11+
cta: string;
12+
recordType: string;
13+
records: {id: string; name: string; stage: string; owner: string; due: string; attention?: boolean}[];
14+
question: string;
15+
answer: string;
16+
operation: string;
17+
result: string;
18+
brief: Brief;
19+
prompts: string[];
20+
};
21+
22+
export const BUSINESS_VARIANTS: BusinessVariant[] = [
23+
{
24+
id: 'spreadsheet', campaign: 'business_sheet_to_app', label: 'Spreadsheet to business app',
25+
heading: 'Your business has outgrown the spreadsheet.',
26+
description: 'Turn your spreadsheet process into your own app. Your coding agent builds it with AdminForth: shared records, clear owners and next steps.',
27+
cta: 'Start my business app', recordType: 'Customer orders',
28+
records: [
29+
{id: 'ORD-1042', name: 'Harbor Café · equipment order', stage: 'Needs follow-up', owner: 'Maya', due: 'Yesterday', attention: true},
30+
{id: 'ORD-1043', name: 'Atlas Office · supplies', stage: 'Preparing', owner: 'Tom', due: 'Today'},
31+
{id: 'ORD-1044', name: 'Brightside School · replacement parts', stage: 'Ready to deliver', owner: 'Priya', due: 'Tomorrow'},
32+
],
33+
question: 'Which orders need a next action today?',
34+
answer: 'Harbor Café’s order is overdue. Maya owns it. No next action.',
35+
operation: 'Ask Maya to confirm the delivery date today.',
36+
result: 'Saved on the order. Everyone sees the same next step.',
37+
brief: {...EXAMPLES.orders, manage: 'The customer and order process we currently run in a spreadsheet'},
38+
prompts: ['Which orders need a next action today?', 'Show the customer, owner and current stage for ORD-1042.', 'Ask Maya to confirm the delivery date today.', 'Show orders with missing owners or dates.', 'Who last changed the stage of ORD-1042?'],
39+
},
40+
{
41+
id: 'followups', campaign: 'business_quote_followups', label: 'Customer follow-ups',
42+
heading: 'Quotes sent. Follow-ups forgotten?',
43+
description: 'A good quote should not die in a spreadsheet. Build your own follow-up app with AdminForth and your coding agent. Every quote gets an owner and a next step.',
44+
cta: 'Start my follow-up app', recordType: 'Quote follow-ups',
45+
records: [
46+
{id: 'REQ-1042', name: 'Harbor Café · maintenance quote', stage: 'Follow-up overdue', owner: 'Maya', due: 'Yesterday', attention: true},
47+
{id: 'REQ-1043', name: 'Atlas Office · service proposal', stage: 'Call scheduled', owner: 'Tom', due: 'Today'},
48+
{id: 'REQ-1044', name: 'Brightside School · inspection quote', stage: 'Awaiting reply', owner: 'Priya', due: 'Tomorrow'},
49+
],
50+
question: 'Which quotes have overdue follow-ups, and whose are they?',
51+
answer: 'Harbor Café’s quote is overdue for a follow-up. Owner: Maya.',
52+
operation: 'Maya: call Harbor Café today at 14:00.',
53+
result: 'The call and due time are saved on the quote.',
54+
brief: EXAMPLES.followups,
55+
prompts: ['Which quotes have overdue follow-ups, and whose are they?', 'Show quotes waiting for a reply with no next action.', 'Maya: call Harbor Café today at 14:00.', 'Which customers does Tom need to contact today?', 'Show the last change to REQ-1042.'],
56+
},
57+
{
58+
id: 'live_records', campaign: 'business_live_records', label: 'Live business records',
59+
heading: 'Stop uploading yesterday’s business data to AI.',
60+
description: 'Still exporting files for AI, then copying changes back? Build an AdminForth app your agent can read and update directly, with your team’s access rules.',
61+
cta: 'Start my connected app', recordType: 'Live business records',
62+
records: [
63+
{id: 'REQ-1042', name: 'Harbor Café · service request', stage: 'Next action missing', owner: 'Maya', due: 'Today', attention: true},
64+
{id: 'REQ-1043', name: 'Atlas Office · site visit', stage: 'Visit confirmed', owner: 'Tom', due: 'Tomorrow'},
65+
{id: 'REQ-1044', name: 'Brightside School · inspection', stage: 'Quote sent', owner: 'Priya', due: 'Thursday'},
66+
],
67+
question: 'Read my current requests. Which ones have no next action?',
68+
answer: 'Harbor Café’s request has no next action. Owner: Maya.',
69+
operation: 'Maya: confirm the visit time today.',
70+
result: 'Saved in your app. Your team and agent see the update.',
71+
brief: {...EXAMPLES.followups, missed: 'I keep exporting a spreadsheet to AI and copying changes back. I want my agent to read and update the same current records my team uses.', details: 'Build customer requests with owner, status, next action and due date. Connect my agent through MCP. Show a permitted update and an action refused by the server.'},
72+
prompts: ['Read my current requests. Which ones have no next action?', 'Show the current record for REQ-1042.', 'Maya: confirm the visit time today.', 'Read REQ-1042 again and show the saved next action.', 'Show the audit log for that update.'],
73+
},
74+
{
75+
id: 'repairs', campaign: 'business_repair_status', label: 'Repair workshop',
76+
heading: '“Is my repair ready?” Know before they call.',
77+
description: 'Stop searching spreadsheets when a customer calls. Build a repair tracker with AdminForth and your coding agent: what’s stuck, who owns it, what happens next.',
78+
cta: 'Start my repair tracker', recordType: 'Repairs',
79+
records: [
80+
{id: 'REP-1042', name: 'Espresso machine · pump replacement', stage: 'Waiting for part', owner: 'Maya', due: 'Yesterday', attention: true},
81+
{id: 'REP-1043', name: 'Office printer · paper feed', stage: 'In repair', owner: 'Tom', due: 'Today'},
82+
{id: 'REP-1044', name: 'Vacuum cleaner · motor check', stage: 'Ready to collect', owner: 'Priya', due: 'Tomorrow'},
83+
],
84+
question: 'Which repairs are late, and what is blocking them?',
85+
answer: 'Espresso machine: overdue, waiting for a pump. Owner: Maya.',
86+
operation: 'Maya: check the pump delivery today at 14:00.',
87+
result: 'The part check is saved on the repair, with a due time.',
88+
brief: {
89+
manage: 'Repair jobs in my workshop, from intake to collection',
90+
missed: 'Repair status and missing parts are spread across spreadsheets and messages. Customers call before we notice a job is late.',
91+
team: 'I manage the workshop; technicians update their assigned repairs; the front desk checks status and collection dates',
92+
source: 'spreadsheet',
93+
details: 'Each repair needs a customer, item, issue, technician, status, promised date, missing part and next action. Start with intake, diagnosis, waiting for parts, in repair and ready to collect.',
94+
},
95+
prompts: ['Which repairs are overdue, and what is blocking each one?', 'Show repairs waiting for parts, with their owners.', 'Set the next action for REP-1042: check the pump delivery today at 14:00.', 'Which repairs are ready for collection?', 'Show who changed the promised date of REP-1042.'],
96+
},
97+
{
98+
id: 'production', campaign: 'business_production_orders', label: 'Small production team',
99+
heading: 'Spot a late order before your customer does.',
100+
description: 'Sales promised Friday. Production is still waiting. Build one order tracker with AdminForth and your coding agent, so both teams see the same stages and dates.',
101+
cta: 'Start my order tracker', recordType: 'Production orders',
102+
records: [
103+
{id: 'ORD-2081', name: 'Oak display shelves · 12 units', stage: 'Waiting for finish', owner: 'Maya', due: 'Tomorrow', attention: true},
104+
{id: 'ORD-2082', name: 'Counter signs · 30 units', stage: 'In production', owner: 'Tom', due: 'Thursday'},
105+
{id: 'ORD-2083', name: 'Display stands · 8 units', stage: 'Ready to ship', owner: 'Priya', due: 'Today'},
106+
],
107+
question: 'Which orders are due tomorrow but not ready to ship?',
108+
answer: '12 oak shelves: due tomorrow, still waiting for finishing.',
109+
operation: 'Maya: confirm the finishing slot today at 11:00.',
110+
result: 'Sales and production can see the next action on the order.',
111+
brief: {
112+
manage: 'Customer orders through our small production team, from quote to shipment',
113+
missed: 'Sales promises a delivery date, but production stages live in separate spreadsheets. We notice delays when customers ask.',
114+
team: 'I see all orders; sales manages customer details and dates; production updates stages; dispatch updates shipment details',
115+
source: 'spreadsheet',
116+
details: 'Track customer, ordered items, quantity, production stage, owner, promised date, blocker, next action and shipment status. Begin with confirmed, materials, in production, finishing, ready to ship and shipped.',
117+
},
118+
prompts: ['Which orders are due tomorrow but not ready to ship?', 'Show orders with a blocker and no next action.', 'Add a finishing-slot check for ORD-2081, owned by Maya, due today at 11:00.', 'Which orders are ready for dispatch today?', 'Show the change history for the delivery date of ORD-2081.'],
119+
},
120+
{
121+
id: 'field_service', campaign: 'business_field_jobs', label: 'Field service team',
122+
heading: 'Job booked. But who’s going?',
123+
description: 'Jobs in messages. Assignments in a spreadsheet. Build one job tracker with AdminForth and your coding agent, so every visit has an owner and a next step.',
124+
cta: 'Start my job tracker', recordType: 'Service jobs',
125+
records: [
126+
{id: 'JOB-3017', name: 'Harbor Café · cold room inspection', stage: 'Needs assignment', owner: 'Unassigned', due: 'Tomorrow', attention: true},
127+
{id: 'JOB-3018', name: 'Brightside School · ventilation', stage: 'Visit scheduled', owner: 'Tom', due: 'Today'},
128+
{id: 'JOB-3019', name: 'Atlas Office · pump maintenance', stage: 'Follow-up needed', owner: 'Priya', due: 'Thursday'},
129+
],
130+
question: 'Which jobs for tomorrow still have nobody assigned?',
131+
answer: 'Harbor Café’s inspection is tomorrow. Nobody is assigned.',
132+
operation: 'Assign Maya. Ask her to confirm the visit time.',
133+
result: 'Maya now owns the job. The office can see the next step.',
134+
brief: {
135+
manage: 'Service requests and site visits for my field team',
136+
missed: 'Jobs arrive in messages and a spreadsheet. We lose track of who is going, what is unfinished and who should follow up.',
137+
team: 'I manage all work; the office assigns jobs and schedules visits; technicians see and update only their assigned jobs',
138+
source: 'spreadsheet',
139+
details: 'A job needs a customer, site, request, priority, owner, visit date, status, visit notes and next action. Start with new, assigned, scheduled, on site, follow-up needed and completed. Do not build automatic dispatch or route optimisation.',
140+
},
141+
prompts: ['Which jobs for tomorrow still have nobody assigned?', 'Show unfinished visits with no next action.', 'Assign JOB-3017 to Maya and add a visit confirmation as the next action.', 'What does Tom need to finish today?', 'Show who changed the status of JOB-3017.'],
142+
},
143+
];
144+
145+
export function businessVariant(campaign: string | null): BusinessVariant | undefined {
146+
return BUSINESS_VARIANTS.find((variant) => variant.campaign === campaign);
147+
}

‎documentation/src/pages/business/business.module.css‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,59 @@
107107
white-space: nowrap;
108108
}
109109

110+
.processPreview {
111+
overflow: hidden;
112+
border: 1px solid var(--line-strong);
113+
border-radius: var(--radius-lg);
114+
background: var(--surface);
115+
box-shadow: var(--shadow);
116+
font-size: 14px;
117+
}
118+
119+
.processTop {
120+
display: flex;
121+
align-items: center;
122+
gap: 10px;
123+
padding: 16px 20px;
124+
border-bottom: 1px solid var(--line);
125+
}
126+
127+
.processTop > svg { width: 24px; height: 24px; }
128+
.processTop > span { margin-left: auto; color: var(--muted); font-size: 11px; }
129+
.processIntro { padding: 20px; }
130+
.processIntro h3 { font-size: 22px; font-weight: 600; letter-spacing: -.5px; }
131+
.processIntro p { color: var(--muted); font-size: 13px; }
132+
.processRecords { margin: 0 16px; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
133+
.processRecord { display: grid; grid-template-columns: 1.25fr 1fr; gap: 14px; padding: 15px 14px; }
134+
.processRecord + .processRecord { border-top: 1px solid var(--line); }
135+
.processRecord > div { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
136+
.processRecord b { font-size: 13px; font-weight: 500; line-height: 1.5; }
137+
.processId { font-family: var(--mono); font-size: 11px; color: var(--muted); }
138+
.processRecord small { color: var(--muted); font-size: 11px; }
139+
.processStatus { background: var(--surface-2); padding: 3px 7px; border-radius: 4px; font-size: 11px; }
140+
.processAttention { color: var(--warning); background: var(--warning-soft); }
141+
.processChat { padding: 20px; }
142+
.processChat > span { color: var(--accent-ink); font-family: var(--mono); font-size: 10px; letter-spacing: 1px; }
143+
.processChat > p { margin-top: 7px; font-size: 15px; font-weight: 500; }
144+
.processChat > div { display: flex; gap: 10px; margin-top: 12px; padding: 12px; background: var(--accent-soft); border-radius: var(--radius); color: var(--ink-2); }
145+
.processChat .ic { color: var(--accent); flex-shrink: 0; margin-top: 3px; }
146+
.processPreview figcaption { padding: 0 20px 16px; font-size: 10px; color: var(--muted); }
147+
.processSteps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
148+
.processSteps > li { padding: 24px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); }
149+
.processSteps h3 { margin-block: 12px; font-size: 20px; }
150+
.processSteps p { color: var(--ink-2); font-size: 15px; }
151+
.processSteps + .note { margin-block: 24px; }
152+
153+
@media (max-width: 800px) {
154+
.processSteps { grid-template-columns: 1fr; }
155+
}
156+
157+
@media (max-width: 420px) {
158+
.processRecord { gap: 8px; padding: 12px 10px; }
159+
.processRecords { margin-inline: 10px; }
160+
.processIntro, .processChat { padding: 16px; }
161+
}
162+
110163
.wrap {
111164
width: 100%;
112165
max-width: 1200px;

0 commit comments

Comments
 (0)