diff --git a/docs/develop/standalone-activities-interactive-demo.mdx b/docs/develop/standalone-activities-interactive-demo.mdx
new file mode 100644
index 0000000000..317c88acf9
--- /dev/null
+++ b/docs/develop/standalone-activities-interactive-demo.mdx
@@ -0,0 +1,383 @@
+---
+id: standalone-activities-interactive-demo
+title: Standalone Activities Interactive Demo
+sidebar_label: Standalone Activities (Interactive)
+toc_max_heading_level: 3
+keywords:
+ - standalone activity
+ - activity execution
+ - execute activity
+ - activity handle
+ - quickstart
+ - interactive demo
+tags:
+ - Activities
+ - Temporal Client
+ - Temporal SDKs
+description: An interactive quickstart for Temporal Standalone Activities — run Activities directly from a Temporal Client without a Workflow.
+---
+
+:::tip SUPPORT, STABILITY, and DEPENDENCY INFO
+
+Temporal SDK support for [Standalone Activities](/standalone-activity) is at
+[Pre-release](/evaluate/development-production-features/release-stages#pre-release).
+
+All APIs are experimental and may be subject to backwards-incompatible changes.
+
+:::
+
+Standalone Activities let you execute an Activity directly from a Temporal Client — no Workflow
+required. The Activity is durably enqueued on the Temporal Server, executed by a Worker, and its
+result is returned to the caller.
+
+Use the interactive demo below to explore the API, experiment with failure scenarios, and see the
+generated SDK code and CLI command update in real time.
+
+import { StandaloneActivityDemo } from '@site/src/components';
+
+
+
+---
+
+## How it works
+
+When you call `client.ExecuteActivity()` (or the equivalent in your SDK), the following happens:
+
+1. **Connect** — Your application connects to the Temporal Server.
+2. **Schedule** — The Server durably persists the Activity execution on the specified Task Queue.
+3. **Poll** — A Worker polling that Task Queue picks up the Activity Task.
+4. **Execute** — The Worker runs your Activity function with the provided arguments.
+5. **Return** — The result is stored by the Server and returned to the original caller via the
+ `ActivityHandle`.
+
+Because the Server durably persists the Activity, it survives Worker restarts and network
+interruptions. If the Activity fails, the Server automatically retries it according to the Retry
+Policy you configure.
+
+### Standalone vs Workflow Activities
+
+| | Workflow Activity | Standalone Activity |
+|---|---|---|
+| Orchestrated by | A Workflow Definition | Your application code |
+| Started with | `workflow.ExecuteActivity()` | `client.ExecuteActivity()` |
+| Retry policy | Configured per `ActivityOptions` | Configured per `StartActivityOptions` |
+| Visibility | Workflow Event History | Activity Visibility (List/Count) |
+| Use case | Complex, multi-step orchestration | Simple, independent jobs |
+
+The Activity function and Worker registration are **identical** for both — only the execution path
+differs.
+
+---
+
+## Setup
+
+### 1. Install the Temporal CLI
+
+Download the Standalone Activity prerelease build of the Temporal CLI:
+
+```bash
+# macOS (Homebrew)
+brew install temporal
+
+# Or download directly from GitHub
+# https://github.com/temporalio/cli/releases/tag/v1.6.2-standalone-activity
+```
+
+### 2. Start a local development server
+
+```bash
+temporal server start-dev
+```
+
+The server starts at `localhost:7233` and the Web UI at
+[http://localhost:8233](http://localhost:8233). Standalone Activities appear under the **Activities**
+nav item in the Web UI.
+
+### 3. Install the SDK
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+
+
+Requires **Go SDK v1.41.0** or higher.
+
+```bash
+go get go.temporal.io/sdk@latest
+```
+
+Clone the samples repository to follow along:
+
+```bash
+git clone https://github.com/temporalio/samples-go.git
+cd samples-go
+```
+
+
+
+
+Requires **Python SDK v1.23.0** or higher.
+
+```bash
+uv add temporalio
+# or: pip install temporalio
+```
+
+Clone the samples repository to follow along:
+
+```bash
+git clone https://github.com/temporalio/samples-python.git
+cd samples-python
+```
+
+
+
+
+Requires **.NET SDK v1.12.0** or higher.
+
+```bash
+dotnet add package Temporalio
+```
+
+Clone the samples repository to follow along:
+
+```bash
+git clone https://github.com/temporalio/samples-dotnet.git
+cd samples-dotnet
+```
+
+
+
+
+### 4. Run the Worker
+
+The Worker registers the Activity and polls the Task Queue. Start it in a dedicated terminal:
+
+
+
+
+```bash
+go run standalone-activity/helloworld/worker/main.go
+```
+
+
+
+
+```bash
+uv run hello_standalone_activity/worker.py
+```
+
+
+
+
+```bash
+dotnet run --project src/StandaloneActivity worker
+```
+
+
+
+
+### 5. Execute the Activity
+
+In a separate terminal, run the starter:
+
+
+
+
+```bash
+go run standalone-activity/helloworld/starter/main.go
+```
+
+
+
+
+```bash
+uv run hello_standalone_activity/execute_activity.py
+```
+
+
+
+
+```bash
+dotnet run --project src/StandaloneActivity execute-activity
+```
+
+
+
+
+Or use the Temporal CLI directly:
+
+```bash
+temporal activity execute \
+ --type Activity \
+ --activity-id my-activity-id \
+ --task-queue my-task-queue \
+ --start-to-close-timeout 10s \
+ --input '"World"'
+```
+
+---
+
+## Key API concepts
+
+### `ExecuteActivity` — start and wait
+
+The primary call. Durably enqueues the Activity, waits for execution, and returns the result:
+
+
+
+
+```go
+handle, err := c.ExecuteActivity(ctx, client.StartActivityOptions{
+ ID: "my-activity-id",
+ TaskQueue: "my-task-queue",
+ StartToCloseTimeout: 10 * time.Second,
+}, helloworld.Activity, "World")
+
+var result string
+err = handle.Get(ctx, &result)
+```
+
+
+
+
+```python
+result = await client.execute_activity(
+ compose_greeting,
+ args=[ComposeGreetingInput("Hello", "World")],
+ id="my-activity-id",
+ task_queue="my-task-queue",
+ start_to_close_timeout=timedelta(seconds=10),
+)
+```
+
+
+
+
+```csharp
+var result = await client.ExecuteActivityAsync(
+ () => MyActivities.ComposeGreetingAsync(
+ new ComposeGreetingInput("Hello", "World")),
+ new("my-activity-id", "my-task-queue")
+ {
+ StartToCloseTimeout = TimeSpan.FromSeconds(10),
+ });
+```
+
+
+
+
+### `StartActivity` — fire and forget
+
+Enqueues the Activity without waiting for it to finish. Useful when you want to kick off
+long-running work and check back later:
+
+
+
+
+```go
+handle, err := c.ExecuteActivity(ctx, options, helloworld.Activity, "World")
+// handle.Get() can be called later
+```
+
+
+
+
+```python
+handle = await client.start_activity(
+ compose_greeting,
+ args=[ComposeGreetingInput("Hello", "World")],
+ id="my-activity-id",
+ task_queue="my-task-queue",
+ start_to_close_timeout=timedelta(seconds=10),
+)
+# Later:
+result = await handle.result()
+```
+
+
+
+
+```csharp
+var handle = await client.StartActivityAsync(
+ () => MyActivities.ComposeGreetingAsync(
+ new ComposeGreetingInput("Hello", "World")),
+ new("my-activity-id", "my-task-queue")
+ {
+ StartToCloseTimeout = TimeSpan.FromSeconds(10),
+ });
+// Later:
+var result = await handle.GetResultAsync();
+```
+
+
+
+
+### List and Count Activities
+
+
+
+
+```go
+// List
+resp, err := c.ListActivities(ctx, client.ListActivitiesOptions{
+ Query: "TaskQueue = 'my-task-queue'",
+})
+for info, err := range resp.Results { ... }
+
+// Count
+resp, err := c.CountActivities(ctx, client.CountActivitiesOptions{
+ Query: "TaskQueue = 'my-task-queue'",
+})
+log.Println("Total:", resp.Count)
+```
+
+
+
+
+```python
+# List
+async for info in client.list_activities(
+ query="TaskQueue = 'my-task-queue'"
+):
+ print(info.activity_id, info.status)
+
+# Count
+resp = await client.count_activities(
+ query="TaskQueue = 'my-task-queue'"
+)
+print("Total:", resp.count)
+```
+
+
+
+
+```csharp
+// List
+await foreach (var info in client.ListActivitiesAsync(
+ "TaskQueue = 'my-task-queue'"))
+{
+ Console.WriteLine($"{info.ActivityId}: {info.Status}");
+}
+
+// Count
+var resp = await client.CountActivitiesAsync(
+ "TaskQueue = 'my-task-queue'");
+Console.WriteLine($"Total: {resp.Count}");
+```
+
+
+
+
+The `Query` parameter uses the same [List Filter](/list-filter) syntax as Workflow Visibility.
+
+---
+
+## Next steps
+
+For complete API reference and advanced usage, see the SDK-specific guides:
+
+- [Standalone Activities — Go SDK](/develop/go/standalone-activities)
+- [Standalone Activities — Python SDK](/develop/python/standalone-activities)
+- [Standalone Activities — .NET SDK](/develop/dotnet/standalone-activities)
diff --git a/src/components/elements/StandaloneActivityDemo.js b/src/components/elements/StandaloneActivityDemo.js
new file mode 100644
index 0000000000..91625c5952
--- /dev/null
+++ b/src/components/elements/StandaloneActivityDemo.js
@@ -0,0 +1,602 @@
+import CodeBlock from '@theme/CodeBlock';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import styles from './standalone-activity-demo.module.css';
+
+// ---------------------------------------------------------------------------
+// Code generation
+// ---------------------------------------------------------------------------
+
+function generateSdkCode(language, config) {
+ const { activityId, taskQueue, greeting, name, timeout, timeoutType, simulateFailures, maxRetries } = config;
+ const expectedResult = `${greeting}, ${name}!`;
+
+ if (language === 'go') {
+ const timeoutField =
+ timeoutType === 'start_to_close'
+ ? `StartToCloseTimeout: ${timeout} * time.Second,`
+ : `ScheduleToCloseTimeout: ${timeout} * time.Second,`;
+ const retryPolicy =
+ simulateFailures && maxRetries > 0
+ ? `\n\tRetryPolicy: &temporal.RetryPolicy{\n\t\tMaximumAttempts: ${maxRetries + 1},\n\t},`
+ : '';
+ return `activityOptions := client.StartActivityOptions{
+\tID: "${activityId}",
+\tTaskQueue: "${taskQueue}",
+\t${timeoutField}${retryPolicy}
+}
+
+handle, err := c.ExecuteActivity(ctx, activityOptions,
+\thelloworld.Activity, "${greeting}", "${name}")
+if err != nil {
+\tlog.Fatalln("Unable to execute activity", err)
+}
+
+var result string
+err = handle.Get(ctx, &result)
+// result: "${expectedResult}"`;
+ }
+
+ if (language === 'python') {
+ const timeoutField =
+ timeoutType === 'start_to_close'
+ ? `start_to_close_timeout=timedelta(seconds=${timeout}),`
+ : `schedule_to_close_timeout=timedelta(seconds=${timeout}),`;
+ const retryPolicy =
+ simulateFailures && maxRetries > 0
+ ? `\n retry_policy=RetryPolicy(\n maximum_attempts=${maxRetries + 1},\n ),`
+ : '';
+ return `result = await client.execute_activity(
+ compose_greeting,
+ args=[ComposeGreetingInput("${greeting}", "${name}")],
+ id="${activityId}",
+ task_queue="${taskQueue}",
+ ${timeoutField}${retryPolicy}
+)
+# result: "${expectedResult}"`;
+ }
+
+ if (language === 'dotnet') {
+ const timeoutField =
+ timeoutType === 'start_to_close'
+ ? `StartToCloseTimeout = TimeSpan.FromSeconds(${timeout}),`
+ : `ScheduleToCloseTimeout = TimeSpan.FromSeconds(${timeout}),`;
+ const retryPolicy =
+ simulateFailures && maxRetries > 0
+ ? `\n MaximumAttempts = ${maxRetries + 1},`
+ : '';
+ return `var result = await client.ExecuteActivityAsync(
+ () => MyActivities.ComposeGreetingAsync(
+ new ComposeGreetingInput("${greeting}", "${name}")),
+ new("${activityId}", "${taskQueue}")
+ {
+ ${timeoutField}${retryPolicy}
+ });
+// result: "${expectedResult}"`;
+ }
+
+ return '';
+}
+
+function generateCliCode(config) {
+ const { activityId, taskQueue, name, timeout, timeoutType } = config;
+ const timeoutFlag =
+ timeoutType === 'start_to_close'
+ ? `--start-to-close-timeout ${timeout}s`
+ : `--schedule-to-close-timeout ${timeout}s`;
+ return `temporal activity execute \\
+ --type Activity \\
+ --activity-id ${activityId} \\
+ --task-queue ${taskQueue} \\
+ ${timeoutFlag} \\
+ --input '"${name}"'`;
+}
+
+// ---------------------------------------------------------------------------
+// Constants
+// ---------------------------------------------------------------------------
+
+const LANGUAGES = [
+ { id: 'go', label: 'Go' },
+ { id: 'python', label: 'Python' },
+ { id: 'dotnet', label: '.NET' },
+];
+
+const FLOW_NODES = [
+ { label: 'Client', sub: 'Your App' },
+ { label: 'Server', sub: 'Temporal' },
+ { label: 'Task Queue', sub: '' },
+ { label: 'Worker', sub: '' },
+ { label: 'Activity', sub: 'Function' },
+];
+
+const IDLE_NODES = ['pending', 'pending', 'pending', 'pending', 'pending'];
+
+const DEFAULT_CONFIG = {
+ activityId: 'my-activity-id',
+ taskQueue: 'my-task-queue',
+ greeting: 'Hello',
+ name: 'World',
+ timeout: 10,
+ timeoutType: 'start_to_close',
+ simulateFailures: false,
+ failCount: 1,
+ maxRetries: 2,
+};
+
+// ---------------------------------------------------------------------------
+// Main component
+// ---------------------------------------------------------------------------
+
+export default function StandaloneActivityDemo() {
+ const [language, setLanguage] = useState('go');
+ const [config, setConfig] = useState({ ...DEFAULT_CONFIG });
+
+ const [sim, setSim] = useState({
+ running: false,
+ nodeStates: [...IDLE_NODES],
+ log: [],
+ status: 'idle', // 'idle' | 'running' | 'completed' | 'failed'
+ result: null,
+ });
+
+ const [history, setHistory] = useState([]);
+
+ const runIdRef = useRef(0);
+ const logScrollRef = useRef(null);
+
+ // Auto-scroll log to bottom
+ useEffect(() => {
+ if (logScrollRef.current) {
+ logScrollRef.current.scrollTop = logScrollRef.current.scrollHeight;
+ }
+ }, [sim.log]);
+
+ const updateConfig = useCallback((key, value) => {
+ setConfig((prev) => ({ ...prev, [key]: value }));
+ }, []);
+
+ const handleExecute = useCallback(() => {
+ const runId = ++runIdRef.current;
+ const isCancelled = () => runIdRef.current !== runId;
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
+
+ const startTime = Date.now();
+ const logEntries = [];
+
+ const elapsed = () => ((Date.now() - startTime) / 1000).toFixed(2);
+
+ /** Push a log entry and update React state atomically with nodeStates */
+ const update = (nodeStates, msg, type = 'info') => {
+ if (isCancelled()) return;
+ if (msg) logEntries.push({ time: elapsed(), msg, type });
+ setSim((prev) => ({
+ ...prev,
+ running: true,
+ nodeStates,
+ log: [...logEntries],
+ status: 'running',
+ }));
+ };
+
+ /** Push a log-only entry (no node state change) */
+ const addLog = (msg, type = 'info') => {
+ if (isCancelled()) return;
+ logEntries.push({ time: elapsed(), msg, type });
+ setSim((prev) => ({ ...prev, log: [...logEntries] }));
+ };
+
+ // Reset UI immediately
+ setSim({
+ running: true,
+ nodeStates: [...IDLE_NODES],
+ log: [],
+ status: 'running',
+ result: null,
+ });
+
+ (async () => {
+ let attempt = 1;
+
+ // ── Step 0: connect ──────────────────────────────────────────────────
+ update(
+ ['active', 'pending', 'pending', 'pending', 'pending'],
+ 'Connecting to Temporal Server at localhost:7233...'
+ );
+ await sleep(400);
+ if (isCancelled()) return;
+
+ // ── Step 1: schedule ─────────────────────────────────────────────────
+ update(
+ ['completed', 'active', 'pending', 'pending', 'pending'],
+ `Scheduling activity "${config.activityId}" on task queue "${config.taskQueue}"...`
+ );
+ await sleep(600);
+ if (isCancelled()) return;
+
+ update(['completed', 'completed', 'pending', 'pending', 'pending'], null);
+
+ // ── Retry loop ───────────────────────────────────────────────────────
+ while (true) {
+ if (isCancelled()) return;
+
+ // Step 2: worker poll
+ update(
+ ['completed', 'completed', 'active', 'pending', 'pending'],
+ attempt === 1
+ ? 'Worker polling task queue for activity tasks...'
+ : `[Retry ${attempt - 1}] Worker polling task queue...`
+ );
+ await sleep(550);
+ if (isCancelled()) return;
+
+ // Step 3: execute
+ update(
+ ['completed', 'completed', 'completed', 'active', 'pending'],
+ `[Attempt ${attempt}] Executing Activity("${config.greeting}", "${config.name}")...`
+ );
+ await sleep(750);
+ if (isCancelled()) return;
+
+ const shouldFail = config.simulateFailures && attempt <= config.failCount;
+ const maxAttempts = config.maxRetries + 1;
+
+ if (shouldFail) {
+ const retriesLeft = maxAttempts - attempt;
+ update(
+ ['completed', 'completed', 'pending', 'failed', 'pending'],
+ `[Attempt ${attempt}/${maxAttempts}] Activity failed: ApplicationError`,
+ 'error'
+ );
+ await sleep(350);
+ if (isCancelled()) return;
+
+ if (retriesLeft <= 0) {
+ logEntries.push({
+ time: elapsed(),
+ msg: `Activity exhausted all ${maxAttempts} attempt(s). No more retries.`,
+ type: 'error',
+ });
+ setSim((prev) => ({
+ ...prev,
+ running: false,
+ status: 'failed',
+ log: [...logEntries],
+ }));
+ setHistory((prev) =>
+ [
+ {
+ activityId: config.activityId,
+ status: 'Failed',
+ duration: `${((Date.now() - startTime) / 1000).toFixed(1)}s`,
+ attempts: attempt,
+ result: '—',
+ timestamp: new Date().toLocaleTimeString(),
+ },
+ ...prev,
+ ].slice(0, 10)
+ );
+ return;
+ }
+
+ addLog(
+ `Scheduling retry in 1s… (${retriesLeft} retry attempt${retriesLeft > 1 ? 's' : ''} remaining)`,
+ 'warn'
+ );
+ await sleep(1000);
+ if (isCancelled()) return;
+
+ attempt++;
+ continue; // jump back to worker poll
+ }
+
+ // ── Success ───────────────────────────────────────────────────────
+ update(
+ ['completed', 'completed', 'completed', 'completed', 'active'],
+ `[Attempt ${attempt}] Activity function returned successfully!`,
+ 'success'
+ );
+ await sleep(400);
+ if (isCancelled()) return;
+
+ const result = `${config.greeting}, ${config.name}!`;
+ logEntries.push({ time: elapsed(), msg: `Result: "${result}"`, type: 'success' });
+
+ setSim({
+ running: false,
+ nodeStates: ['completed', 'completed', 'completed', 'completed', 'completed'],
+ log: [...logEntries],
+ status: 'completed',
+ result,
+ });
+
+ setHistory((prev) =>
+ [
+ {
+ activityId: config.activityId,
+ status: 'Completed',
+ duration: `${((Date.now() - startTime) / 1000).toFixed(1)}s`,
+ attempts: attempt,
+ result,
+ timestamp: new Date().toLocaleTimeString(),
+ },
+ ...prev,
+ ].slice(0, 10)
+ );
+ return;
+ }
+ })();
+ }, [config]);
+
+ const codeLanguage = language === 'dotnet' ? 'csharp' : language;
+
+ const failureNote =
+ config.simulateFailures
+ ? config.failCount > config.maxRetries
+ ? `⚠ All ${config.maxRetries + 1} attempt(s) will fail — failCount exceeds maxRetries.`
+ : `ℹ Activity will fail ${config.failCount} time(s), then succeed on attempt ${config.failCount + 1}.`
+ : null;
+
+ return (
+
+ {/* Language tabs */}
+
+ {LANGUAGES.map(({ id, label }) => (
+
+ ))}
+
+
+
+ {/* ── Left column: configure + code ── */}
+
+
+ Configure Activity
+
+
updateConfig('activityId', v)}
+ />
+ updateConfig('taskQueue', v)}
+ />
+ updateConfig('greeting', v)}
+ />
+ updateConfig('name', v)}
+ />
+ updateConfig('timeout', Number(v))}
+ />
+
+
+
+
+
+
+
+
+ Failure Simulation
+
+
+
+
+ {config.simulateFailures && (
+ <>
+
updateConfig('failCount', Number(v))}
+ />
+ updateConfig('maxRetries', Number(v))}
+ />
+ >
+ )}
+
+ {failureNote && {failureNote}
}
+
+
+
+ SDK Code
+ {generateSdkCode(language, config)}
+
+
+
+ CLI Command
+ {generateCliCode(config)}
+
+
+
+ {/* ── Right column: simulation ── */}
+
+
+
+
+
+
+ Execution Flow
+
+ {FLOW_NODES.map((node, i) => (
+
+
+
{node.label}
+ {node.sub && (
+
{node.sub}
+ )}
+
+ {i < FLOW_NODES.length - 1 && (
+
+ ›
+
+ )}
+
+ ))}
+
+
+
+
+ Activity Log
+
+ {sim.log.length === 0 ? (
+
+ Click "Execute Activity" to run the simulation
+
+ ) : (
+ sim.log.map((entry, i) => (
+
+ [{entry.time}s]
+ {entry.msg}
+
+ ))
+ )}
+
+
+ {sim.status === 'completed' && sim.result && (
+
+ ✅ Result: "{sim.result}"
+
+ )}
+ {sim.status === 'failed' && (
+
+ ❌ Activity failed after exhausting all retry attempts
+
+ )}
+
+
+ {history.length > 0 && (
+
+
+ Activity History{' '}
+ ({history.length})
+
+
+
+
+
+ | Activity ID |
+ Status |
+ Duration |
+ Attempts |
+ Result |
+
+
+
+ {history.map((h, i) => (
+
+ | {h.activityId} |
+
+
+ {h.status}
+
+ |
+ {h.duration} |
+ {h.attempts} |
+ {h.result} |
+
+ ))}
+
+
+
+
+ )}
+
+
+
+ );
+}
+
+// ---------------------------------------------------------------------------
+// Sub-components
+// ---------------------------------------------------------------------------
+
+function ConfigField({ label, value, onChange, type = 'text', min, max }) {
+ return (
+
+
+ onChange(e.target.value)}
+ />
+
+ );
+}
diff --git a/src/components/elements/standalone-activity-demo.module.css b/src/components/elements/standalone-activity-demo.module.css
new file mode 100644
index 0000000000..4b4db563d7
--- /dev/null
+++ b/src/components/elements/standalone-activity-demo.module.css
@@ -0,0 +1,416 @@
+/* ── Root ───────────────────────────────────────────────────────────────── */
+
+.demo {
+ font-family: var(--ifm-font-family-base);
+}
+
+/* ── Language tabs ──────────────────────────────────────────────────────── */
+
+.languageTabs {
+ display: flex;
+ gap: 6px;
+ margin-bottom: 16px;
+ border-bottom: 2px solid var(--ifm-color-emphasis-200);
+ padding-bottom: 10px;
+}
+
+.langTab {
+ padding: 5px 18px;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 4px;
+ background: var(--ifm-background-color);
+ color: var(--ifm-font-color-base);
+ cursor: pointer;
+ font-size: 0.875rem;
+ font-weight: 500;
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
+}
+
+.langTab:hover {
+ background: var(--ifm-color-emphasis-100);
+}
+
+.langTabActive {
+ background: var(--ifm-color-primary);
+ color: #fff;
+ border-color: var(--ifm-color-primary);
+}
+
+/* ── Two-column layout ──────────────────────────────────────────────────── */
+
+.columns {
+ display: flex;
+ gap: 24px;
+ align-items: flex-start;
+}
+
+.leftCol,
+.rightCol {
+ flex: 1;
+ min-width: 0;
+}
+
+@media (max-width: 900px) {
+ .columns {
+ flex-direction: column;
+ }
+}
+
+/* ── Section ────────────────────────────────────────────────────────────── */
+
+.section {
+ margin-bottom: 20px;
+}
+
+.sectionTitle {
+ font-size: 0.95rem;
+ font-weight: 600;
+ margin: 0 0 8px;
+ color: var(--ifm-font-color-base);
+}
+
+/* ── Config form ────────────────────────────────────────────────────────── */
+
+.configGrid {
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: 6px;
+ overflow: hidden;
+}
+
+.configRow {
+ display: flex;
+ align-items: center;
+ padding: 7px 12px;
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+ background: var(--ifm-background-surface-color);
+}
+
+.configRow:last-child {
+ border-bottom: none;
+}
+
+.configLabel {
+ flex: 1;
+ font-size: 0.83rem;
+ color: var(--ifm-font-color-secondary);
+ user-select: none;
+}
+
+.configInput,
+.configSelect {
+ width: 150px;
+ padding: 4px 8px;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 4px;
+ background: var(--ifm-background-color);
+ color: var(--ifm-font-color-base);
+ font-size: 0.83rem;
+}
+
+.checkbox {
+ margin-right: 6px;
+ cursor: pointer;
+}
+
+.simNote {
+ font-size: 0.8rem;
+ color: var(--ifm-font-color-secondary);
+ margin: 8px 0 0;
+ padding: 8px 12px;
+ background: var(--ifm-color-emphasis-100);
+ border-radius: 4px;
+ line-height: 1.4;
+}
+
+/* ── Execute button ─────────────────────────────────────────────────────── */
+
+.executeBtn {
+ width: 100%;
+ padding: 12px 24px;
+ background: var(--ifm-color-primary);
+ color: #fff;
+ border: none;
+ border-radius: 6px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ transition: background 0.2s;
+}
+
+.executeBtn:hover:not(.executeBtnDisabled) {
+ background: var(--ifm-color-primary-dark);
+}
+
+.executeBtnDisabled {
+ opacity: 0.65;
+ cursor: not-allowed;
+}
+
+/* ── Spinner ────────────────────────────────────────────────────────────── */
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.spinner {
+ display: inline-block;
+ width: 14px;
+ height: 14px;
+ border: 2px solid rgba(255, 255, 255, 0.35);
+ border-top-color: #fff;
+ border-radius: 50%;
+ animation: spin 0.75s linear infinite;
+ flex-shrink: 0;
+}
+
+/* ── Flow diagram ───────────────────────────────────────────────────────── */
+
+.flowDiagram {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 14px 12px;
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: 6px;
+ overflow-x: auto;
+ gap: 4px;
+}
+
+.flowNode {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 8px 10px;
+ border-radius: 6px;
+ border: 2px solid var(--ifm-color-emphasis-300);
+ background: var(--ifm-background-color);
+ min-width: 68px;
+ text-align: center;
+ transition: border-color 0.3s, background 0.3s, opacity 0.3s;
+}
+
+.flowNodeLabel {
+ font-size: 0.75rem;
+ font-weight: 600;
+ white-space: nowrap;
+ transition: color 0.3s;
+}
+
+.flowNodeSub {
+ font-size: 0.63rem;
+ color: var(--ifm-font-color-secondary);
+ margin-top: 2px;
+ white-space: nowrap;
+}
+
+/* Node states */
+
+.flowNode_pending {
+ opacity: 0.38;
+}
+
+@keyframes nodePulse {
+ 0%,
+ 100% {
+ box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.45);
+ }
+ 50% {
+ box-shadow: 0 0 0 7px rgba(59, 130, 246, 0);
+ }
+}
+
+.flowNode_active {
+ border-color: #3b82f6;
+ background: rgba(59, 130, 246, 0.08);
+ animation: nodePulse 1.4s ease-in-out infinite;
+}
+
+.flowNode_active .flowNodeLabel {
+ color: #3b82f6;
+}
+
+.flowNode_completed {
+ border-color: #22c55e;
+ background: rgba(34, 197, 94, 0.08);
+}
+
+.flowNode_completed .flowNodeLabel {
+ color: #15803d;
+}
+
+.flowNode_failed {
+ border-color: #ef4444;
+ background: rgba(239, 68, 68, 0.08);
+}
+
+.flowNode_failed .flowNodeLabel {
+ color: #dc2626;
+}
+
+/* Arrows */
+
+.flowArrow {
+ font-size: 1.6rem;
+ color: var(--ifm-color-emphasis-300);
+ flex-shrink: 0;
+ line-height: 1;
+ transition: color 0.3s;
+ user-select: none;
+}
+
+.flowArrowLit {
+ color: #22c55e;
+}
+
+/* ── Activity log ───────────────────────────────────────────────────────── */
+
+.log {
+ height: 190px;
+ overflow-y: auto;
+ background: var(--ifm-background-surface-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: 6px;
+ padding: 10px 12px;
+ font-family: var(--ifm-font-family-monospace);
+ font-size: 0.78rem;
+ line-height: 1.55;
+}
+
+.logPlaceholder {
+ color: var(--ifm-font-color-secondary);
+ font-style: italic;
+ padding: 4px 0;
+}
+
+.logLine {
+ display: flex;
+ gap: 8px;
+ padding: 1px 0;
+}
+
+.logTime {
+ color: var(--ifm-font-color-secondary);
+ flex-shrink: 0;
+}
+
+.logLine_info .logMsg {
+ color: var(--ifm-font-color-base);
+}
+
+.logLine_success .logMsg {
+ color: #15803d;
+ font-weight: 600;
+}
+
+.logLine_error .logMsg {
+ color: #dc2626;
+}
+
+.logLine_warn .logMsg {
+ color: #b45309;
+}
+
+/* Result banners */
+
+.resultSuccess {
+ margin-top: 8px;
+ padding: 9px 14px;
+ background: rgba(34, 197, 94, 0.1);
+ border: 1px solid rgba(34, 197, 94, 0.5);
+ border-radius: 6px;
+ color: #15803d;
+ font-size: 0.88rem;
+}
+
+.resultFailed {
+ margin-top: 8px;
+ padding: 9px 14px;
+ background: rgba(239, 68, 68, 0.08);
+ border: 1px solid rgba(239, 68, 68, 0.45);
+ border-radius: 6px;
+ color: #dc2626;
+ font-size: 0.88rem;
+}
+
+/* ── Activity history table ─────────────────────────────────────────────── */
+
+.historyCount {
+ font-weight: 400;
+ color: var(--ifm-font-color-secondary);
+ font-size: 0.85rem;
+}
+
+.historyWrapper {
+ overflow-x: auto;
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: 6px;
+}
+
+.historyTable {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.82rem;
+}
+
+.historyTable th {
+ padding: 7px 12px;
+ text-align: left;
+ background: var(--ifm-background-surface-color);
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+ font-weight: 600;
+ color: var(--ifm-font-color-secondary);
+ font-size: 0.72rem;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ white-space: nowrap;
+}
+
+.historyTable td {
+ padding: 7px 12px;
+ border-bottom: 1px solid var(--ifm-color-emphasis-100);
+ vertical-align: middle;
+}
+
+.historyTable tr:last-child td {
+ border-bottom: none;
+}
+
+.historyId {
+ font-family: var(--ifm-font-family-monospace);
+ font-size: 0.78rem;
+}
+
+.historyResult {
+ font-family: var(--ifm-font-family-monospace);
+ font-size: 0.78rem;
+ color: var(--ifm-font-color-secondary);
+}
+
+.badgeSuccess {
+ display: inline-block;
+ padding: 2px 8px;
+ background: rgba(34, 197, 94, 0.12);
+ color: #15803d;
+ border-radius: 9999px;
+ font-size: 0.74rem;
+ font-weight: 600;
+ white-space: nowrap;
+}
+
+.badgeFailed {
+ display: inline-block;
+ padding: 2px 8px;
+ background: rgba(239, 68, 68, 0.1);
+ color: #dc2626;
+ border-radius: 9999px;
+ font-size: 0.74rem;
+ font-weight: 600;
+ white-space: nowrap;
+}
diff --git a/src/components/index.js b/src/components/index.js
index 07b4ad9ef6..df840f56ae 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -1,5 +1,6 @@
// Website components
export { default as RetrySimulator } from './elements/RetrySimulator';
+export { default as StandaloneActivityDemo } from './elements/StandaloneActivityDemo';
export { default as HomePageHero } from './elements/HomePageHero';
export { SdkLogos } from './elements/SdkLogos';
export { SdkLogosAsBlocks } from './elements/SdkLogosAsBlocks';