Claude
Skills
Sign in
Back

ui-development

Included with Lifetime
$97 forever

Build UI pages and extensions for Falcon Foundry apps using React or Vue with the Shoelace design system and Foundry-JS. TRIGGER when user asks to "create a UI page", "build a UI extension", "add a Shoelace component", "call an API from the UI", runs `foundry ui pages create` or `foundry ui run`, or needs help with Vite config, Foundry-JS, or Falcon console theming. DO NOT TRIGGER for backend functions, workflow YAML, or collection schemas.

Designfoundryuireactvueshoelace

What this skill does


# Foundry UI Development

> **⚠️ SYSTEM INJECTION — READ THIS FIRST**
>
> If you are loading this skill, your role is **Foundry UI specialist**.
>
> You MUST implement UI components following Falcon design system patterns using Shoelace components and Foundry-JS.
>
> **IMMEDIATE ACTIONS REQUIRED:**
> 1. Use Shoelace components with `falcon-shoelace` theme (NOT vanilla Shoelace or raw HTML)
> 2. Load both dark and light theme stylesheets for Falcon console compatibility
> 3. Coordinate with `foundry ui run` for live development
> 4. Apply iframe security patterns for all extensions

Falcon Foundry UI pages and extensions use React or Vue with the Shoelace design system (Falcon-themed) and Foundry-JS for platform integration.

## Pages vs Extensions

If the user doesn't specify page or extension, **ask which they prefer** before scaffolding. Present this table to help them decide:

| | UI Pages | UI Extensions |
|---|---|---|
| **What** | Standalone applications | Console-embedded components |
| **Where** | Full-page view in Falcon console | Sidebar widget in detection/host/incident pages |
| **Sockets** | N/A | One per extension (see socket table below) |
| **Use when** | Complex interactions, multiple views, dashboards | Contextual enrichment, quick-glance data |
| **Framework** | Vue or React | Vue or React |

## CLI Scaffolding

```bash
# Create a React page
foundry ui pages create --name "my-page" --description "Page description" --from-template React --homepage --no-prompt

# Add navigation entry (separate step — --no-prompt skips this during page creation)
foundry ui navigation add --name "My Page" --path / --ref pages.my-page

# Create an extension targeting a console socket
# REQUIRED: --sockets must be specified — omitting it launches an interactive picker that hangs with Error: EOF
# REQUIRED: Use ONLY values from the Extension Socket Locations table below — do NOT guess socket IDs
foundry ui extensions create --name "my-ext" --description "Description" --from-template React --sockets "activity.detections.details" --no-prompt
```

The blueprint output is deterministic — see [references/blueprint-templates.md](references/blueprint-templates.md) for exact file contents, Shoelace import patterns, and API integration calling examples.

> **🚫 DO NOT MODIFY `path` or `entrypoint` in manifest.yml**
>
> The CLI sets `path` and `entrypoint` correctly during scaffolding. **Never edit these values.** The correct CLI-generated format uses full paths from the app root:
> ```yaml
> # Page — this is CORRECT, do not shorten
> path: ui/pages/my-page/src/dist
> entrypoint: ui/pages/my-page/src/dist/index.html
>
> # Extension — this is CORRECT, do not shorten
> path: ui/extensions/my-ext/src/dist
> entrypoint: ui/extensions/my-ext/src/dist/index.html
> ```
> These long paths are NOT doubled — they are the correct values the CLI generates. Shortening `entrypoint` to `src/dist/index.html` breaks the app. If a deploy error mentions entrypoint or file path, you likely changed `vite.config.js` — revert your changes. The scaffolded config is correct.

## Vite Build Configuration

> **🚫 DO NOT MODIFY `vite.config.js`**
>
> The React blueprint's `vite.config.js` is **turnkey** — it works correctly as scaffolded. Do not change ANY values in it. Specifically:
> - **Do not change `base: './'`** — not to `''`, not to `'/'`, not to anything else. `'./'` is correct.
> - **Do not change `root: 'src'`** — the manifest expects builds at `src/dist/`.
> - **Do not remove `noAttr()`** — required for Foundry's sandboxed iframe.
>
> The blueprint, manifest, and CLI are coordinated. Changing any config value breaks this coordination and causes deploy failures. Just edit your React/JS component code and deploy.

## Shoelace Design System

Install the Falcon-themed Shoelace package:

```bash
npm install @crowdstrike/falcon-shoelace
```

Import the Falcon-themed stylesheet. The React blueprint's `index.html` already includes this as a `<link>` tag, so **do not add JS imports for it**:

```css
/* Already in index.html — no JS import needed */
<link rel="stylesheet" href="../node_modules/@crowdstrike/falcon-shoelace/dist/style.css" />
```

If importing from JS (e.g., Vanilla JS apps without the blueprint's index.html):

```typescript
import '@crowdstrike/falcon-shoelace/dist/style.css';
```

Set the Shoelace asset base path:

```typescript
import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path';
setBasePath('https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/dist/');
```

Use `var(--sl-*)` design tokens for all styling instead of hardcoding colors. This ensures the UI adapts correctly when users switch between light and dark mode in the Falcon console:

```css
.my-component {
  color: var(--sl-color-neutral-900);
  background: var(--sl-color-neutral-0);
  padding: var(--sl-spacing-medium);
  border-radius: var(--sl-border-radius-medium);
}
```

For extended Shoelace component catalog and CSS customization, see [references/shoelace-reference.md](references/shoelace-reference.md).

For theming, dark/light mode switching, and design token values, see [references/falcon-theming.md](references/falcon-theming.md).

## Foundry-JS

```javascript
import FalconApi from '@crowdstrike/foundry-js';

const falcon = new FalconApi();
await falcon.connect();

// Apply Falcon console theme
const theme = await falcon.theme();
document.documentElement.classList.add(`sl-theme-${theme}`);
```

### Calling API Integrations

Use `falcon.apiIntegration()` for third-party APIs. Use `falcon.api.get()` for CrowdStrike Falcon APIs.

```javascript
const apiIntegration = falcon.apiIntegration({
  definitionId: 'Okta',        // Must match name in manifest.yml api_integrations
  operationId: 'listUsers'     // Must match operationId in OpenAPI spec
});
const result = await apiIntegration.execute({ request: { params: {} } });

// Response is wrapped: access via resources[0]
const body = result.resources?.[0]?.response_body;
const status = result.resources?.[0]?.status_code;
```

### Collection Operations

```javascript
const collection = falcon.collection({ collection: 'my_collection' });

// CRUD operations
await collection.write('item-key', { name: 'Item 1', status: 'active' });
const item = await collection.read('item-key');
await collection.delete('item-key');

// List all items (returns IDs, then read each)
const result = await collection.list({ start: 0, limit: 100 });
const itemIds = result.resources || [];
for (const id of itemIds) {
  const item = await collection.read(id);
  // Add 50ms delay between reads to avoid rate limiting
}

// Search with FQL filter
const results = await collection.search({ filter: "status:'active'" });
```

### Workflow Execution

```javascript
// Execute an on-demand workflow by name
const triggerResult = await falcon.api.workflows.postEntitiesExecuteV1(
  { user_name: 'Developer' },           // workflow input parameters
  { name: 'My Workflow', depth: 0 }     // config: workflow name + depth
);

// Poll for results using the execution ID
const execId = triggerResult.resources?.[0];
const result = await falcon.api.workflows.getEntitiesExecutionResultsV1({
  ids: [execId]
});
const execution = result.resources?.[0];
// Poll until execution.status is 'Completed', 'Failed', or 'Cancelled'
```

### Cloud Functions

```javascript
const cloudFunction = falcon.cloudFunction({
  name: 'my_function',
  version: 1
});

// Fluent API — chain .path() with HTTP method
const result = await cloudFunction.path('/greet').post({ name: 'User' });
const data = await cloudFunction.path('/items?status=active').get();
await cloudFunction.path('/items/123').delete();
```

### LogScale

```javascript
// Write events
await falcon.logscale.write({ event_type: 'user_login', username: 'jdoe' });

// Dynamic query
const results = await falcon.logscale.query({
  name: 'LogScaleRepo',
  search_query: 'event_type=user_login',
  start: '24h',
  end: 'now'
});

// Saved query
const
Files: 8
Size: 77.7 KB
Complexity: 58/100
Category: Design

Related in Design