sveltekit-component-cli
v1.2.0
Published
CLI tool for generating SvelteKit components
Maintainers
Readme
SvelteKit Component CLI 🚀
A powerful, professional CLI tool for generating consistent Svelte 5 components with runes, TypeScript, Tailwind CSS, testing, and Storybook integration.
✨ Features
- 🚀 Svelte 5 Ready - Uses the latest runes system ($state, $props, $derived)
- 🎯 Consistent Component Structure - Generate standardized components that follow best practices
- ⚡ TypeScript Support - Fully typed components with intelligent prop handling
- 🎨 Tailwind CSS Integration - Beautiful, responsive styling out of the box
- 🧪 Automatic Test Generation - Vitest/Testing Library tests for every component
- 📚 Storybook Stories - Interactive documentation and component showcase
- 🔧 Team Configuration - Shared settings via
.sveltegenrc.json - 📁 Smart File Organization - Organized component folders with index files
- 🚀 Interactive CLI - Guided component creation with intelligent prompts
🚀 Quick Start
Installation
# Install globally
npm install -g sveltekit-component-cli
# Or use with npx (no installation required)
npx sveltekit-component-cli generate ButtonBasic Usage
# Initialize configuration
svelte-gen init
# Generate a simple component
svelte-gen generate Button
# Generate component with props
svelte-gen generate Card --props "title:string,isActive:boolean=false,count:number"
# Generate in specific directory
svelte-gen generate Header -d src/components/layout
# Skip test or story generation
svelte-gen generate Modal --no-test --no-story📖 Commands
generate (alias: g)
Generate a new SvelteKit component with all associated files.
svelte-gen generate <ComponentName> [options]Options:
-t, --type <type>- Component type (component, page, layout) [default: component]-d, --directory <dir>- Target directory [default: src/lib/components]--no-test- Skip test file generation--no-story- Skip Storybook story generation--props <props>- Component props (comma-separated)
Props Format:
# Basic props
--props "title:string,count:number"
# Props with defaults
--props "title:string='Hello',isActive:boolean=false,items:number=0"
# Mixed props
--props "name:string,age:number=18,isVisible:boolean=true"init
Initialize team configuration file.
svelte-gen initCreates .sveltegenrc.json with your team's preferred defaults.
list (alias: ls)
List available component templates.
svelte-gen list🚀 Svelte 5 Features
Modern Runes System
Components are generated using Svelte 5's new runes:
$props()- Modern prop declaration with TypeScript support$state()- Reactive state management$derived()- Computed values and dynamic classes{@render children?.()}- New slot syntax for better composition
📁 Generated Structure
When you run svelte-gen generate Button --props "label:string,variant:string='primary'", you get:
src/lib/components/Button/
├── Button.svelte # Main component
├── Button.test.ts # Vitest tests
├── Button.stories.ts # Storybook stories
└── index.ts # Export fileComponent Example
Button.svelte (Svelte 5 with runes):
<script lang="ts">
let { label, variant = 'primary' }: { label: string; variant?: string } = $props();
// Component state using $state rune
let isHovered = $state(false);
// Derived values using $derived rune
let containerClasses = $derived(`
flex flex-col gap-3 p-6 bg-white dark:bg-gray-800
border border-gray-200 dark:border-gray-700 rounded-lg
shadow-sm hover:shadow-md transition-all duration-200 ease-in-out
hover:-translate-y-0.5 max-w-full min-w-0 font-sans
focus-within:ring-2 focus-within:ring-blue-500 focus-within:ring-offset-2
${isHovered ? 'shadow-md' : ''}
`.trim().replace(/\s+/g, ' '));
</script>
<div
class={containerClasses}
onmouseenter={() => isHovered = true}
onmouseleave={() => isHovered = false}
>
<h1 class="text-xl font-semibold text-gray-900 dark:text-gray-100 leading-tight m-0">
Button Component
</h1>
<div class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed m-0">
<span class="font-medium text-gray-700 dark:text-gray-300">label:</span>
<span class="font-mono bg-gray-100 dark:bg-gray-700 px-1.5 py-0.5 rounded text-xs ml-1">
{label}
</span>
</div>
<div class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed m-0">
<span class="font-medium text-gray-700 dark:text-gray-300">variant:</span>
<span class="font-mono bg-gray-100 dark:bg-gray-700 px-1.5 py-0.5 rounded text-xs ml-1">
{variant}
</span>
</div>
</div>⚙️ Configuration
Create .sveltegenrc.json in your project root:
{
"defaults": {
"directory": "src/lib/components",
"test": true,
"story": true,
"type": "component"
},
"templates": {
"component": "component.svelte",
"page": "page.svelte",
"layout": "layout.svelte"
}
}🎨 Styling with Tailwind
Components are generated with professional Tailwind CSS classes including:
- Responsive Design - Mobile-first approach
- Dark Mode Support - Automatic dark/light theme handling
- Interactive States - Hover, focus, and active states
- Accessibility - ARIA-compliant focus management
- Modern Design - Card-based layouts with subtle shadows
- Animation - Smooth transitions and micro-interactions
Key Tailwind Features Used:
/* Modern card design */
bg-white dark:bg-gray-800
border border-gray-200 dark:border-gray-700
rounded-lg shadow-sm hover:shadow-md
/* Smooth interactions */
transition-all duration-200 ease-in-out
hover:-translate-y-0.5
/* Focus accessibility */
focus-within:ring-2 focus-within:ring-blue-500🧪 Testing Integration
Generated tests use modern testing practices:
Button.test.ts:
import { render, screen } from '@testing-library/svelte';
import { describe, it, expect } from 'vitest';
import Button from './Button.svelte';
describe('Button', () => {
it('renders correctly', () => {
render(Button, {
props: {
label: 'test',
variant: 'primary',
}
});
expect(screen.getByText('Button Component')).toBeInTheDocument();
});
it('displays label prop correctly', () => {
const testLabel = 'test value';
render(Button, {
props: { label: testLabel }
});
expect(screen.getByText(`label: ${testLabel}`)).toBeInTheDocument();
});
});📚 Storybook Integration
Button.stories.ts:
import type { Meta, StoryObj } from '@storybook/svelte';
import Button from './Button.svelte';
const meta: Meta<Button> = {
title: 'Components/Button',
component: Button,
parameters: { layout: 'centered' },
tags: ['autodocs'],
argTypes: {
label: { control: 'text', description: 'label prop' },
variant: { control: 'text', description: 'variant prop' }
},
};
export default meta;
type Story = StoryObj<meta>;
export const Default: Story = {
args: {
label: 'Sample text',
variant: 'primary',
},
};🔧 Development
Prerequisites
- Node.js 16+
- npm or yarn
- TypeScript knowledge
Local Development
# Clone the repository
git clone <your-repo-url>
cd sveltekit-component-cli
# Install dependencies
npm install
# Build the project
npm run build
# Link for local testing
npm link
# Test the CLI
svelte-gen generate TestComponentProject Structure
sveltekit-component-cli/
├── src/
│ ├── commands/ # CLI command implementations
│ │ ├── generate.ts # Component generation logic
│ │ ├── init.ts # Configuration initialization
│ │ └── list.ts # Template listing
│ ├── utils/ # Utility functions
│ │ ├── case-utils.ts # String case conversions
│ │ ├── config.ts # Configuration management
│ │ └── prop-parser.ts # Props parsing logic
│ └── index.ts # CLI entry point
├── templates/ # Mustache templates
│ ├── component.svelte.mustache
│ ├── component.test.ts.mustache
│ └── component.stories.ts.mustache
├── dist/ # Compiled output
└── package.json🤝 Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🆘 Support
🙏 Acknowledgments
- SvelteKit team for the amazing framework
- Tailwind CSS for the utility-first CSS framework
- The open-source community for inspiration and tools
Made with ❤️ for the SvelteKit community
