Skip to content

Commit b62a657

Browse files
committed
chore: make tweaks to the demo copy, ui, colors, modals (#361)
1 parent c9e86ed commit b62a657

File tree

5 files changed

+286
-127
lines changed

5 files changed

+286
-127
lines changed

apps/demo/src/lib/components/EventsPanel.svelte

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { Card, CardContent, CardHeader, CardTitle } from '$lib/components/ui/card';
55
import { Play, CheckCircle2, XCircle } from '@lucide/svelte';
66
import { codeToHtml } from 'shiki';
7+
import PulseDot from '$lib/components/PulseDot.svelte';
78
89
interface Props {
910
flowState: ReturnType<typeof createFlowState>;
@@ -137,13 +138,17 @@
137138
});
138139
</script>
139140

140-
<Card class="h-full flex flex-col">
141+
<Card class="h-full flex flex-col relative">
142+
<!-- PulseDot in center for desktop/tablet view -->
143+
<div class="absolute inset-0 flex items-center justify-center pointer-events-none z-10">
144+
<PulseDot />
145+
</div>
141146
<CardHeader class="pb-0 pt-2 px-3 flex-shrink-0 relative">
142147
<div class="flex items-center justify-between">
143148
<CardTitle class="text-sm">Event Stream ({displayableEvents.length})</CardTitle>
144149
</div>
145150
</CardHeader>
146-
<CardContent class="flex-1 overflow-auto pt-1 pb-2 px-3 min-h-0">
151+
<CardContent class="flex-1 overflow-auto pt-1 pb-2 px-3 min-h-0 relative">
147152
<div class="space-y-1">
148153
{#if displayableEvents.length === 0}
149154
<p class="text-sm text-muted-foreground text-center py-8">

apps/demo/src/lib/components/ExplanationPanel.svelte

Lines changed: 142 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,24 @@
4343
'This flow processes web articles by fetching content, generating summaries and keywords, then publishing the results.',
4444
whatItDoes:
4545
'Demonstrates parallel execution, automatic retries, and dependency management—all core pgflow features.',
46-
reliabilityFeatures: [
46+
options: [
4747
{
48-
setting: 'maxAttempts: 2',
49-
explanation: 'Automatically retries failed steps up to 2 times before giving up'
48+
name: 'slug',
49+
value: '"article_flow"',
50+
explanation:
51+
'Unique identifier for this flow. Must be ≤128 characters, containing only letters, numbers, and underscores.'
5052
},
5153
{
52-
setting: 'baseDelay: 1',
53-
explanation: 'Initial retry delay of 1 second, doubling with each retry (1s, 2s, 4s...)'
54+
name: 'maxAttempts',
55+
value: '2',
56+
explanation:
57+
'Maximum total attempts allowed. With 2 attempts: 1 initial try + 1 retry on failure.'
58+
},
59+
{
60+
name: 'baseDelay',
61+
value: '1',
62+
explanation:
63+
'Base delay for retries in seconds. With exponential backoff, first retry waits 1s (subsequent retries would wait 2s, 4s, etc).'
5464
}
5565
],
5666
inputType: `{
@@ -62,26 +72,27 @@
6272
// Step-level concept explanations (how pgflow works internally)
6373
const stepConcepts: Record<string, string> = {
6474
fetchArticle:
65-
'Root step with no dependencies. start_flow() creates a task and queues a message containing the task ID. ' +
66-
'Worker polls the queue, calls start_tasks() with the task ID to reserve the task and get its input, ' +
67-
'executes the handler, calls complete_task() to save the output. Tasks exist independently from queue messages, ' +
68-
'enabling both automated polling and manual reservation (future: human approval steps).',
75+
'Root step (no dependencies) - starts immediately when flow begins. ' +
76+
'pgflow creates a task and queues it. Worker polls the queue, reserves the task, ' +
77+
'executes your handler with the initial flow input, and saves the output. ' +
78+
'<strong>KEY INSIGHT:</strong> The output becomes available to dependent steps under the key <strong>"fetchArticle"</strong>.',
6979
7080
summarize:
71-
'Depends on fetchArticle. When fetchArticle completes, SQL Core checks dependencies, creates a task, and queues a message. ' +
72-
"Worker polls, calls start_tasks() which assembles input from both fetchArticle's output and the original run input, " +
73-
'executes the handler, calls complete_task().',
81+
'Waits for <strong>fetchArticle</strong> to complete. Once ready, pgflow creates a task and queues it. ' +
82+
"When the worker calls <strong>start_tasks()</strong>, the SQL function assembles the input by combining the original flow input with <strong>fetchArticle's</strong> output. " +
83+
'<strong>KEY INSIGHT:</strong> Dependencies automatically contribute their outputs to your input object.',
7484
7585
extractKeywords:
76-
'Also depends on fetchArticle, so becomes ready alongside summarize. ' +
77-
'Both messages hit the queue simultaneously—parallel execution happens naturally as workers ' +
78-
'independently poll and start whichever task they receive first.',
86+
'Also depends on <strong>fetchArticle</strong> - becomes ready at the same time as <strong>summarize</strong>. ' +
87+
'Both tasks queue simultaneously. Workers poll for batches, ' +
88+
'enabling true parallel execution when multiple workers or async handlers are involved. ' +
89+
'<strong>KEY INSIGHT:</strong> Steps with the same dependencies run in parallel automatically.',
7990
8091
publish:
81-
'Depends on both summarize AND extractKeywords—blocked until both complete. ' +
82-
'After the second finishes, SQL Core finds publish ready, creates a task and queues a message. ' +
83-
'start_tasks() assembles input from both dependency outputs. After completion, no dependents remain ' +
84-
'and the run is marked completed.'
92+
'Requires BOTH <strong>summarize</strong> AND <strong>extractKeywords</strong> to complete. pgflow waits for all dependencies, ' +
93+
'then creates and queues a task. When the worker calls <strong>start_tasks()</strong>, the SQL function assembles the input ' +
94+
'by combining outputs from both dependencies. After <strong>publish</strong> completes, the flow finishes. ' +
95+
'<strong>KEY INSIGHT:</strong> Multiple dependencies create synchronization points in your workflow.'
8596
};
8697
8798
// Step metadata for explanation
@@ -91,6 +102,11 @@
91102
name: string;
92103
displayName: string;
93104
whatItDoes: string;
105+
options: Array<{
106+
name: string;
107+
value: string;
108+
explanation: string;
109+
}>;
94110
dependsOn: string[];
95111
dependents: string[];
96112
inputType: string;
@@ -102,6 +118,20 @@
102118
displayName: 'Fetch Article',
103119
whatItDoes:
104120
'Fetches article content from the provided URL using Jina Reader API. Returns structured content with title and text for downstream processing.',
121+
options: [
122+
{
123+
name: 'slug',
124+
value: '"fetchArticle"',
125+
explanation:
126+
'Step identifier within the flow. Must be unique per flow, ≤128 chars, and contain only letters, numbers, and underscores.'
127+
},
128+
{
129+
name: 'dependsOn',
130+
value: '[]',
131+
explanation:
132+
'No dependencies - this is a root step that starts immediately when the flow begins. Only receives the initial flow input.'
133+
}
134+
],
105135
dependsOn: [],
106136
dependents: ['summarize', 'extractKeywords'],
107137
inputType: `{
@@ -119,6 +149,19 @@
119149
displayName: 'Summarize',
120150
whatItDoes:
121151
'Generates a concise summary of the article content using an LLM. Runs in parallel with keyword extraction.',
152+
options: [
153+
{
154+
name: 'slug',
155+
value: '"summarize"',
156+
explanation: 'Step identifier within the flow.'
157+
},
158+
{
159+
name: 'dependsOn',
160+
value: '["fetchArticle"]',
161+
explanation:
162+
'Waits for fetchArticle to complete. IMPORTANT: The output from fetchArticle will be available in this step\'s input object under the key "fetchArticle".'
163+
}
164+
],
122165
dependsOn: ['fetchArticle'],
123166
dependents: ['publish'],
124167
inputType: `{
@@ -134,6 +177,19 @@
134177
displayName: 'Extract Keywords',
135178
whatItDoes:
136179
'Extracts key terms and topics from the article using an LLM. Runs in parallel with summarization.',
180+
options: [
181+
{
182+
name: 'slug',
183+
value: '"extractKeywords"',
184+
explanation: 'Step identifier within the flow.'
185+
},
186+
{
187+
name: 'dependsOn',
188+
value: '["fetchArticle"]',
189+
explanation:
190+
'Waits for fetchArticle to complete. IMPORTANT: The output from fetchArticle will be available in this step\'s input object under the key "fetchArticle".'
191+
}
192+
],
137193
dependsOn: ['fetchArticle'],
138194
dependents: ['publish'],
139195
inputType: `{
@@ -148,6 +204,19 @@
148204
displayName: 'Publish',
149205
whatItDoes:
150206
'Combines the summary and keywords and publishes the processed article. In this demo, returns a mock article ID—in production, this would insert into a database.',
207+
options: [
208+
{
209+
name: 'slug',
210+
value: '"publish"',
211+
explanation: 'Step identifier within the flow.'
212+
},
213+
{
214+
name: 'dependsOn',
215+
value: '["summarize", "extractKeywords"]',
216+
explanation:
217+
'Waits for BOTH summarize AND extractKeywords to complete. IMPORTANT: The outputs from both steps will be available in this step\'s input object under their respective keys: "summarize" and "extractKeywords".'
218+
}
219+
],
151220
dependsOn: ['summarize', 'extractKeywords'],
152221
dependents: [],
153222
inputType: `{
@@ -389,6 +458,29 @@
389458
{/if}
390459
</div>
391460

461+
<!-- Configuration Options (collapsible) -->
462+
<details
463+
class="concept-explainer mt-2 bg-background/50 border border-border rounded-lg"
464+
>
465+
<summary
466+
class="font-semibold text-sm text-foreground cursor-pointer hover:bg-background/80 flex items-center gap-2 p-3 rounded-lg transition-colors"
467+
>
468+
<span class="concept-caret">▸</span>
469+
<span class="flex-1">Configuration options</span>
470+
</summary>
471+
<div class="text-sm text-foreground/90 leading-relaxed px-3 pb-3 space-y-2.5">
472+
{#each currentStepInfo.options as option (option.name)}
473+
<div>
474+
<div class="font-mono text-sm mb-0.5">
475+
<span class="font-bold text-foreground">{option.name}:</span>
476+
<span class="text-foreground ml-1">{option.value}</span>
477+
</div>
478+
<div class="text-sm text-foreground/80 ml-4">{option.explanation}</div>
479+
</div>
480+
{/each}
481+
</div>
482+
</details>
483+
392484
<!-- Concept explainer (collapsible) -->
393485
<details
394486
class="concept-explainer mt-3 mb-3 bg-background/50 border border-border rounded-lg"
@@ -399,8 +491,9 @@
399491
<span class="concept-caret">▸</span>
400492
<span class="flex-1">How this step works in pgflow</span>
401493
</summary>
402-
<div class="text-xs text-muted-foreground leading-relaxed px-3 pb-3">
403-
{stepConcepts[currentStepInfo.name]}
494+
<div class="text-sm text-foreground/80 leading-relaxed px-3 pb-3">
495+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
496+
{@html stepConcepts[currentStepInfo.name]}
404497
</div>
405498
</details>
406499

@@ -579,44 +672,52 @@
579672
class="font-semibold text-sm text-foreground cursor-pointer hover:bg-background/80 flex items-center gap-2 p-3 rounded-lg transition-colors"
580673
>
581674
<span class="concept-caret">▸</span>
582-
<span class="flex-1">How pgflow orchestrates this flow</span>
675+
<span class="flex-1">Orchestration in Postgres</span>
583676
</summary>
584-
<div class="text-xs text-muted-foreground leading-relaxed px-3 pb-3 space-y-2">
677+
<div class="text-sm text-foreground/80 leading-relaxed px-3 pb-3 space-y-2.5">
585678
<p>
586-
<code class="bg-muted px-1 rounded font-mono">start_flow()</code> creates a run and initializes
587-
state for each step. Root steps (no dependencies) get tasks queued immediately.
679+
The <strong>pgflow client</strong> calls SQL function
680+
<code class="bg-muted px-1 rounded font-mono">start_flow()</code> via Supabase RPC, which
681+
creates a run and initializes state for each step. Root steps (no dependencies) get tasks
682+
queued immediately.
588683
</p>
589684
<p>
590-
<strong>Edge Function worker</strong> polls the queue, calls
685+
<strong>Edge Function worker</strong> polls the queue, calls SQL function
591686
<code class="bg-muted px-1 rounded font-mono">start_tasks()</code> to reserve tasks,
592687
executes handlers, then calls
593688
<code class="bg-muted px-1 rounded font-mono">complete_task()</code> to save outputs.
594689
</p>
595690
<p>
596-
<strong>SQL Core</strong> checks dependencies after each completion, creates tasks
597-
for steps with all dependencies met, and marks the run complete when
691+
<code class="bg-muted px-1 rounded font-mono">complete_task()</code> checks
692+
dependencies after each completion, creates tasks for steps with all dependencies
693+
met, and marks the run complete when
598694
<code class="bg-muted px-1 rounded font-mono">remaining_steps = 0</code>.
599695
</p>
600696
<p>
601-
<strong>Supabase Realtime</strong> broadcasts state changes back to this UI for live
602-
updates.
697+
<strong>Supabase Realtime</strong> streams database events. The
698+
<strong>pgflow client</strong>
699+
transforms these into a developer-friendly API with promises for completion and reactive
700+
state updates.
603701
</p>
604702
</div>
605703
</details>
606704

607-
<!-- Reliability Configuration (collapsible) -->
705+
<!-- Configuration Options (collapsible) -->
608706
<details class="concept-explainer bg-background/50 border border-border rounded-lg">
609707
<summary
610708
class="font-semibold text-sm text-foreground cursor-pointer hover:bg-background/80 flex items-center gap-2 p-3 rounded-lg transition-colors"
611709
>
612710
<span class="concept-caret">▸</span>
613-
<span class="flex-1">Reliability configuration</span>
711+
<span class="flex-1">Configuration options</span>
614712
</summary>
615-
<div class="text-xs text-muted-foreground leading-relaxed px-3 pb-3 space-y-2">
616-
{#each flowInfo.reliabilityFeatures as feature (feature.setting)}
713+
<div class="text-sm text-foreground/90 leading-relaxed px-3 pb-3 space-y-2.5">
714+
{#each flowInfo.options as option (option.name)}
617715
<div>
618-
<code class="bg-muted px-1 rounded font-mono text-primary">{feature.setting}</code>
619-
- {feature.explanation}
716+
<div class="font-mono text-sm mb-0.5">
717+
<span class="font-bold text-foreground">{option.name}:</span>
718+
<span class="text-foreground ml-1">{option.value}</span>
719+
</div>
720+
<div class="text-sm text-foreground/80 ml-4">{option.explanation}</div>
620721
</div>
621722
{/each}
622723
</div>
@@ -673,6 +774,11 @@
673774
scroll-behavior: smooth;
674775
}
675776
777+
/* Make inline code elements slightly bolder */
778+
.explanation-content :global(code) {
779+
font-weight: 500;
780+
}
781+
676782
/* Custom scrollbar styling */
677783
.explanation-content::-webkit-scrollbar {
678784
width: 8px;

0 commit comments

Comments
 (0)