Welcome to The Weekly Five - your curated list of 5
exceptional open source projects I discovered this week.

Type Safety Across the Stack: How Modern TypeScript Tools Are Reshaping Web Development

The TypeScript ecosystem has matured beyond basic type checking. Today's developers are pushing type safety into every layer of their applications, from runtime validation to URL state management, transforming how we build reliable web experiences. This shift isn't just about catching bugs earlier (though it does that brilliantly). It's about creating a development workflow where your types guide you through data transformation, form handling, and state synchronization without the cognitive overhead of manual validation logic.

Top takeaways

  • Schema validation libraries like Zod and Valibot now offer complete type inference, eliminating the need to define types separately from runtime validation logic

  • Type-safe state management has expanded beyond traditional stores to include URL query parameters, making shareable application states trivial to implement

  • Framework-agnostic tools are winning mindshare by offering consistent APIs across React, Vue, Svelte, and Solid, reducing the learning curve when switching contexts

Who this issue is for

Developers building production TypeScript applications who want to eliminate runtime errors, reduce boilerplate, and maintain type safety from API boundaries to UI state.

zod

Why this made the cut: Zod has become the de facto standard for TypeScript schema validation, powering everything from API validation to form libraries across the ecosystem.

Why it matters

Zod bridges the gap between TypeScript's compile-time guarantees and JavaScript's runtime reality. When data crosses boundaries (API responses, user input, environment variables), Zod validates structure and types while automatically inferring TypeScript types from your schemas. This eliminates the duplication of writing both runtime checks and type definitions.

Key features

  • Runtime Validation: Parse unknown data and get type-safe results or detailed error messages

  • Schema Validation: Compose complex validation logic with primitives, objects, arrays, unions, and custom refinements

  • Static Types: Automatic TypeScript type inference means your schemas are your types, no manual synchronization needed

How to use

Install with npm install zod. Define schemas using Zod's chainable API:

import { z } from 'zod';

const UserSchema = z.object({
  id: z.number(),
  email: z.string().email(),
  role: z.enum(['admin', 'user']),
  metadata: z.record(z.string()).optional()
});

type User = z.infer<typeof UserSchema>;

const result = UserSchema.safeParse(apiResponse);
if (result.success) {
  // result.data is fully typed as User
}

Common patterns include validating API responses before state updates, parsing environment variables at startup with z.string().transform(), and creating reusable schema fragments with .extend() and .merge(). The .safeParse() method returns a discriminated union, making error handling explicit without throwing exceptions.

🔗 View on GitHub | GitHub stars: 43,025

valibot

Why this made the cut: Valibot challenges Zod's dominance with a modular architecture that can reduce bundle sizes by 90% while maintaining comparable functionality.

Why it matters

Bundle size matters for user experience, especially on mobile networks. Valibot's modular design means you only ship the validation logic you actually use. Unlike monolithic schema libraries, each validation function is tree-shakeable. For applications where every kilobyte counts, Valibot delivers the same type-safe validation as Zod with a fraction of the footprint.

Key features

  • Bundle Size: Starts at under 1KB and grows only with the validators you import

  • Modular: Each schema method and validation is a separate import, maximizing tree-shaking effectiveness

  • Parsing: Pipeline-based transformations let you validate, transform, and normalize data in a single pass

How to use

Install with npm install valibot. Import only what you need:

import * as v from 'valibot';

const EmailSchema = v.pipe(
  v.string(),
  v.email(),
  v.toLowerCase()
);

const ConfigSchema = v.object({
  apiUrl: v.pipe(v.string(), v.url()),
  timeout: v.optional(v.number(), 5000)
});

const config = v.parse(ConfigSchema, rawConfig);

The pipeline approach with v.pipe() makes transformations explicit and composable. Use v.optional() with default values to handle missing fields gracefully. For complex validation, v.custom() accepts any predicate function. Community tips emphasize importing from the main package (valibot) rather than deep imports to ensure optimal bundling.

🔗 View on GitHub | GitHub stars: 8,768

formisch

Why this made the cut: Formisch is the first truly framework-agnostic form library that works identically across React, Vue, Svelte, and Solid without wrapper bloat.

Why it matters

Form state management has historically been fragmented across framework ecosystems, forcing developers to relearn patterns when switching contexts. Formisch uses schema-first validation and provides a unified API that works with any reactive framework. It's headless, so you maintain complete control over markup and styling while Formisch handles state synchronization and validation timing.

Key features

  • Bundle Size: Modular architecture keeps the core under 2KB with framework adapters adding minimal overhead

  • Form Validation: Schema-driven validation with support for field-level, form-level, and async validation

  • Framework Support: First-class adapters for React, Solid, Vue, Svelte, Preact, and Qwik with identical APIs

How to use

Install the core and your framework adapter: npm install formisch @formisch/react valibot. Create a form with schema validation:

import { Field, Form, useForm } from '@formisch/react';
import * as v from 'valibot';

const SignupSchema = v.object({
  username: v.pipe(v.string(), v.minLength(3, 'Min. 3 characters')),
  email: v.pipe(v.string(), v.email('Invalid email')),
});

function SignupForm() {
  const signupForm = useForm({
    schema: SignupSchema,
  });

  return (
    <Form of={signupForm} onSubmit={(output) => console.log(output)}>
      <Field of={signupForm} path={['username']}>
        {(field) => (
          <div>
            <input {...field.props} value={field.input ?? ''} type="text" />
            {field.errors && <span>{field.errors[0]}</span>}
          </div>
        )}
      </Field>

      <Field of={signupForm} path={['email']}>
        {(field) => (
          <div>
            <input {...field.props} value={field.input ?? ''} type="email" />
            {field.errors && <span>{field.errors[0]}</span>}
          </div>
        )}
      </Field>

      <button type="submit">Sign up</button>
    </Form>
  );
}

In addition, Formisch offers several functions (called "methods") that can be used to read and manipulate the form state. These include focus, getDeepErrorEntries, getDeepErrors, getDirtyInput, getDirtyPaths, getErrors, getInput, handleSubmit, insert, isDirty, isEdited, isTouched, isValid, move, pickDirty, remove, replace, reset, setErrors, setInput, submit, swap and validate. These methods allow you to control the form programmatically.

🔗 View on GitHub | GitHub stars: 975

nuqs

Why this made the cut: nuqs solves URL state management with the same ergonomics as useState, making shareable application states effortless without complex routing libraries.

Why it matters

Modern applications increasingly need shareable state (filters, pagination, modals) that persists across page refreshes and can be bookmarked. Managing URL query parameters manually is error-prone and loses type safety. nuqs provides a useState-like interface that automatically syncs with URL search params, handles serialization, and maintains full TypeScript safety. It works with Next.js App Router, Pages Router, and React Router without abstraction leaks.

Key features

  • Type-safe: Parser-based approach ensures query params are validated and typed on read

  • React Integration: Drop-in replacement for useState with automatic URL synchronization

  • Search Params: Built-in parsers for strings, numbers, booleans, enums, arrays, and dates plus custom parser support

How to use

Install with npm install nuqs. Use useQueryState for single parameters or useQueryStates for multiple:

import { useQueryState, parseAsInteger, parseAsStringEnum } from 'nuqs';

function ProductList() {
  const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1));
  const [sort, setSort] = useQueryState('sort', 
    parseAsStringEnum(['price', 'name', 'date']).withDefault('name')
  );

  // URL updates automatically: /products?page=2&sort=price
  return (
    <div>
      <button onClick={() => setPage(p => p + 1)}>Next</button>
      <select value={sort} onChange={e => setSort(e.target.value)}>
        <option value="name">Name</option>
        <option value="price">Price</option>
      </select>
    </div>
  );
}

Parsers handle serialization and validation. Use .withDefault() to avoid null checks. For multiple related params, useQueryStates batches updates into a single navigation event. The library handles edge cases like initial server-side rendering, shallow routing, and navigation timing. Advanced patterns include creating custom parsers for complex types and using queryTypes helper to share parser configs across components.

🔗 View on GitHub | GitHub stars: 10,589

angular

Why this made the cut: Angular's latest releases have doubled down on type safety with signals, standalone components, and improved template type checking that rivals JSX.

Why it matters

Angular has transformed from the framework developers loved to criticize into a lean, modern platform with some of the strongest type safety guarantees in web development. Recent versions introduced signals (fine-grained reactivity), standalone components (no more NgModules), and template type checking that catches errors in HTML templates at compile time. For teams building large-scale applications where refactoring safety and long-term maintainability matter more than bundle size, Angular's opinionated structure and tooling prevent entire classes of bugs.

Key features

  • TypeScript-First: Designed for TypeScript from day one with decorators, dependency injection, and full template type inference

  • Signals: Fine-grained reactivity system that's fully type-safe and performs better than zone.js-based change detection

  • Developer Experience: CLI generates type-safe code, language service provides IntelliSense in templates, and strict mode catches errors early

How to use

Install Angular CLI: npm install -g @angular/cli. Create a new project with ng new my-app --standalone. Modern Angular uses signals for reactive state:

import { Component, signal, computed } from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `
    <div>Count: {{ count() }}</div>
    <div>Double: {{ doubled() }}</div>
    <button (click)="increment()">Increment</button>
  `
})
export class CounterComponent {
  count = signal(0);
  doubled = computed(() => this.count() * 2);
  
  increment() {
    this.count.update(n => n + 1);
  }
}

Signals are called as functions to read values. computed() creates derived state that updates automatically. Use .set() for direct updates or .update() for function-based changes. Template type checking validates that count() is actually callable and that event bindings like (click) receive correct types. For forms, Angular's reactive forms integrate with validation schemas and provide type-safe form controls through FormBuilder.

🔗 View on GitHub | GitHub stars: 100,422

If you only try one

Start with Zod. While every tool here solves important problems, Zod has the highest immediate impact on code quality. You can adopt it incrementally (start with API validation), it integrates with virtually every TypeScript tool in the ecosystem, and the pattern of "schema as single source of truth" fundamentally changes how you think about data flow. Once you experience writing a schema and getting both runtime validation and TypeScript types automatically, you'll find excuses to use it everywhere. The skills transfer directly to Valibot if bundle size becomes a concern, and it's the required foundation for getting the most out of Formisch.

If you are doing Open Source I have a good news for you, I work at CodeRabbit which is an AI review tool and its free for Open Source, please reach out to me on X or LinkedIn or just send an email on [email protected] if you need help on adopting CodeRabbit.

You can visit our portal below to create a new account and connect your repository and start reviewing your code.

Keep Reading