Skip to content

Commit d2732b2

Browse files
committed
docs: pair every StackBlitz button with a CodeSandbox alternative
The CodeSandboxButton component shipped in the initial docs commit but was never actually used in any MDX page — leaving CodeSandbox-leaning readers without an explicit 'open in CodeSandbox' CTA. Add the button next to every StackBlitzButton across guide + 22 recipe pages (EN + RU), plus the homepage hero (EN + RU), pointing at the same example path.
1 parent 75d49b6 commit d2732b2

28 files changed

Lines changed: 60 additions & 0 deletions

apps/docs/src/content/docs/guide/getting-started.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ description: "Install Triggery, write your first trigger, fire your first event
66
import { Aside, TabItem, LinkCard, CardGrid } from '@astrojs/starlight/components';
77
import FrameworkTabs from '~/components/FrameworkTabs.astro';
88
import StackBlitzButton from '~/components/StackBlitzButton.astro';
9+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
910

1011
import PackageManagers from '~/components/PackageManagers.astro';
1112

1213
In five minutes you'll have a single file that declares a scenario ("when a new message arrives and the user has notifications on — show a toast"), and three small components that plug into it. None of the components know about each other.
1314

1415
<StackBlitzButton path="examples/vite-react-counter" label="Skip ahead — open the counter example in StackBlitz" />
16+
<CodeSandboxButton path="examples/vite-react-counter" label="Skip ahead — open the counter example in CodeSandbox" />
1517

1618
## Prerequisites
1719

apps/docs/src/content/docs/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ For SolidJS use `@triggery/solid`, for Vue 3 use `@triggery/vue` — the API is
9999
<LinkButton href="/guide/getting-started/" icon="right-arrow">Read the Getting Started guide</LinkButton>
100100
<LinkButton href="/recipes/react/notification-pipeline/" variant="minimal">See it in a real recipe</LinkButton>
101101
<LinkButton href="https://stackblitz.com/github/triggeryjs/triggery/tree/main/examples/vite-react-counter?file=README.md" variant="minimal" icon="external">Open in StackBlitz</LinkButton>
102+
<LinkButton href="https://codesandbox.io/p/github/triggeryjs/triggery/main/examples/vite-react-counter" variant="minimal" icon="external">Open in CodeSandbox</LinkButton>
102103

103104
## What people are saying
104105

apps/docs/src/content/docs/recipes/react/analytics.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ sidebar:
77

88
import { Aside, LinkCard, CardGrid, FileTree } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011

1112
The analytics anti-pattern: every button and every form imports a `track(...)` helper, which imports the Segment SDK, which imports Amplitude, which is conditional on a feature flag — and the moment you want to swap providers, half your codebase changes. Triggery flips it: components fire a generic `ui:event`, a single trigger routes it to the right destination, and swapping providers is a one-file change.
1213

1314
<StackBlitzButton path="examples/vite-react-analytics" label="Open in StackBlitz" />
15+
<CodeSandboxButton path="examples/vite-react-analytics" label="Open in CodeSandbox" />
1416

1517
## Scenario
1618

apps/docs/src/content/docs/recipes/react/auth-reactions.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ sidebar:
77

88
import { Aside, LinkCard, CardGrid, FileTree } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011

1112
Auth events are an architectural mess in every app: the access token expired *while the user was halfway through editing a form*, or a permission was revoked *while they have a privileged screen open*. Without a coordinator, every form and every screen has to subscribe to "auth events" and decide for itself. With Triggery, *the trigger* decides — features just register their state and their handlers.
1213

1314
<StackBlitzButton path="examples/vite-react-auth-reactions" label="Open in StackBlitz" />
15+
<CodeSandboxButton path="examples/vite-react-auth-reactions" label="Open in CodeSandbox" />
1416

1517
## Scenario
1618

apps/docs/src/content/docs/recipes/react/chat-mentions.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ sidebar:
77

88
import { Aside, LinkCard, CardGrid, FileTree } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011

1112
A common product pattern: when the user is @-mentioned in chat, optionally relay the mention to an outbound integration (Slack, Discord, a webhook URL), then react to whether the relay succeeded — and let the user retry or disable the integration without writing it again. Triggery handles the *chain* of async work cleanly: one event in, one trigger drives the whole pipeline, side effects stay inside the components that own them.
1213

1314
<StackBlitzButton path="examples/vite-react-chat-mentions" label="Open in StackBlitz" />
15+
<CodeSandboxButton path="examples/vite-react-chat-mentions" label="Open in CodeSandbox" />
1416

1517
## Scenario
1618

apps/docs/src/content/docs/recipes/react/counter.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ sidebar:
77

88
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011

1112
The "hello world" of Triggery. Two buttons fire an `increment`/`decrement` event; a counter component reacts via `useAction` and re-renders itself. Nothing more.
1213

1314
<StackBlitzButton path="examples/vite-react-counter" label="Open in StackBlitz" />
15+
<CodeSandboxButton path="examples/vite-react-counter" label="Open in CodeSandbox" />
1416

1517
## The trigger
1618

apps/docs/src/content/docs/recipes/react/debounced-search.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ sidebar:
77

88
import { Aside, LinkCard, CardGrid, FileTree } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011

1112
The classic autocomplete: user types into a search field, the app fetches suggestions from an API, late responses don't overwrite newer ones, the network isn't hammered. Without Triggery this is a 40-line `useEffect` riddled with refs, race-condition bookkeeping, and an `AbortController` you carry around by hand. With Triggery the input fires one event per keystroke and the trigger handles concurrency, cancellation and debouncing declaratively.
1213

1314
<StackBlitzButton path="examples/vite-react-debounced-search" label="Open in StackBlitz" />
15+
<CodeSandboxButton path="examples/vite-react-debounced-search" label="Open in CodeSandbox" />
1416

1517
## Scenario
1618

apps/docs/src/content/docs/recipes/react/form-with-zod.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ sidebar:
77

88
import { Aside, LinkCard, CardGrid, FileTree } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011

1112
A trigger's event payload is typed at compile time, but runtime data — form submissions, URL params, WebSocket frames — comes in unstructured. Triggery's recommended pattern: validate **at the producer's boundary**, fire only what passes. The trigger handler then sees a fully typed, runtime-checked payload. This recipe shows the idiom and packages it as a small `useValidatedEvent` helper so every producer in the app is a one-liner.
1213

1314
<StackBlitzButton path="examples/vite-react-form-zod" label="Open in StackBlitz" />
15+
<CodeSandboxButton path="examples/vite-react-form-zod" label="Open in CodeSandbox" />
1416

1517
## Scenario
1618

apps/docs/src/content/docs/recipes/react/modal-stack.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ sidebar:
77

88
import { Aside, LinkCard, CardGrid, FileTree } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011

1112
Every non-trivial app eventually grows a modal mess: "Confirm delete" opens "Resolve conflict" opens "Reauthenticate" — all from different features, none of them wanting to know about each other. Triggery turns this into a one-liner per feature: fire `modal:open`, fire `modal:close`, listen if you care. Per-route stacks come for free with `<TriggerScope>`.
1213

1314
<StackBlitzButton path="examples/vite-react-modal-stack" label="Open in StackBlitz" />
15+
<CodeSandboxButton path="examples/vite-react-modal-stack" label="Open in CodeSandbox" />
1416

1517
## Scenario
1618

apps/docs/src/content/docs/recipes/react/notification-pipeline.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ sidebar:
77

88
import { Aside, LinkCard, CardGrid, TabItem, Steps, FileTree } from '@astrojs/starlight/components';
99
import StackBlitzButton from '~/components/StackBlitzButton.astro';
10+
import CodeSandboxButton from '~/components/CodeSandboxButton.astro';
1011
import PackageManagers from '~/components/PackageManagers.astro';
1112

1213
The canonical scenario: a new chat message arrives and three side effects happen *in different components*, gated by *user state owned by yet another component*. None of them know about each other. Reading the trigger file tells a product manager exactly what happens, and reading the components tells nobody anything but their own job.
1314

1415
This is the scenario the rest of the docs use to compare against `useEffect`/saga/listener alternatives.
1516

1617
<StackBlitzButton path="examples/vite-react-notifications" label="Open the full example in StackBlitz" />
18+
<CodeSandboxButton path="examples/vite-react-notifications" label="Open the full example in CodeSandbox" />
1719

1820
## Scenario
1921

0 commit comments

Comments
 (0)