一键导入
dashboard-design
Design judgment and UI copy for building Vesta dashboard widgets that feel considered rather than templated, within the fixed design system.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Design judgment and UI copy for building Vesta dashboard widgets that feel considered rather than templated, within the fixed design system.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use for any Microsoft account, personal or work (Outlook.com, Hotmail, Live, Microsoft 365); preferred over email-client for Microsoft accounts. Graph-based mail (read/send/reply/forward, drafts, flag/categorize, move/archive, folders, attachments, block senders), calendar and meetings, Microsoft Teams (chats, channels, presence), and new-mail/Teams notifications. Requires daemon.
Browse, navigate, click, fill forms, screenshot, or scrape web pages with a stealth (Camoufox) browser.
Use before building or modifying the user's dashboard: widgets, pages, layouts, custom UI. Understand what the user wants, design it, write a spec, then dispatch the dashboard-builder to build it.
Use when someone who doesn't have their own vesta asks what vesta is, how to get one, or hints they want in. Vesta is invite-only: you gatekeep and build desire through scarcity, draw out what they want, then sell vesta as indispensable to their goals and set them up end-to-end in chat. Not for the owner, who already has one.
Talk to vestad, the host daemon that runs this container. Register a background service to get a port, build public URLs, update vestad to the latest release, check its version, and read gateway logs. Use when a skill needs an inbound port or a shareable link, when the user asks to update Vesta, or when debugging gateway/container issues.
Self-improvement and memory curation; used nightly by the dreamer or anytime.
| name | dashboard-design |
| description | Design judgment and UI copy for building Vesta dashboard widgets that feel considered rather than templated, within the fixed design system. |
| license | MIT (anthropics/claude-code), adapted and extended |
How to build dashboard widgets that feel considered. You work inside a fixed system: the fonts, base theme, and color tokens are synced from the main app (index.css, shadcn), and the density rules are set. You do not choose fonts or invent palettes. Your material is hierarchy, composition, structure, color as signal, motion, restraint, and copy. Make deliberate choices that fit this specific data, not the templated defaults you would reach for on any dashboard.
Each card leads with a single primary value, its reason to exist, set large; everything else is secondary and muted. If a widget has two equally loud numbers, split it into two or demote one. The eye should land in one place, then travel to the supporting detail.
Build the chrome from shadcn components: Button, Card, Tabs, Dialog, Sheet, Input, and the rest, using their built-in variants and sizes (density-adjusted). Compose existing components before writing anything custom, and reach for a custom component only when shadcn genuinely cannot express what the spec needs. When you do go custom, build it from the same tokens, spacing, and density so it reads as part of the set, not bolted on.
A high density command center, not a roomy app: default shadcn sizes are too large, so override them so a lot fits without feeling cramped.
text-sm; labels text-xs text-muted-foreground (do not lower the opacity, it washes out on the dark theme); large numbers only text-lg or text-xl font-semibold.rounded-2xl bg-secondary p-3 text-sm; dense widgets p-2; grid gap-2; inside widgets space-y-2. Combine related info into single rows.<Button size="sm" className="h-8 px-2 text-xs">; inputs h-8 text-xs.col-span-1 is the default and ~90% of widgets (metrics, counters, trackers); col-span-2 only for charts that need width; col-span-full almost never.A widget-heavy page is a responsive auto-fill grid: grid gap-2 grid-cols-[repeat(auto-fill,minmax(280px,1fr))].
The dashboard renders inside an iframe, in a card that sits in the main app's layout, on both desktop and mobile. It never owns the viewport: the frame is wide on desktop and narrow on a phone. Design every widget and page for both from the start, not desktop first with mobile bolted on afterward. The grid reflows to a single column on a narrow frame, text and controls stay legible and tappable, and nothing overflows the card. The content frame clips horizontal overflow rather than scrolling it, because on the mobile app the user swipes sideways to move between the dashboard and the chat and logs tabs, so a page that scrolled sideways would swallow that swipe. A widget wider than the frame is cut off, not scrollable: size every table, chart, and wide row to the frame and let it reflow, never rely on horizontal scroll. Do not assume full-screen chrome or fixed viewport heights, you live inside a card.
Prefer a single responsive layout, but when making one layout serve both gets contorted, it is fine to branch: render a distinct arrangement per viewport with useIsMobile() from @/hooks/use-mobile (the parent app also passes isMobile through parent-bridge). A clean desktop view and a clean mobile view beat one tangled layout that half works on each.
Progressive disclosure is a priority, not a nice-to-have, on a surface this dense, embedded, and mobile-friendly: show the essential at a glance and reveal detail on demand. It is what keeps every widget calm and what makes the narrow frame work. Examples:
... button), not crowded onto the face of the card.Structure follows the design system. Buttons, cards, inputs, borders, and surfaces use the semantic Tailwind tokens that are automatically synced from the main app into index.css (primary, secondary, muted, accent, destructive, warning, border, and the card/background/foreground families), so the dashboard matches the wider app and stays in step with its theme. You never edit index.css; those tokens are always current, build against them.
Raw scales (text-green-500, bg-amber-100) are fine where you need a color a token does not cover: a value that is up or down, a chart series, a status dot, a category. Reserve them for signal, not decoration, and use them the same way across every widget so the user learns them once. A widget washed in one accent has no signal left to give.
Structural devices (numbering, eyebrows, dividers, labels) should encode something true about the content, not decorate it. Numbered markers (01 / 02 / 03) belong only when the content actually is a sequence: a real process or an ordered timeline where order carries information the reader needs. Question whether a device makes sense before using it.
In a dense card a chart is a glance, not a report. Drop gridlines, legends, and axis clutter; label only the value that matters. A sparkline or a few bars beside the number usually beats a full chart. Match the chart's color to its meaning, not to a default palette.
A dense, minimal surface needs precision in spacing, type scale, and detail rather than more elements. Elegance is executing the chosen layout well.
A new widget should look like it belongs next to the others on its page: the same card shape, label style, icon treatment, and spacing. Read the neighboring widgets and match them before inventing anything. Consistency is how the dashboard reads as one product rather than a pile of parts.
Design the loading, empty, and error states, not just the happy path. Loading is a skeleton shaped like the widget, not a spinner dropped in a tiny card. Empty is a short line of direction, not blank space. Error says what went wrong and how to fix it.
Use animation deliberately and rarely. A subtle state transition or a single load reveal can help; scattered micro-interactions read as AI-generated, and less is usually more. Respect reduced motion.
Spend your boldness in one place and keep everything around it quiet and disciplined; cut any decoration that does not serve the data. Build to a quality floor without announcing it: responsive down to mobile, visible keyboard focus, reduced motion respected. Critique your own work as you build. Consider Chanel's advice: before you finish, look again and remove one thing.
Be careful with selector specificity: it is easy to generate classes that cancel each other out (a type-based selector like .section fighting an element-based one), which shows up most in the paddings and margins between sections.
Words in a widget exist to make it easier to understand and use. They are design material, not decoration. Bring the same intention to copy that you bring to spacing.