build-dashboard
Build the visual layer of a holaOS dashboard app — TanStack Start + @holaboss/ui + workspace tokens. Use when an app has SDK primitives wired (via app-builder-sdk) AND needs a `src/client/` UI surface. NOT for marketing pages, NOT for snapshot HTML reports.
Works with
---
name: build-dashboard
description: Build the visual layer of a holaOS dashboard app — TanStack Start + @holaboss/ui + workspace tokens. Use when an app has SDK primitives wired (via app-builder-sdk) AND needs a `src/client/` UI surface. NOT for marketing pages, NOT for snapshot HTML reports.
license: Apache-2.0
---
# build-dashboard
The agent before you reliably produces ugly dashboards because it starts from a blank page and reaches for default shapes (single-column full-width cards, KPI strips that don't fit, sidebars that don't earn their space). This skill exists to **bypass that default**. The visual decisions are already made — your job is to fill in the data and copy.
## When to use
- The user asked for a dashboard, workspace pane, list view, kanban, calendar, or "let me see my X"
- The app's `app.ts` already declares `resource(...)` rows via the SDK (set up via the `app-builder-sdk` skill first)
- The app dir needs a `src/client/` directory
**Skip this skill when:**
- Integration-only module (Slack/Discord/Stripe-style MCP-only) — those use only `app-builder-sdk`
- Marketing landing page → use `frontend-design`
- One-off static HTML report → not this product class
## The two non-negotiables
1. **Copy the bundled reference. Don't invent.** `reference/messaging-dashboard/src/client/` is the canonical starting point. Three files below are verbatim across every dashboard; the rest gets customized per shape.
2. **Two style imports, not one.** `@holaboss/ui/styles.css` only bakes in utilities used inside the library. Every Tailwind class your `src/client/` writes needs your own app-side compile pass. The register-time lint `workspace_app_missing_tailwind_compile` rejects apps missing this.
## The shape catalog — pick one
Look at the user's data, NOT at "what dashboards usually have". Most apps are shape 1.
| # | Shape | Pick when the data is… | Template |
|---|---|---|---|
| 1 | **Queue / feed** | scheduled items, drafts, an action queue, an activity log, anything time-ordered | `reference/messaging-dashboard/` (full, ready to copy) |
| 2 | **Dense table** | flat records (CRM contacts, log rows, ticket list) that the user scans like a spreadsheet | Replace shape-1's `messages-table.tsx` with the `<Table>` primitive (see snippet below) |
| 3 | **Kanban** | rows that move between named statuses; user drags between columns | Replace shape-1's main column with horizontal status columns (see snippet below) |
| 4 | **Detail / form** | a single resource the user edits or watches in depth | Replace shape-1's main column with `<Field>` form (see snippet below) |
| 5 | **Calendar week** | rows with `start_time` + duration that pin to a day-grid | Replace shape-1's main column with `@holaboss/ui`'s `Calendar` primitive |
Shapes 2–5 still keep shape 1's header, app.css, connection pill, status badge, and tokens. **Only the main content area changes.**
ASCII for shape 1 (the most common, read this even if you're using another shape):
```
┌────────────────────────────────────────────┐
│ Outgoing ● ● Connected · @jot │ ← header
│ 5 queued · agent will send on schedule │
│ │
│ NEEDS ATTENTION │
│ ┌──────────────────────────────────┐ │ ← attention strip
│ │ #ops · Failed · 3h ago │ │ (warning-bordered,
│ │ Composio retry exhausted… │ │ always-visible Retry)
│ │ [Retry] [Edit] │ │
│ └──────────────────────────────────┘ │
│ │
│ TODAY ───────────────────────────── 02 │ ← day divider
│ NOW · 08:42 ───────────────────────── │ ← "now" cursor on rail
│ 09:00 ● #general · ● Scheduled │ ← next-up marker
│ Heads-up: pricing page goes live… │
│ 17:00 · #growth · ● Draft │
│ Weekly recap — KPI strip… │
│ │
│ TOMORROW ────────────────────────── 02 │
│ … │
└────────────────────────────────────────────┘
(max-w-3xl centered on bg-background)
```
## Foundation — paste verbatim into every dashboard
These five files do NOT vary per shape. Copy them exactly.
### `src/client/app.css` (13 lines)
```css
/* App-local Tailwind compile entry.
*
* `@holaboss/ui/styles.css` only bakes in utilities used INSIDE the library.
* Every Tailwind class your `src/client/` writes (max-w-3xl, grid-cols-*,
* text-fg-48, bg-card, flex-1, etc.) needs an app-side compile pass to land
* in the bundle. Without it the page renders mostly unstyled.
*
* Required by the register-time lint `workspace_app_missing_tailwind_compile`.
*/
@import "tailwindcss";
@source "../client";
```
### `src/client/routes/__root.tsx`
```tsx
import "@holaboss/ui/styles.css"
import "../app.css"
import type { ReactNode } from "react"
export function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" data-theme="holaos-light">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Your App — holaOS</title>
</head>
<body className="antialiased">{children}</body>
</html>
)
}
```
### `src/client/components/connection-pill.tsx`
```tsx
import { StatusDot } from "@holaboss/ui"
type Props = {
state: "ready" | "needs_connect" | "needs_reauth" | "checking"
handle?: string
}
const COPY: Record<Props["state"], { label: string; tone: "success" | "warning" | "muted" }> = {
ready: { label: "Connected", tone: "success" },
needs_connect: { label: "Not connected", tone: "warning" },
needs_reauth: { label: "Reauth required", tone: "warning" },
checking: { label: "Checking…", tone: "muted" },
}
export function ConnectionPill({ state, handle }: Props) {
const { label, tone } = COPY[state]
return (
<span className="inline-flex items-center gap-1.5 text-xs text-fg-64">
<StatusDot variant={tone} size="sm" />
<span className="text-fg-80">{label}</span>
{handle ? <span className="text-fg-48">· {handle}</span> : null}
</span>
)
}
```
Wire `state` from `getIntegrationStatus()` — `ready === true` → `"ready"`, `code === "integration_not_connected"` → `"needs_connect"`, `code === "integration_needs_reauth"` → `"needs_reauth"`. See app-builder-sdk skill for the helper.
### `src/client/components/header-bar.tsx`
```tsx
import { Button, StatusDot } from "@holaboss/ui"
import { Plus } from "lucide-react"
import type { ReactNode } from "react"
type Props = {
title: string
subtitle?: string
rightSlot?: ReactNode
onCompose?: () => void
}
export function HeaderBar({ title, subtitle, rightSlot, onCompose }: Props) {
return (
<header className="px-10 pt-12 pb-8">
<div className="flex items-center gap-3">
<div className="flex min-w-0 flex-1 items-center gap-2.5">
<h1
className="font-serif text-[22px] leading-none text-foreground"
style={{ fontFamily: "'Source Serif 4', serif", fontWeight: 500 }}
>
{title}
</h1>
<StatusDot variant="success" size="sm" pulse />
</div>
{rightSlot}
<Button
variant="ghost"
size="sm"
onClick={onCompose}
className="h-7 gap-1.5 px-2 text-xs text-fg-64 hover:text-foreground"
>
<Plus className="size-3" />
Add draft
</Button>
</div>
{subtitle ? (
<p className="mt-2 truncate text-xs text-fg-48">{subtitle}</p>
) : null}
</header>
)
}
```
### `src/client/components/status-badge.tsx`
```tsx
import { StatusDot } from "@holaboss/ui"
// REPLACE this union with your resource's state machine.
type MyStatus = "draft" | "scheduled" | "sent" | "edited" | "failed"
// REPLACE this map: one entry per state with its label and dot variant.
// Use `success` for completed/healthy, `info` for in-flight/scheduled,
// `muted` for inert/draft, `warning` for soft problems, `destructive`
// for hard failures.
const MAP: Record<MyStatus, { label: string; dot: "success" | "warning" | "destructive" | "muted" | "info" }> = {
draft: { label: "Draft", dot: "muted" },
scheduled: { label: "Scheduled", dot: "info" },
sent: { label: "Sent", dot: "success" },
edited: { label: "Edited", dot: "info" },
failed: { label: "Failed", dot: "destructive" },
}
export function StatusBadge({ status }: { status: MyStatus }) {
const { label, dot } = MAP[status]
return (
<span className="inline-flex items-center gap-1 text-[11px] text-fg-64">
<StatusDot variant={dot} size="sm" />
{label}
</span>
)
}
```
## Shape 1: queue / feed (canonical, fully bundled)
The full implementation is bundled at `reference/messaging-dashboard/src/client/` next to this skill. Two files vary per app — read them directly from the bundled reference:
- `routes/index.tsx` — page composition (~100 lines). Sets up the 3-region layout: header → attention strip → grouped sections. Read this whole file before copying.
- `components/messages-table.tsx` — the row + rail + attention list (~150 lines). The hardest file; spent the most iteration. Read this whole file before copying.
- `lib/sample-data.ts` — mock data with the `MessageRow` shape (`channel / text / status / bucket / timeLabel / authorHandle / errorReason`). **Replace this file entirely** with TanStack Start server functions that read from your `app.resource()` rows.
What to swap when copying shape 1:
| File | Change | Keep |
|---|---|---|
| `lib/sample-data.ts` | Replace entirely with server functions; rename to `data.ts`. | The row shape — your data should map to the same field set, or the table needs JSX changes too. |
| `routes/index.tsx` | Page title (`"Outgoing"`), subtitle, `nowLabel` (real current time), day-divider labels. | The 3-region structure (header → attention → grouped sections), `max-w-3xl`, spatial sketch comment, useMemo grouping. |
| `messages-table.tsx` | Column meta layout (`#{channel} · author · time`), body field, error-reason placement. | 3-col grid (`64px_16px_1fr_auto`), rail (`bg-fg-32`), marker treatment, attention strip styling. |
| `status-badge.tsx` | `MAP` lookup → your states. | Component shape. |
| `header-bar.tsx`, `connection-pill.tsx`, `__root.tsx`, `app.css` | nothing. | everything. |
## Shape 2: dense table (CRM / log / ticket list)
When the data is naturally rows-and-columns and the user scans like a spreadsheet, replace shape-1's `messages-table.tsx` with the `<Table>` primitive. Header + connection pill + `app.css` setup stay.
```tsx
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Badge } from "@holaboss/ui"
import { StatusBadge } from "./status-badge"
export function RecordsTable({ rows }: { rows: MyRow[] }) {
return (
<Table className="text-[13px]">
<TableHeader>
<TableRow className="text-fg-48">
<TableHead className="w-[180px] pl-6">Name</TableHead>
<TableHead>Email</TableHead>
<TableHead className="w-[140px]">Owner</TableHead>
<TableHead className="w-[120px]">Status</TableHead>
<TableHead className="w-[140px] text-right pr-6">Last touch</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<TableRow key={row.id} className="hover:bg-muted/40">
<TableCell className="pl-6 text-foreground">{row.name}</TableCell>
<TableCell className="text-fg-64">{row.email}</TableCell>
<TableCell className="text-fg-64">{row.owner}</TableCell>
<TableCell><StatusBadge status={row.status} /></TableCell>
<TableCell className="text-right text-fg-64 tabular-nums pr-6">{row.lastTouchLabel}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)
}
```
Layout shape: drop the time-rail; keep `max-w-3xl` (or bump to `max-w-5xl` if 5+ columns). Day-divider sections from shape 1 become optional — usually one flat table is fine.
## Shape 3: kanban (status board)
When rows move between named statuses and the user drags between them. Replace shape-1's main column with horizontally-arranged status columns. Header + connection pill + `app.css` stay.
```tsx
import { Card } from "@holaboss/ui"
import { StatusBadge } from "./status-badge"
const COLUMNS = ["draft", "scheduled", "sent", "failed"] as const
export function KanbanBoard({ rows }: { rows: MyRow[] }) {
const byStatus = COLUMNS.map((status) => ({
status,
rows: rows.filter((r) => r.status === status),
}))
return (
<div className="grid grid-cols-4 gap-3 px-10 pb-12">
{byStatus.map(({ status, rows }) => (
<div key={status} className="flex flex-col gap-2">
<div className="flex items-baseline justify-between px-1">
<span className="text-[10px] tracking-wider text-fg-48 uppercase">{status}</span>
<span className="font-mono text-[10px] text-fg-32 tabular-nums">
{rows.length.toString().padStart(2, "0")}
</span>
</div>
<div className="flex flex-col gap-2">
{rows.map((row) => (
<Card key={row.id} size="sm" className="cursor-pointer hover:bg-muted/40">
<div className="px-3 py-2">
<div className="text-[11px] text-fg-48">#{row.channel}</div>
<p className="mt-1 line-clamp-3 text-sm leading-snug text-fg-80">{row.text}</p>
<div className="mt-2">
<StatusBadge status={row.status} />
</div>
</div>
</Card>
))}
</div>
</div>
))}
</div>
)
}
```
Layout shape: change `max-w-3xl` on the outer container to `max-w-6xl` for breathing room. Drop the attention strip (failed rows surface naturally in the "failed" column).
## Shape 4: single-resource detail / form
For workflows where the user edits one resource at a time (settings, single-record CRM contact, single bookmark editor). Replace shape-1's main column with a `<Field>`-based form. Header + connection pill + `app.css` stay.
```tsx
import { Button, Field, FieldDescription, FieldGroup, FieldLabel, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Textarea } from "@holaboss/ui"
export function RecordForm({ record, onSave }: { record: MyRow; onSave: (r: MyRow) => void }) {
return (
<form className="mx-auto flex max-w-2xl flex-col gap-6 px-10 pb-12">
<FieldGroup>
<Field>
<FieldLabel>Title</FieldLabel>
<Input defaultValue={record.title} />
</Field>
<Field>
<FieldLabel>Owner</FieldLabel>
<Select defaultValue={record.owner}>
<SelectTrigger><SelectValue /></SelectTrigger>
<SelectContent>
<SelectItem value="alice">Alice</SelectItem>
<SelectItem value="bob">Bob</SelectItem>
</SelectContent>
</Select>
</Field>
<Field>
<FieldLabel>Notes</FieldLabel>
<Textarea rows={6} defaultValue={record.notes} />
<FieldDescription>Markdown is supported.</FieldDescription>
</Field>
</FieldGroup>
<div className="flex justify-end gap-2">
<Button variant="ghost" type="button">Cancel</Button>
<Button type="submit">Save</Button>
</div>
</form>
)
}
```
Layout shape: tighter column (`max-w-2xl`). No attention strip; surface validation errors inline via `FieldError`.
## Shape 5: calendar week
When rows have a real `start_time` + duration that pin to a day-grid. Use `@holaboss/ui`'s `Calendar` primitive. This shape is intentionally less battle-tested — extend the base only when calendar truly fits.
```tsx
import { Calendar } from "@holaboss/ui"
export function WeekCalendar({ rows }: { rows: MyRow[] }) {
// Calendar is the base-ui primitive; for full week-view with custom
// event rendering you'll need to compose it yourself. The skeleton:
return (
<div className="px-10 pb-12">
<Calendar mode="single" />
{/* Layer events on top via absolute-positioned cards keyed by date. */}
</div>
)
}
```
## Wiring the rest of the app
Everything below is the same as the `app-builder-sdk` skill describes for any app — repeat here only for the dashboard-specific gotchas.
### Required deps in `package.json`
```json
{
"dependencies": {
"@holaboss/app-builder-sdk": "latest",
"@holaboss/ui": "latest",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"lucide-react": "^0.542.0"
},
"devDependencies": {
"@tailwindcss/vite": "^4.2.1",
"@vitejs/plugin-react": "^5.0.0",
"tailwindcss": "^4.2.1",
"vite": "^6.3.0"
}
}
```
Use `"latest"` literally for the two `@holaboss/*` packages — pre-1.0 caret semver drifts.
### Required `vite.config.ts`
```ts
import tailwind from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
export default defineConfig({
plugins: [react(), tailwind()],
})
```
Without `@tailwindcss/vite`, the `@import "tailwindcss"` in `app.css` is a no-op and your custom utilities don't compile.
### `server.ts` boots BOTH MCP and the dashboard
```ts
import { startMcpServer, SqliteStateBackend, createRuntimeBrokerTransport } from "@holaboss/app-builder-sdk"
import { buildMyApp } from "./app.ts"
const state = new SqliteStateBackend({ path: process.env.WORKSPACE_DB_PATH! })
const bridge = createRuntimeBrokerTransport({ provider: "<provider>" })
const app = buildMyApp({ state, bridge })
// MCP for the agent
await startMcpServer({
port: Number(process.env.MCP_PORT),
app, bridge,
})
// Dashboard for the user (iframe loads this URL)
// Use TanStack Start's production build output OR Vite's dev server.
// IMPORTANT: read from the SAME SqliteStateBackend the SDK uses; never
// spin up a second DB.
import { build } from "./client/build"
Bun.serve({ port: Number(process.env.PORT), fetch: build.fetch })
```
The desktop's `AppSurfacePane` iframe resolves to `process.env.PORT` — whatever you serve there is what the user sees.
## Required setup checklist (lint-enforced)
The register-time lint rejects dashboard apps that fail any of these. Run through the list before declaring done.
| Check | Lint code (if fails) |
|---|---|
| `src/client/` has ≥3 distinct named imports from `@holaboss/ui` | `workspace_app_holaboss_ui_named_imports_too_few` |
| At least one `.css` file under `src/client/` contains `@import "tailwindcss"` | `workspace_app_missing_tailwind_compile` |
| No hex / `rgb()` / `hsl()` / `oklch()` literals in `src/client/**/*.css` | `workspace_app_parallel_design_system` |
| No custom `--<token>:` definitions in CSS (passthroughs like `--mine: var(--background)` allowed) | `workspace_app_parallel_design_system` |
If any lint fires, the runtime returns the file + line + suggested fix. Don't try to bypass — read the message and fix the root cause.
## What you may NOT do (read once, internalize)
These are hard rules. The lint catches some; the rest are caught by review (or by the user noticing the dashboard looks alien).
- **No `font-bold` / `font-semibold` / `font-extrabold` / inline `style={{ fontWeight: ... }}`.** Design system clamps all of those to 500. Hierarchy comes from **size** (`text-2xl` for hero numbers, `text-base` for headings, `text-xs` for labels) and **color** (`text-foreground` → `text-fg-80` → `text-fg-64` → `text-fg-48`).
- **No hex / `rgb()` / `oklch()` literals anywhere.** Lint rejects in CSS; review catches in JSX. Use tokens: `bg-background`, `bg-card`, `bg-muted`, `text-foreground`, `text-fg-{12,16,32,48,64,80,92}`, `border`, `border-warning`, `bg-warning/[0.06]`, `text-primary`.
- **No second component library.** No MUI, Ant, Chakra, raw Radix, Headless UI, react-aria. The `@holaboss/ui` package wraps base-ui's shadcn-flavored primitives; that is the only allowed source.
- **No `components/ui/` directory** (shadcn-add copy). Import primitives from `@holaboss/ui` only.
- **No `bg-gradient-*` on cards, no `hover:shadow-*`, no `hover:-translate-y-*` lift effects.** Subtle hover via `hover:bg-muted/40` only.
- **No per-app theme toggle.** Theme is workspace-level; the app inherits via CSS variables.
- **No custom CSS files beyond `app.css`** (and `app.css` must contain only `@import "tailwindcss"` + `@source`, possibly empty `@layer` blocks).
- **No KPI strip "because dashboards usually have them".** Add stat cards only when the user genuinely tracks ≥3 comparable numbers that need to sit side-by-side. The single count of "5 queued" goes in the subtitle, not in a card.
- **No sidebar "because dashboards usually have them".** Add one only when the user has a genuine second navigation axis that must stay on screen (multi-channel chat, multi-project switcher).
- **No `Promise.all` rendering gate.** Each card / table / chart renders the moment its own data lands, with `Skeleton` during fetch and `EmptyState` if empty. A 0.5s skeleton beats a 4s blank page.
## What you SHOULD do
- **Read `reference/messaging-dashboard/` end-to-end** (it lives next to this skill — 4 component files, 1 lib file, 1 routes file). Even if your shape isn't queue/feed, the patterns transfer.
- **Spend 30 seconds on a one-line spatial sketch BEFORE writing JSX.** Single sentence: "Header strip + grouped sections of rows" or "Header + 4-column kanban". If you can't say it in one sentence, pick from the shape catalog above.
- **Replace `lib/sample-data.ts` with TanStack Start server functions** that read from the SDK's `SqliteStateBackend` (the table `app.resource()` declared). Never spin up a second DB. Never call MCP tools from the dashboard.
- **Wire `ConnectionPill` to `getIntegrationStatus()`** (helper from `@holaboss/app-builder-sdk`). The four `state` values map directly to readiness codes.
- **Test in both light AND dark.** Workspace theme can be either; the dashboard inherits via `[data-theme]`. Set `data-theme="holaos-dark"` on `<html>` to verify dark renders correctly.
## Examples
```
User: "Build a GitHub work tracker dashboard"
→ Shape 1 (queue / feed). Rows = issues + PRs, grouped by today / this week / older.
Status mapping: open → info, in_progress → success, closed → muted, failed → destructive.
Replace `sample-data.ts` with a server function reading from your `app.resource("issue")` rows.
User: "Make me a Notion page tracker"
→ Shape 2 (dense table). One row per page, columns: title / database / author / last-edited / status.
No attention strip; just one flat sortable table.
User: "I want to see my Linear issues organized by status"
→ Shape 3 (kanban). Columns: backlog / todo / in-progress / done / canceled. Cards have title + assignee + priority.
User: "I want to manage my Mailchimp campaigns"
→ Shape 1 (queue / feed) grouped by send time — campaigns are time-ordered drafts → scheduled → sent, exactly the messaging metaphor.
User: "I want a calendar of my upcoming gcal events"
→ Shape 5 (calendar week). Compose from `Calendar` primitive; this is the least-tested shape, expect to iterate.
```
## When you're done
Run through this list — if any item is uncertain, fix before declaring done:
1. `bun install` in the app dir → exit 0
2. `bun run server.ts` → "MCP server listening on :<port>" AND dashboard responds on `:$PORT`
3. `curl http://localhost:<PORT>/` returns a TanStack Start HTML response, NOT the SDK's "headless module" placeholder (search for `headless module` in the response body)
4. Open the dashboard in the desktop iframe. Visually:
- Fonts are Inter + Source Serif 4 (NOT Times / system-ui)
- Connection pill shows correct state (Connected / Reauth / Not connected)
- Empty state renders when filtered to a status with no rows
- Hover affordances on rows (subtle bg shift, no shadow lift)
- Light mode AND dark mode both look intentional (set `data-theme="holaos-dark"` on `<html>` to test)
5. The dashboard looks like the rest of the workspace (same fonts, borders, radii, card surface color). If it looks alien, you've broken a token import, imported from outside `@holaboss/ui`, or redefined a primitive.
If all 5 pass, you're done. **Do not invoke `interface-design`.** The build pass should already produce shipping-quality output via this skill + the bundled reference + the register-time lints.
If you later receive an `[Auto-queued post-build polish pass]` input for this app (the runtime queues one when a binding completes and unblocks `pendingIntegrations`), re-enter **this** skill — not `interface-design` — and re-evaluate `src/client/` against the bundled reference now that real data is wired in. That second pass is the safety net for cases the build-time agent finished before the integrations were connected, not a license to add chrome that this skill didn't already endorse.More SEO & Marketing skills
ai-video-generation
skills-101/superpowers
Generate AI videos with Google Veo, Seedance 2.0, HappyHorse, Wan, Grok and 40+ models via inference.sh CLI. Models: Veo 3.1, Veo 3, Seedance 2.0, HappyHorse 1.0, Wan 2.5, Grok Imagine Video, OmniHuman, Fabric, HunyuanVideo. Capabilities: text-to-video, image-to-video, reference-to-video, video editing, lipsync, avatar animation, video upscaling, foley sound. Use for: social media videos, marketing content, explainer videos, product demos, AI avatars. Triggers: video generation, ai video, text to video, image to video, veo, animate image, video from image, ai animation, video generator, generate video, t2v, i2v, ai video maker, create video with ai, runway alternative, pika alternative, sora alternative, kling alternative, seedance, happyhorse
ai-image-generation
skills-101/superpowers
Generate AI images with GPT-Image-2, FLUX, Gemini, Grok, Seedream, Reve and 50+ models via inference.sh CLI. Models: GPT-Image-2, FLUX Dev LoRA, FLUX.2 Klein LoRA, Gemini 3 Pro Image, Grok Imagine, Seedream 4.5, Reve, ImagineArt. Capabilities: text-to-image, image-to-image, inpainting, LoRA, image editing, upscaling, text rendering. Use for: AI art, product mockups, concept art, social media graphics, marketing visuals, illustrations. Triggers: flux, image generation, ai image, text to image, stable diffusion, generate image, ai art, midjourney alternative, dall-e alternative, text2img, t2i, image generator, ai picture, create image with ai, generative ai, ai illustration, grok image, gemini image, gpt image, openai image, chatgpt image
ai-avatar-video
skills-101/superpowers
Create AI avatar and talking head videos via inference.sh CLI. Recommended: P-Video-Avatar (fastest, cheapest, built-in TTS). Also: OmniHuman, Fabric, PixVerse. Audio: Inworld TTS-2 (100+ languages, emotion steering for characters), ElevenLabs, Kokoro. Capabilities: audio-driven avatars, text-to-avatar, lipsync videos, talking head generation, virtual presenters, UGC content. Use for: AI presenters, explainer videos, virtual influencers, dubbing, marketing videos, UGC ads, gaming avatars, NPC dialogue. Triggers: ai avatar, talking head, lipsync, avatar video, virtual presenter, ai spokesperson, audio driven video, heygen alternative, synthesia alternative, talking avatar, lip sync, video avatar, ai presenter, digital human, ugc, ugc video, ugc ad, avatar ugc

