xiaohongshu
xiaohongshu
frontend-design-svelte
Create distinctive, production-grade Svelte/TypeScript frontends with exceptional design quality
Full skill instructions
This skill guides the creation of distinctive, production-grade Svelte frontends that combine Svelte's reactive elegance with exceptional design quality. It integrates all design frameworks: intentional thinking, typography, color, motion, spatial composition, and anti-pattern awareness.
Before writing any code, establish intentional design direction:
The Four Critical Questions:
Deliberately reject these patterns:
Typography:
Color & Theme:
Layout & Space:
Motion:
Always use TypeScript in Svelte components:
<script lang="ts">
import type { ComponentProps } from 'svelte'
interface Props {
title: string
count: number
onAction?: () => void
}
let { title, count, onAction }: Props = $props()
</script>
$:Leverage Svelte's reactive declarations for dynamic styling and state:
<script lang="ts">
let theme: 'light' | 'dark' = $state('light')
let isHovered = $state(false)
// Reactive computed values
let backgroundColor = $derived(
theme === 'light' ? 'var(--color-bg-light)' : 'var(--color-bg-dark)'
)
let shadowIntensity = $derived(isHovered ? '0.2' : '0.1')
</script>
Svelte's scoped styles are default. Use CSS custom properties for theming:
<style>
:global(:root) {
--color-primary: #8b4513;
--color-accent: #d4a574;
--color-bg: #faf8f3;
--font-display: 'Playfair Display', serif;
--font-body: 'IBM Plex Sans', sans-serif;
--spacing-unit: 8px;
}
.card {
background: var(--color-bg);
padding: calc(var(--spacing-unit) * 3);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, var(--shadow-intensity));
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.card:hover {
--shadow-intensity: 0.15;
transform: translateY(-4px);
}
</style>
Use Svelte's built-in transitions for elegant animations:
<script lang="ts">
import { fade, fly, scale, slide } from 'svelte/transition'
import { cubicOut, elasticOut } from 'svelte/easing'
let isVisible = $state(true)
let showDetails = $state(false)
</script>
<!-- Fade in on mount -->
<div in:fade={{ duration: 300 }} out:fade={{ duration: 200 }}>
Content
</div>
<!-- Orchestrated entrance with stagger -->
<div
in:fly={{ y: 50, duration: 600, delay: 100, easing: cubicOut }}
out:fly={{ y: 20, duration: 300 }}
>
Hero section
</div>
<!-- Elastic expand on interaction -->
{#if showDetails}
<div
in:scale={{ start: 0.95, duration: 400, easing: elasticOut }}
out:scale={{ duration: 200 }}
>
Detailed content
</div>
{/if}
<!-- Slide for list items (staggered) -->
<ul>
{#each items as item (item.id)}
<li
in:slide={{ duration: 400, delay: index * 50 }}
out:slide={{ duration: 200 }}
>
{item.name}
</li>
{/each}
</ul>
Use Svelte stores for theme, animations, and global UI state:
<!-- lib/stores/theme.ts -->
import { writable, derived } from 'svelte/store'
export const isDarkMode = writable(false)
export const themeVariables = derived(isDarkMode, ($isDarkMode) => ({
bgColor: $isDarkMode ? '#1a1a1a' : '#faf8f3',
textColor: $isDarkMode ? '#f5f5f5' : '#333333',
accentColor: '#d4a574',
shadows: $isDarkMode ? 'rgba(0,0,0,0.4)' : 'rgba(0,0,0,0.1)',
}))
<!-- Usage in component -->
<script lang="ts">
import { isDarkMode, themeVariables } from '$lib/stores/theme'
</script>
<div style:background-color={$themeVariables.bgColor}>
Content
</div>
Svelte's approach to accessibility:
<script lang="ts">
let isMenuOpen = $state(false)
let focusedIndex = $state(-1)
</script>
<!-- Semantic structure -->
<nav aria-label="Main navigation">
<button
aria-expanded={isMenuOpen}
aria-controls="main-menu"
aria-label="Toggle navigation menu"
>
Menu
</button>
<ul id="main-menu" role="menubar" hidden={!isMenuOpen}>
{#each menuItems as item (item.id)}
<li role="none">
<a href={item.href} role="menuitem">
{item.label}
</a>
</li>
{/each}
</ul>
</nav>
<!-- Form accessibility -->
<form>
<label for="email">Email address</label>
<input
id="email"
type="email"
required
aria-required="true"
aria-describedby="email-hint"
/>
<small id="email-hint">We'll never share your email.</small>
</form>
Use Svelte's class directives and media queries:
<script lang="ts">
let viewport: 'mobile' | 'tablet' | 'desktop' = $state('mobile')
let windowWidth = $state(0)
$effect(() => {
if (windowWidth < 640) viewport = 'mobile'
else if (windowWidth < 1024) viewport = 'tablet'
else viewport = 'desktop'
})
</script>
<svelte:window bind:innerWidth={windowWidth} />
<div class="container" class:is-mobile={viewport === 'mobile'}>
<header class:is-compact={viewport === 'mobile'}>
<!-- Mobile-optimized header -->
</header>
</div>
<style>
.container {
padding: calc(var(--spacing-unit) * 4);
}
.container.is-mobile {
padding: calc(var(--spacing-unit) * 2);
}
header.is-compact {
font-size: 18px;
}
@media (min-width: 640px) {
header {
font-size: 24px;
}
}
</style>
Input: Feature requirements, target users, problem statement
Actions:
Deliverable: Design brief with clear direction
Input: Design brief and tone direction
Actions:
Deliverable: Design tokens in CSS variables and Svelte stores
<!-- $lib/styles/tokens.css -->
:root {
/* Typography */
--font-display: 'Playfair Display', serif;
--font-body: 'IBM Plex Sans', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
--size-display: 88px;
--size-h1: 48px;
--size-h2: 28px;
--size-body: 16px;
--size-small: 12px;
/* Colors */
--color-bg: #faf8f3;
--color-text: #2a2a2a;
--color-accent: #d4a574;
--color-accent-dark: #8b4513;
/* Motion */
--easing-out: cubic-bezier(0.16, 0.04, 0.04, 1);
--easing-elastic: cubic-bezier(0.34, 1.56, 0.64, 1);
--duration-quick: 200ms;
--duration-standard: 400ms;
--duration-slow: 600ms;
}
Input: Design tokens and feature requirements
Actions:
Deliverable: Typed component structure
<!-- lib/components/Button.svelte -->
<script lang="ts">
import { cubicOut } from 'svelte/easing'
interface Props {
variant?: 'primary' | 'secondary' | 'outline'
size?: 'small' | 'medium' | 'large'
disabled?: boolean
ariaLabel?: string
onclick?: () => void
}
let {
variant = 'primary',
size = 'medium',
disabled = false,
ariaLabel,
onclick,
}: Props = $props()
</script>
<button
class="button {variant} {size}"
{disabled}
aria-label={ariaLabel}
on:click={onclick}
in:scale={{ start: 0.95, duration: 200, easing: cubicOut }}
>
<slot />
</button>
Input: Component structure and design tokens
Actions:
Deliverable: Transition patterns and animation sequences
Input: Component library and motion patterns
Actions:
Deliverable: Responsive component library
Input: Design tokens and component library
Actions:
Deliverable: Fully themed component system
Input: All components and interactions
Actions:
Deliverable: Fully accessible component library
Input: Complete feature implementation
Actions:
will-change, GPU acceleration)Deliverable: Production-ready application
Use these checks before finalizing any design or component:
Typography:
Color & Theme:
Layout & Space:
Motion & Animation:
Svelte-Specific:
<script lang="ts">$:<script lang="ts">
import { fly, scale } from 'svelte/transition'
import { cubicOut, elasticOut } from 'svelte/easing'
let isHovered = $state(false)
interface Props {
title: string
description: string
image?: string
}
let { title, description, image }: Props = $props()
</script>
<article
in:fly={{ y: 40, duration: 500, easing: cubicOut }}
class="card"
on:mouseenter={() => (isHovered = true)}
on:mouseleave={() => (isHovered = false)}
>
{#if image}
<img src={image} alt="" class="card-image" />
{/if}
<div class="card-content">
<h3>{title}</h3>
<p>{description}</p>
{#if isHovered}
<button
in:scale={{ start: 0.8, duration: 300, easing: elasticOut }}
class="card-action"
>
Learn More
</button>
{/if}
</div>
</article>
<style>
.card {
background: var(--color-bg);
border-radius: 12px;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
cursor: pointer;
}
.card:hover {
transform: translateY(-12px);
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.15);
}
.card-image {
width: 100%;
height: 240px;
object-fit: cover;
}
.card-content {
padding: calc(var(--spacing-unit) * 3);
}
h3 {
font-family: var(--font-display);
font-size: var(--size-h2);
font-weight: 700;
margin: 0 0 calc(var(--spacing-unit) * 2) 0;
color: var(--color-text);
}
p {
font-family: var(--font-body);
font-size: var(--size-body);
line-height: 1.6;
color: rgba(0, 0, 0, 0.7);
margin: 0;
}
.card-action {
margin-top: calc(var(--spacing-unit) * 2);
padding: calc(var(--spacing-unit) * 1.5) calc(var(--spacing-unit) * 3);
background: var(--color-accent);
color: white;
border: none;
border-radius: 6px;
font-family: var(--font-body);
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease-out;
}
.card-action:hover {
background: var(--color-accent-dark);
transform: scale(1.05);
}
</style>
<script lang="ts">
import { slide } from 'svelte/transition'
import { cubicOut } from 'svelte/easing'
interface ListItem {
id: string
label: string
}
interface Props {
items: ListItem[]
}
let { items }: Props = $props()
</script>
<ul class="list">
{#each items as item, index (item.id)}
<li
in:slide={{
duration: 400,
delay: index * 50,
easing: cubicOut,
}}
out:slide={{ duration: 200 }}
>
<span class="list-number">{index + 1}</span>
<span class="list-label">{item.label}</span>
</li>
{/each}
</ul>
<style>
.list {
list-style: none;
padding: 0;
margin: 0;
}
li {
display: flex;
align-items: center;
padding: calc(var(--spacing-unit) * 2) calc(var(--spacing-unit) * 3);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease-out;
}
li:hover {
background-color: rgba(0, 0, 0, 0.02);
}
.list-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
margin-right: calc(var(--spacing-unit) * 2);
background: var(--color-accent);
color: white;
border-radius: 50%;
font-weight: 600;
font-size: 13px;
}
.list-label {
font-family: var(--font-body);
font-size: var(--size-body);
color: var(--color-text);
}
</style>
$derived for computed values and $effect for side effectssvelte/transition for all animations:global() sparinglywritable for theme, animation state, and global UI statebind: carefully, memoize expensive computations with $derivedReady to build distinctive, intentional Svelte frontends? Start with Phase 1: Design Thinking & Intent Definition. Never skip the pre-coding work.
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience