Welcome to Vielzeug
Vielzeug (German for "many tools") is a collection of lightweight, framework-agnostic TypeScript utilities for modern web development. Each package is designed to solve one problem exceptionally well, with minimal dependencies and maximum type safety.
The Vielzeug Ecosystem
🔧 Core & Utilities
Perfect starting point for any project:
| Package | Description | Size |
|---|---|---|
| Toolkit | 100+ essential utilities for arrays, objects, strings, async operations, and more | Tree-shakeable |
| Logit | Beautiful console logging with colors, timestamps, and log levels | 1.8 KB |
💾 Data & State
Client-side data management made simple:
| Package | Description | Size |
|---|---|---|
| Deposit | Type-safe IndexedDB & LocalStorage wrapper with schemas, TTL, and migrations | 3.4 KB |
| Fetchit | Modern HTTP client with smart caching, deduplication, and query management | 3.0 KB |
| Stateit | Tiny reactive state management with subscriptions and async support | 0.9 KB |
🎨 Frontend & Forms
Build better user interfaces:
| Package | Description | Size |
|---|---|---|
| Craftit | Web Components framework with reactive state and DOM reconciliation | 3.4 KB |
| Formit | Form state management with validation, dirty tracking, and file uploads | 2.4 KB |
| Validit | Schema validation with async support and detailed error messages | 2.4 KB |
| i18nit | Internationalization with pluralization and locale-aware formatting | 1.6 KB |
🏗️ Architecture & Security
Structure your application properly:
| Package | Description | Size |
|---|---|---|
| Permit | Role-Based Access Control (RBAC) with dynamic rules and wildcards | 1.0 KB |
| Routeit | Client-side routing with middleware, nested routes, and type-safe params | 2.1 KB |
| Wireit | Dependency injection container with async support and scoped instances | 1.4 KB |
Quick Start
Installation
Each package can be installed independently:
pnpm add @vielzeug/toolkitnpm install @vielzeug/toolkityarn add @vielzeug/toolkitYour First Lines
import { debounce, groupBy } from '@vielzeug/toolkit';
import { createStore } from '@vielzeug/stateit';
import { createHttpClient } from '@vielzeug/fetchit';
// Debounce search input
const search = debounce((query: string) => {
console.log('Searching for:', query);
}, 300);
// Reactive state management
const store = createStore({ count: 0 });
store.subscribe((state) => console.log(state.count));
store.set((s) => ({ count: s.count + 1 }));
// HTTP client with caching
const http = createHttpClient({ baseUrl: '/api' });
const users = await http.get('/users');Common Use Cases
Building a Form
import { createForm } from '@vielzeug/formit';
import { v } from '@vielzeug/validit';
const userSchema = v.object({
email: v.string().email(),
age: v.number().min(18),
});
const form = createForm({
fields: {
email: { value: '', validators: (v) => userSchema.shape.email.parse(v) },
age: { value: 0, validators: (v) => userSchema.shape.age.parse(v) },
},
});
await form.submit(async (data) => {
await fetch('/api/users', { method: 'POST', body: data });
});Fetching & Caching Data
import { createHttpClient, createQueryClient } from '@vielzeug/fetchit';
const http = createHttpClient({ baseUrl: '/api' });
const queryClient = createQueryClient({ staleTime: 5000 });
// Cached and deduplicated
const user = await queryClient.fetch({
queryKey: ['user', userId],
queryFn: () => http.get(`/users/${userId}`),
});
// Invalidate cache when data changes
queryClient.invalidate(['user']);Permission Management
import { createPermit } from '@vielzeug/permit';
const permit = createPermit();
permit.register('admin', 'posts', ['create', 'update', 'delete']);
permit.register('user', 'posts', ['create']);
const canDelete = permit.can(currentUser, 'posts', 'delete');Reactive State
import { createStore } from '@vielzeug/stateit';
const store = createStore({ todos: [], filter: 'all' });
// Subscribe to specific values
store.subscribe(
(state) => state.filter,
(filter) => console.log('Filter changed:', filter),
);
// Update state
store.set((state) => ({
todos: [...state.todos, { id: 1, text: 'Learn Vielzeug' }],
}));Design Philosophy
1. Simple Over Clever
We prefer straightforward, readable code over clever abstractions. If you can understand what's happening at a glance, we've done our job.
2. TypeScript First
Every package is built with TypeScript from the ground up. Type inference works out of the box, and you get autocomplete everywhere.
3. Zero/Minimal Dependencies
Most packages have 0-1 dependencies. This means:
- Smaller bundle sizes
- Fewer security vulnerabilities
- Less supply chain risk
- Faster installs
4. Framework Agnostic
Use Vielzeug with any framework (or no framework):
- ✅ React
- ✅ Vue
- ✅ Svelte
- ✅ Angular
- ✅ Vanilla JS/TS
5. Production Ready
All packages are:
- ✅ Battle-tested in production
- ✅ Fully tested (>95% coverage)
- ✅ Actively maintained
- ✅ Semantically versioned
Package Comparison
How does Vielzeug stack up?
| Feature | Vielzeug | Lodash | Zod + RHF + TanStack | Native |
|---|---|---|---|---|
| Bundle Size | 0.1-1 KB per package | 24 KB (full) | 40+ KB combined | 0 KB |
| TypeScript | Native, first-class | Via @types | Good | Manual |
| Dependencies | 0-1 per package | 0 | Many | N/A |
| Tree-shakeable | Yes, by default | lodash-es only | Varies | N/A |
| Framework | Agnostic | Agnostic | React-focused | Agnostic |
| Learning Curve | Low | Low | Medium-High | Low |
Getting Help
- 📖 Documentation: Each package has detailed docs with examples
- 💬 Discussions: Ask questions on GitHub
- 🐛 Issues: Report bugs
- 🎮 REPL: Try it online without installing
What's Next?
- Explore packages: Browse the navigation to find packages that solve your problems
- Try examples: Each package has real-world examples
- Check the REPL: Test packages in your browser without setup
- Start building: Install what you need and start coding
Ready to dive in? Start with Toolkit for general utilities, or pick a specific package for your current needs! 🚀