### Install Arrow Core from npm Source: https://arrow-js.com/docs.md Installs the core Arrow runtime library using npm. ```shell npm install @arrow-js/core ``` -------------------------------- ### Sync Component with Props Usage Source: https://arrow-js.com/api.md Example of creating a synchronous component with props that manages local state and event listeners. It demonstrates lazy prop reading and cleanup. ```typescript import { component, html, onCleanup, reactive } from '@arrow-js/core' import type { Props } from '@arrow-js/core' // Sync component with props const Counter = component((props: Props<{ count: number }>) => { const local = reactive({ clicks: 0 }) const onResize = () => console.log('resize') window.addEventListener('resize', onResize) onCleanup(() => window.removeEventListener('resize', onResize)) return html`` }) ``` -------------------------------- ### Install Arrow Coding Agent Skill Source: https://arrow-js.com/docs.md Installs the Arrow coding agent skill wrapper for project-specific guidance in tools like Codex and Claude Code. ```shell npx @arrow-js/skill@latest ``` -------------------------------- ### Async Component Usage Source: https://arrow-js.com/api.md Example of an asynchronous component that fetches user data based on an ID prop and renders the user's name. It uses `async/await` for data fetching. ```typescript // Async component const UserName = component(async ({ id }: { id: string }) => { const user = await fetch(`/api/users/${id}`).then(r => r.json()) return user.name }) ``` -------------------------------- ### Render Document with Parts Source: https://arrow-js.com/api.md Injects rendered HTML, head content, and payload script into an HTML shell template string. Primarily used in custom server setups. ```typescript import type { DocumentRenderParts } from '@arrow-js/framework' declare function renderDocument( template: string, parts: DocumentRenderParts ): string ``` -------------------------------- ### Create Arrow Sandbox VM Source: https://arrow-js.com/api.md Returns an ArrowTemplate that renders a stable host element and boots a QuickJS + WASM VM. Use the output event to receive calls from inside the sandbox and hostBridge to expose host modules. ```typescript import type { ArrowTemplate } from '@arrow-js/core' type HostBridgeFn = (...args: unknown[]) => unknown | Promise type HostBridgeModule = Record type HostBridge = Record interface SandboxProps { source: Record shadowDOM?: boolean; onError?: (error: Error | string) => void; debug?: boolean; } interface SandboxEvents { output?: (payload: unknown) => void; } declare function sandbox void; debug?: boolean; }>(props: T, events?: SandboxEvents, hostBridge?: HostBridge): ArrowTemplate ``` ```typescript import { html } from '@arrow-js/core' import { sandbox } from '@arrow-js/sandbox' const source = { 'main.ts': [ "import { html, reactive } from '@arrow-js/core'", "import { formatCount } from 'host-bridge:demo'", '', 'const state = reactive({ count: 0 })', '', 'export default html``' ].join('\n'), } html`
${sandbox({ source }, { output(payload) { console.log(payload) }, }, { 'host-bridge:demo': { formatCount(count) { return 'Count ' + count }, }, })}
` ``` -------------------------------- ### Arrow JS html Tag - Static Attribute Binding Source: https://arrow-js.com/api.md Example of a static attribute binding in an `html` template. The attribute is set once. ```html html`
` ``` -------------------------------- ### sandbox Source: https://arrow-js.com/api.md Returns an `ArrowTemplate` that renders a stable `` host element and boots a QuickJS + WASM VM behind it. It allows for isolated execution of JavaScript code with host-provided bridges and event handling. ```APIDOC ## sandbox() Returns an `ArrowTemplate` that renders a stable `` host element and boots a QuickJS + WASM VM behind it. ### Signature ```ts import type { ArrowTemplate } from '@arrow-js/core' type HostBridgeFn = (...args: unknown[]) => unknown | Promise type HostBridgeModule = Record type HostBridge = Record interface SandboxProps { source: Record shadowDOM?: boolean; onError?: (error: Error | string) => void; debug?: boolean; } interface SandboxEvents { output?: (payload: unknown) => void; } declare function sandbox void; debug?: boolean; }>( props: T, events?: SandboxEvents, hostBridge?: HostBridge ): ArrowTemplate ``` ### Rules - `source` must contain exactly one `main.ts` or `main.js` entry file. - `main.css` is optional and is injected into the sandbox host root. By default that root is an open shadow root. - Pass `shadowDOM: false` to render into the custom element’s light DOM instead. - Use the optional second argument to receive `output(payload)` calls from inside the sandbox. - Use the optional third argument to expose host bridge modules that sandbox code can import directly. ### Usage ```ts import { html } from '@arrow-js/core' import { sandbox } from '@arrow-js/sandbox' const source = { 'main.ts': [ "import { html, reactive } from '@arrow-js/core'", "import { formatCount } from 'host-bridge:demo'", '', 'const state = reactive({ count: 0 })', '', 'export default html``', ].join('\n'), } html`
${sandbox({ source }, { output(payload) { console.log(payload) }, }, { 'host-bridge:demo': { formatCount(count) { return 'Count ' + count }, }, })}
` ``` > **Security Model** > User-authored Arrow code runs inside QuickJS/WASM. The host page > only mounts trusted DOM and forwards sanitized event payloads. It > does not run user callbacks in the window realm. ``` -------------------------------- ### Creating Observable State with reactive() Source: https://arrow-js.com/api.md Demonstrates how to create reactive proxies for objects and arrays. Property reads are tracked, and writes notify observers. ```typescript import { reactive } from '@arrow-js/core' const data = reactive({ count: 0, items: [] as string[] }) data.count++ // triggers observers data.items.push('hello') // array mutations trigger parent observers ``` -------------------------------- ### Arrow JS html Tag - Static Expression Source: https://arrow-js.com/api.md Example of using a static expression within an `html` template. Static expressions render once. ```html html`

${someString}

` ``` -------------------------------- ### Arrow JS html Tag - Reactive Attribute Binding Source: https://arrow-js.com/api.md Example of a reactive attribute binding in an `html` template. The attribute updates when the expression changes. ```html html`
` ``` -------------------------------- ### Mounting an ArrowTemplate Source: https://arrow-js.com/api.md Demonstrates how to mount an `ArrowTemplate` to the DOM or obtain a `DocumentFragment`. An `ArrowTemplate` is callable. ```javascript const template = html`

Hello

` // Mount to a DOM node template(document.getElementById('app')) // Get a DocumentFragment const fragment = template() ``` -------------------------------- ### Todo App Base Styles and Light Theme Source: https://arrow-js.com/play Defines the base styles for the todo application and the default light theme using CSS variables. Includes layout, typography, and component styling. ```css .todo { --bg: #fafaf8; --text: #1d1d1f; --muted: #86868b; --surface: #fff; --border: #f0f0f0; --input-border: #d2d2d7; --subtle: #d2d2d7; --filter-bg: #f0f0f0; --filter-active: #fff; --filter-shadow: 0 1px 3px rgba(0, 0, 0, 0.06); --danger: #ef4444; min-height: 100vh; padding: 48px 24px; background: var(--bg); color: var(--text); font: 15px/1.5 -apple-system, 'IBM Plex Sans', system-ui, sans-serif; } html[data-theme='dark'] .todo { --bg: #18181b; --text: #e4e4e7; --muted: #71717a; --surface: #27272a; --border: #27272a; --input-border: #3f3f46; --subtle: #52525b; --filter-bg: #27272a; --filter-active: #3f3f46; --filter-shadow: none; --danger: #f87171; } .todo > * { max-width: 480px; margin-left: auto; margin-right: auto; } .todo-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 28px; } .todo-header h1 { margin: 0; font-size: 32px; font-weight: 700; } .todo-count { font-size: 14px; color: var(--muted); } .todo-input-row { display: flex; gap: 10px; margin-bottom: 20px; } .todo-input { flex: 1; padding: 12px 16px; border: 1.5px solid var(--input-border); border-radius: 12px; font: inherit; color: var(--text); background: var(--surface); outline: none; transition: border-color 200ms, box-shadow 200ms; } .todo-input:focus { border-color: #6366f1; box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } .todo-add { padding: 12px 24px; border: 0; border-radius: 12px; background: #6366f1; color: #fff; font: inherit; font-weight: 600; cursor: pointer; transition: background 150ms; } .todo-add:hover { background: #4f46e5; } .todo-filters { display: flex; padding: 3px; background: var(--filter-bg); border-radius: 10px; margin-bottom: 20px; } .todo-filter { flex: 1; border: 0; border-radius: 8px; padding: 7px 0; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; background: transparent; color: var(--muted); transition: all 150ms; text-transform: capitalize; } .todo-filter[data-active='true'] { background: var(--filter-active); color: var(--text); box-shadow: var(--filter-shadow); } .todo-list { list-style: none; padding: 0; margin-top: 0; margin-bottom: 20px; } .todo-item { display: flex; align-items: center; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--border); } .todo-check { width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--subtle); background: transparent; cursor: pointer; padding: 0; flex-shrink: 0; display: grid; place-items: center; font-size: 11px; color: transparent; transition: all 150ms; } .todo-item[data-done='true'] .todo-check { border-color: #6366f1; background: #6366f1; color: #fff; } .todo-text { flex: 1; transition: opacity 200ms; } .todo-item[data-done='true'] .todo-text { text-decoration: line-through; opacity: 0.35; } .todo-remove { border: 0; background: transparent; color: var(--subtle); cursor: pointer; font-size: 18px; padding: 4px 8px; border-radius: 6px; opacity: 0; transition: opacity 150ms, color 150ms; } .todo-item:hover .todo-remove { opacity: 1; } .todo-remove:hover { color: var(--danger); } .todo-footer { display: flex; justify-content: space-between; align-items: center; font-size: 13px; color: var(--muted); } .todo-clear { border: 0; background: transparent; color: #6366f1; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; padding: 4px 10px; border-radius: 6px; transition: background 150ms; } .todo-clear:hover { background: rgba(99, 102, 241, 0.08); } ``` -------------------------------- ### renderDocument() Source: https://arrow-js.com/api.md Injects rendered HTML, head content, and payload script into an HTML shell template string. This function is used in custom server setups. ```APIDOC ## renderDocument() ### Description Injects rendered HTML, head content, and payload script into an HTML shell template string. Used in custom server setups. ### Signature ```ts import type { DocumentRenderParts } from '@arrow-js/framework' declare function renderDocument( template: string, parts: DocumentRenderParts ): string ``` ### Placeholder markers The `template` string should contain these HTML comment placeholders: - `` — replaced with `parts.head` - `` — replaced with `parts.html` - `` — replaced with `parts.payloadScript` ``` -------------------------------- ### Arrow JS html Tag - Property Binding Source: https://arrow-js.com/api.md Example of property binding using the `.` prefix in an `html` template. This sets an IDL property instead of an attribute. ```html html`` ``` -------------------------------- ### Gallery Component Implementation Source: https://arrow-js.com/play Implements the main photo gallery UI. It manages the state for the open lightbox, handles user interactions like opening/closing the lightbox and navigating between photos via keyboard, and renders the image grid. Requires the Lightbox component. ```typescript import { component, html, reactive } from '@arrow-js/core' import { Lightbox } from './Lightbox' const photos = [10, 11, 13, 14, 15, 16, 17, 18, 19].map((id) => ({ id, thumb: `https://picsum.photos/id/${id}/300/200`, full: `https://picsum.photos/id/${id}/800/600`, })) export const GalleryApp = component(() => { const state = reactive({ open: -1 }) const open = (i: number) => { state.open = i } const close = () => { state.open = -1 } const prev = () => { state.open = (state.open - 1 + photos.length) % photos.length } const next = () => { state.open = (state.open + 1) % photos.length } document.addEventListener('keydown', (e: KeyboardEvent) => { if (state.open < 0) return if (e.key === 'Escape') close() else if (e.key === 'ArrowLeft') prev() else if (e.key === 'ArrowRight') next() }) return html`

Gallery

${photos.length} photos
${photos.map( (photo, i) => html` ` )}
${() => state.open >= 0 ? Lightbox({ src: photos[state.open].full, index: state.open, total: photos.length, onClose: close, onPrev: prev, onNext: next, }) : ''}
` }) ``` -------------------------------- ### Timer Control Button Styles Source: https://arrow-js.com/play Styles for the buttons that control the timer (e.g., start, stop, reset). Includes hover effects and styling for secondary buttons. ```css .timer-controls { display: flex; gap: 10px; } .timer-btn { border: 0; border-radius: 12px; padding: 16px 52px; font: inherit; font-size: 20px; font-weight: 700; cursor: pointer; background: rgba(255, 255, 255, 0.2); color: #fff; transition: background 150ms; } .timer-btn:hover { background: rgba(255, 255, 255, 0.3); } .timer-btn--sec { padding: 16px 28px; font-size: 16px; background: rgba(255, 255, 255, 0.1); } .timer-btn--sec:hover { background: rgba(255, 255, 255, 0.18); } ``` -------------------------------- ### Render List of Templates Source: https://arrow-js.com/ Render an array of templates to display a list. Use `.key()` on each item for efficient updates, especially when the list order changes. ```javascript import { html, reactive } from '@arrow-js/core' const data = reactive({ todos: [ { id: 1, text: 'Write docs' }, { id: 2, text: 'Ship app' }, ] }) html`
    ${() => data.todos.map(todo => html`
  • ${todo.text}
  • `.key(todo.id))}
` ``` -------------------------------- ### Keying Components in Lists Source: https://arrow-js.com/api.md Demonstrates how to use the `.key()` method on a component instance when rendering it within a list to preserve its identity across updates. ```typescript html`${() => items.map(item => ItemCard(item).key(item.id) )}` ``` -------------------------------- ### Manual Subscriptions ($on, $off) Source: https://arrow-js.com/api.md Allows for manual subscription to property changes. Use $on to subscribe to a property and $off to unsubscribe. Prefer watch() or template expressions for general use. ```APIDOC ## Manual Subscriptions ($on, $off) ### Description Provides methods for direct, per-property event handling. Use `$on` to subscribe to changes of a specific property and `$off` to unsubscribe from it. These are generally less preferred than `watch()` or template expressions for most use cases. ### Methods - **$on(propertyName, callback)**: Subscribes the `callback` function to changes in `propertyName`. - **$off(propertyName, callback)**: Unsubscribes the specified `callback` from `propertyName`. ### Usage Example ```ts // Assuming 'data' is a reactive object data.$on('count', (newVal, oldVal) => { console.log(`Count changed from ${oldVal} to ${newVal}`) }) // To unsubscribe later // data.$off('count', callbackFunction) ``` ``` -------------------------------- ### Manual Subscriptions with $on and $off Source: https://arrow-js.com/api.md Illustrates how to manually subscribe to and unsubscribe from property changes using $on and $off. Prefer watch() or template expressions unless direct per-property control is needed. ```typescript data.$on('count', (newVal, oldVal) => { /* ... */ }) data.$off('count', callback) ``` -------------------------------- ### Arrow JS html Tag - Reactive Expression Source: https://arrow-js.com/api.md Example of using a reactive (function) expression within an `html` template. Reactive expressions re-evaluate when tracked reads change. ```html html`

${() => data.count}

` ``` -------------------------------- ### Nesting SVG elements with data Source: https://arrow-js.com/api.md This example demonstrates how to use the `svg` template literal to dynamically render SVG rectangles based on data, ensuring they are correctly parsed as SVG nodes. ```typescript import { html, svg } from '@arrow-js/core' html` ${() => data.values.map((v, i) => svg``)} ` ``` -------------------------------- ### Typical Server-Side Rendering Flow Source: https://arrow-js.com/api.md Illustrates a common server flow for rendering a page using renderToString and serializePayload. Handles routing and constructs the final HTML document. ```typescript import { renderToString, serializePayload } from '@arrow-js/ssr' export async function renderPage(url: string) { const page = routeToPage(url) const result = await renderToString(page.view) return [ '', '', ' ', ` ${page.title}`, ' ', ' ', `
${result.html}
`, ` ${serializePayload(result.payload)}`, ' ', '' ].join('\n') } ``` -------------------------------- ### Pomodoro Timer Application Logic Source: https://arrow-js.com/play Manages the timer state, including work/break modes, remaining time, running status, and completed sessions. Handles starting, pausing, resetting, and ticking the timer. Use this for the main timer functionality. ```typescript import { component, html, reactive } from '@arrow-js/core' import { TimerRing } from './TimerRing' const WORK_SECONDS = 25 * 60 const BREAK_SECONDS = 5 * 60 export const TimerApp = component(() => { const state = reactive({ mode: 'work' as 'work' | 'break', remaining: WORK_SECONDS, running: false, sessions: 0, }) let timer = 0 const total = () => (state.mode === 'work' ? WORK_SECONDS : BREAK_SECONDS) const progress = () => 1 - state.remaining / total() const minutes = () => String(Math.floor(state.remaining / 60)).padStart(2, '0') const seconds = () => String(state.remaining % 60).padStart(2, '0') const tick = () => { if (!state.running) return if (state.remaining <= 0) { state.running = false if (state.mode === 'work') { state.sessions++ state.mode = 'break' state.remaining = BREAK_SECONDS } else { state.mode = 'work' state.remaining = WORK_SECONDS } return } state.remaining-- timer = window.setTimeout(tick, 1000) } const start = () => { if (state.running) return state.running = true tick() } const pause = () => { state.running = false window.clearTimeout(timer) } const reset = () => { pause() state.remaining = total() } const setMode = (mode: 'work' | 'break') => { pause() state.mode = mode state.remaining = mode === 'work' ? WORK_SECONDS : BREAK_SECONDS } return html`
${TimerRing({ progress })}
${minutes}:${seconds}

${() => state.sessions} ${() => (state.sessions === 1 ? 'session' : 'sessions')} completed

` }) ``` -------------------------------- ### Panel Introduction Text Styles Source: https://arrow-js.com/play Styles for introductory text within a tab panel. Sets margins, color, and line height for readability. ```css .panel-intro { margin: 0 0 16px; color: var(--muted); line-height: 1.7; } ``` -------------------------------- ### Agent Prompt for Arrow Sandbox Payloads Source: https://arrow-js.com/docs.md This prompt guides AI agents to generate code payloads for the Arrow sandbox. It specifies the required file structure, preferred Arrow JS primitives, and communication methods. The goal is to ensure generated code is self-contained, adheres to Arrow conventions, and is JSON-serializable. ```plaintext Build this UI as an Arrow sandbox payload. Return an object for sandbox({ source, ... }) with exactly one entry file named main.ts or main.js, plus main.css only if styles are needed. Use @arrow-js/core primitives directly: reactive(...) for state, html`...` for DOM, and component(...) only when reusable local state or composition is actually needed. Arrow expression slots are static by default, so any live value must be wrapped in a callable function like ${() => state.count}. Use event bindings like @click="${() => state.count++}", do not use JSX, React hooks, Vue directives, direct DOM mutation, or framework-specific render APIs. Export a default Arrow template or component result from main.ts. Keep the example self-contained, prefer a single clear root view, and communicate back to the host with output(payload) when needed. Put CSS in main.css, keep payloads JSON-serializable, and only return the files that are necessary for the requested interface. If you create multiple files, make sure imports match the virtual filenames you place in source. ``` -------------------------------- ### Create Arrow App with Vite Source: https://arrow-js.com/docs.md Scaffolds a complete Vite-based Arrow application with SSR and hydration. ```shell pnpm create arrow-js@latest arrow-app ``` -------------------------------- ### render() Source: https://arrow-js.com/api.md Performs a full-lifecycle render, mounting a view into a root element. It handles asynchronous components and boundaries, returning a promise that resolves with render results. ```APIDOC ## render() ### Description Full-lifecycle render that mounts a view into a root element, tracking async components and boundaries. ### Signature ```ts import type { RenderOptions, RenderResult } from '@arrow-js/framework' declare function render( root: ParentNode, view: unknown, options?: RenderOptions ): Promise ``` ### RenderOptions ```ts import type { RenderOptions } from '@arrow-js/framework' ``` ### RenderResult ```ts import type { RenderPayload, RenderResult } from '@arrow-js/framework' ``` ### Usage ```ts import { render } from '@arrow-js/framework' import { html } from '@arrow-js/core' const view = html`

Hello

` const { root, payload } = await render(document.getElementById('app'), view) ``` ``` -------------------------------- ### Reactive Data with Watcher Source: https://arrow-js.com/ Demonstrates how to create reactive data and use a watcher to perform an action when specific data changes. The watcher logs the total when the logTotal flag is true. ```typescript import { reactive, watch } from '@arrow-js/core' const data = reactive({ price: 25, quantity: 10, logTotal: true }) watch(() => data.logTotal ? data.price * data.quantity : null, (total) => total !== null && console.log(`Total: ${total}`) ) ``` -------------------------------- ### Base Styles and Theming Source: https://arrow-js.com/play Defines the base styles for the game container, including color variables for light and dark themes, and basic layout properties. It also includes a keyframe animation for blinking effects. ```css .flap { --bg: #fafaf8; --text: #1d1d1f; --muted: #86868b; --surface: #fff; --border: #e4e4e7; --accent: #d97706; --glow: rgba(217, 119, 6, 0.2); --pipe: #16a34a; --pipe-fill: #e8f5ec; --pipe-stripe: #b5dfc2; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 32px 24px; background: var(--bg); color: var(--text); font: 14px/1.5 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace; user-select: none; } html[data-theme='dark'] .flap { --bg: #18181b; --text: #e4e4e7; --muted: #71717a; --surface: #09090b; --border: #27272a; --accent: #f59e0b; --glow: rgba(245, 158, 11, 0.3); --pipe: #22c55e; --pipe-fill: #0d2818; --pipe-stripe: #145a2a; } /* ── header ── */ .flap-header { display: flex; align-items: center; justify-content: space-between; width: 100%; max-width: 560px; } .flap-title { margin: 0; font-size: 18px; font-weight: 700; color: var(--text); } .flap-scores { display: flex; align-items: baseline; gap: 12px; font-variant-numeric: tabular-nums; } .flap-score { font-size: 20px; font-weight: 700; color: var(--accent); line-height: 1; } .flap-best { font-size: 12px; color: var(--muted); } /* ── game area ── */ .flap-game { position: relative; width: 100%; max-width: 560px; height: 400px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); overflow: hidden; } /* ── player ── */ .flap-player { position: absolute; top: 0; left: 56px; font-size: 15px; font-weight: 700; line-height: 1.2; color: var(--accent); z-index: 3; will-change: transform; text-shadow: 0 0 8px var(--glow); white-space: nowrap; } .flap-player[data-phase='idle'], .flap-player[data-phase='over'] { animation: flap-blink 900ms ease-in-out infinite; } @keyframes flap-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.15; } } /* ── boundary lines ── */ .flap-ceil, .flap-floor { position: absolute; left: 0; width: 100%; height: 1px; background: var(--border); z-index: 2; pointer-events: none; } .flap-ceil { top: 0; } .flap-floor { bottom: 0; } /* ── pipes ── */ .flap-pipe { position: absolute; top: 0; left: 0; width: 52px; display: flex; flex-direction: column; z-index: 1; will-change: transform; pointer-events: none; } .flap-pipe--top { justify-content: flex-end; } .flap-pipe--bot { justify-content: flex-start; } .flap-cap { font-size: 11px; line-height: 1; color: var(--pipe); white-space: pre; text-align: center; flex-shrink: 0; } .flap-body { flex: 1; min-height: 0; margin: 0 8px; border-left: 1.5px solid var(--pipe); border-right: 1.5px solid var(--pipe); background-color: var(--pipe-fill); background-image: repeating-linear-gradient( 0deg, var(--pipe-stripe) 0px, var(--pipe-stripe) 2px, transparent 2px, transparent 6px ); } /* ── death shards ── */ .flap-shard { position: absolute; font-size: 15px; font-weight: 700; line-height: 1; color: var(--accent); z-index: 3; pointer-events: none; will-change: transform, opacity; } /* ── footer ── */ .flap-footer { width: 100%; max-width: 560px; text-align: center; } .flap-hint { font-size: 12px; color: var(--muted); } ``` -------------------------------- ### Render List with Keys Source: https://arrow-js.com/docs.md Return an array of templates to render a list. Use `.key(...)` when identity must survive reorders to preserve DOM nodes and their state. ```typescript import { html, reactive } from '@arrow-js/core' const data = reactive({ todos: [ { id: 1, text: 'Write docs' }, { id: 2, text: 'Ship app' }, ], }) html`
    ${() => data.todos.map((todo) => html`
  • ${todo.text}
  • `.key(todo.id) )}
` ``` -------------------------------- ### Basic Component with Local State Source: https://arrow-js.com/docs.md Demonstrates a component with local reactive state and cleanup for event listeners. Use `onCleanup` to remove listeners when the component unmounts. ```typescript import { component, html, onCleanup, reactive } from '@arrow-js/core' import type { Props } from '@arrow-js/core' const parentState = reactive({ count: 1 }) const Counter = component((props: Props<{ count: number }>) => { const local = reactive({ clicks: 0 }) const onResize = () => console.log(window.innerWidth) window.addEventListener('resize', onResize) onCleanup(() => window.removeEventListener('resize', onResize)) return html`` }) html`

Dashboard

${Counter(parentState)}
` ``` -------------------------------- ### pick() / props() Source: https://arrow-js.com/api.md Narrows a reactive object down to specific keys. `props` is an alias for `pick`. The returned object is a live proxy, not a copy. ```APIDOC ## pick() / props() ### Description Narrows a reactive object down to specific keys. `props` is an alias for `pick`. The returned object is a live proxy — reads and writes flow through to the source. It is not a copy. ### Signatures ```ts declare function pick( source: T, ...keys: K[] ): Pick declare function pick(source: T): T const props = pick // alias ``` ### Usage Pass only the keys a component needs. ### Example ```ts import { pick, reactive } from '@arrow-js/core' const state = reactive({ count: 1, theme: 'dark', locale: 'en' }) // Pass only the keys a component needs html`${Counter(pick(state, 'count'))}` // Without keys — returns the source as-is html`${Counter(pick(state))}` ``` ``` -------------------------------- ### Create Mountable Template Source: https://arrow-js.com/docs.md Use the `html` tagged template literal to create a mountable template. Expression slots can be static or reactive. ```typescript import { html, reactive } from '@arrow-js/core' const data = reactive({ disabled: false }) html`` ``` -------------------------------- ### sandbox Function Source: https://arrow-js.com/api.md The `sandbox` function creates a sandboxed environment. It accepts props for configuration and optional events for output handling. ```APIDOC ## sandbox Function ### Description Creates a sandboxed environment using provided properties and optional events. ### Parameters #### Props (`SandboxProps`) - **source** (Record) - Required - An object containing the source code for the sandbox. - **shadowDOM** (boolean) - Optional - If true, the sandbox will use Shadow DOM. - **onError** (function) - Optional - A callback function to handle errors that occur within the sandbox. - **debug** (boolean) - Optional - If true, enables debug mode for the sandbox. #### Events (`SandboxEvents`) - **output** (function) - Optional - A callback function that receives output from the sandbox. #### HostBridge (`HostBridge`) - **hostBridge** (HostBridge) - Optional - An interface for bridging communication between the host and the sandbox. ### Returns - **ArrowTemplate** - An Arrow Template representing the sandbox component. ``` -------------------------------- ### Sandbox Integration with Arrow JS Source: https://arrow-js.com/ Shows how to use the Arrow JS sandbox to render dynamic UI. The sandbox executes code in a WASM virtual machine and communicates with the host page. ```typescript import { html } from '@arrow-js/core' import { sandbox } from '@arrow-js/sandbox' const root = document.getElementById('app') if (!root) throw new Error('Missing #app root') const source = { 'main.ts': [ "import { html, reactive } from '@arrow-js/core'", '', "const state = reactive({ count: 0 })", '', "export default html``", ].join('\n'), 'main.css': [ 'button {', ' font: inherit;', ' padding: 0.75rem 1rem;', '}', ].join('\n'), } root.innerHTML = html`
${sandbox({ source })}
`.render() ``` -------------------------------- ### renderToString() Source: https://arrow-js.com/api.md Renders a view to an HTML string on the server. It waits for all async components to resolve before returning. This is the main SSR entry point. ```APIDOC ## renderToString() ### Description Renders a view to an HTML string on the server. Waits for all async components to resolve before returning. This is the main SSR entry point. Use it inside your request handler after you have chosen the page and built the Arrow view for the incoming URL. ### Signature ```ts import type { HydrationPayload, SsrRenderOptions, SsrRenderResult, } from '@arrow-js/ssr' declare function renderToString( view: unknown, options?: SsrRenderOptions ): Promise ``` ### Usage ```ts import { renderToString, serializePayload } from '@arrow-js/ssr' const { html, payload } = await renderToString(view) // Serialize payload for client-side hydration const script = serializePayload(payload) ``` ### Typical server flow ```ts import { renderToString, serializePayload } from '@arrow-js/ssr' export async function renderPage(url: string) { const page = routeToPage(url) const result = await renderToString(page.view) return [ '', '', ' ', ` ${page.title}`, ' ', ' ', `
${result.html}
`, ` ${serializePayload(result.payload)}`, ' ', '' ].join('\n') } ``` Internally uses JSDOM to render templates into a virtual DOM, then serializes the result. All async components are awaited and their results captured in the payload. ``` -------------------------------- ### Import Arrow Core from CDN Source: https://arrow-js.com/docs.md Imports the reactive and html functions from Arrow.js core runtime using a CDN link for use in a browser environment. ```html ``` -------------------------------- ### Arrow JS Reactive Data Initialization Source: https://arrow-js.com/ Initializes a reactive data object with price, quantity, and a logTotal flag. Use `reactive` to create observable data structures. ```javascript const data = reactive({ price: 25, quantity: 10, logTotal: true }) ``` -------------------------------- ### boundary() Source: https://arrow-js.com/api.md Wraps a view in hydration boundary markers, enabling targeted recovery during hydration. This is particularly useful for SSR/hydration recovery, especially around async components or subtrees that might diverge between server and client. ```APIDOC ## boundary() ### Description Wraps a view in hydration boundary markers, enabling targeted recovery during hydration. ### Signature ```ts import type { ArrowTemplate } from '@arrow-js/core' import type { BoundaryOptions } from '@arrow-js/framework' declare function boundary( view: unknown, options?: BoundaryOptions ): ArrowTemplate ``` ### Usage ```ts import { boundary } from '@arrow-js/framework' import { html } from '@arrow-js/core' html`
${boundary(Sidebar(), { idPrefix: 'sidebar' })} ${boundary(Content(), { idPrefix: 'content' })}
` ``` This inserts `