npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sveltopia/regions

v0.1.1

Published

Layout regions system for passing content from pages to layouts in SvelteKit

Readme

@sveltopia/regions

npm version npm downloads bundle size CI License: MIT

Full Documentation & Examples →

Pass content from child pages to parent layouts in SvelteKit. Server-rendered data or reactive snippets. Type-safe with optional validation.

Svelte 5 ready.

Features

Pass page-specific content (headers, breadcrumbs, sidebars) from pages to parent layouts without prop drilling.

Three Strategies:

  • Load Functions - SSR-friendly data (perfect for SEO)
  • Component Wrappers - Simple client-side props
  • Snippets - Full reactive UI with page state

Key Features:

  • SSR-friendly with zero layout shift
  • Type-safe with TypeScript + optional runtime validation
  • No prop drilling - pages set regions directly
  • Mix strategies on the same page
  • Zero runtime cost (validation stripped in production)

Installation

npm install @sveltopia/regions
# or
pnpm add @sveltopia/regions
# or
yarn add @sveltopia/regions

Requirements: SvelteKit 2.12.0+, Svelte 5.0.0+

Quick Start (CLI)

Generate everything with one command:

npx @sveltopia/regions add page-header

The CLI walks you through:

  1. Strategy choice - Load Function / Component Wrapper / Snippet
  2. Field definitions - What data this region needs
  3. Validator - Valibot / Zod / TypeScript-only
  4. File generation - Schema, components, and examples

Generated files are production-ready with full TypeScript support.

Example Output (Load Function Strategy)

✔ Which strategy? › Load function (SSR, best for SEO)
✔ Fields? › title, description
✔ Validator? › Valibot

Generated:
  src/lib/regions/page-header/pageHeaderSchema.ts
  src/lib/regions/page-header/PageHeaderRegion.svelte
  src/routes/page-header-example/+page.server.ts
  src/routes/page-header-example/+page.svelte

See Full Documentation for all strategies and advanced usage.

1. Define Types & Layout

// lib/types.ts
export interface HeaderData {
  title: string;
  description?: string;
}
<!-- routes/+layout.svelte -->
<script lang="ts">
  import { LayoutRegions, LayoutRegion } from '@sveltopia/regions';
  import type { HeaderData } from '$lib/types';
</script>

<LayoutRegions>
  <LayoutRegion name="header">
    {#snippet children(data)}
      {#if data}
        {@const typed = data as HeaderData}
        <h1>{typed.title}</h1>
        {#if typed.description}<p>{typed.description}</p>{/if}
      {/if}
    {/snippet}
    {#snippet fallback()}
      <h1>Default Title</h1>
    {/snippet}
  </LayoutRegion>

  {@render children?.()}
</LayoutRegions>

2. Set Content from Pages

Load Function Strategy:

// routes/about/+page.server.ts
import type { HeaderData } from '$lib/types';

export const load = () => ({
  regions: {
    header: {
      title: "About",
      description: "Learn more"
    } satisfies HeaderData
  }
});

Component Wrapper Strategy:

<!-- routes/about/+page.svelte -->
<script lang="ts">
  import { useLayoutRegions } from '@sveltopia/regions';
  import type { HeaderData } from '$lib/types';

  useLayoutRegions({
    header: {
      title: "About",
      description: "Learn more"
    } satisfies HeaderData
  });
</script>

Snippet Strategy:

<!-- routes/about/+page.svelte -->
<script lang="ts">
  import { useLayoutRegions } from '@sveltopia/regions';

  useLayoutRegions({ header: headerSnippet });
</script>

{#snippet headerSnippet()}
  <h1>About</h1>
  <p>Learn more</p>
{/snippet}

Core Concepts

Three-State Logic

Regions support three states for flexible content control:

// 1. Content - renders the provided data/snippet
useLayoutRegions({ header: { title: "Products" } });

// 2. Undefined - renders fallback if defined
useLayoutRegions({ /* header not mentioned */ });

// 3. Null - renders nothing (suppresses fallback)
useLayoutRegions({ header: null });

Schema Validation (Optional)

Add runtime validation with Valibot or Zod:

Valibot:

// lib/regions/headerSchema.ts
import * as v from 'valibot';
import { valibot } from '@sveltopia/regions';

const _headerSchema = v.pipe(
  v.object({
    title: v.string(),
    category: v.union([
      v.literal('components'),
      v.literal('patterns')
    ])
  })
);

export type HeaderData = v.InferOutput<typeof _headerSchema>;

export const headerSchema = valibot<HeaderData>(_headerSchema, v.parse);

Zod:

// lib/regions/headerSchema.ts
import { z } from 'zod';
import type { RegionSchema } from '@sveltopia/regions';

const _headerSchema = z.object({
  title: z.string(),
  category: z.enum(['components', 'patterns'])
});

export type HeaderData = z.infer<typeof _headerSchema>;

export const headerSchema = _headerSchema satisfies RegionSchema<HeaderData>;

Usage in layout:

<script lang="ts">
  import { headerSchema, type HeaderData } from '$lib/regions/headerSchema';
</script>

<LayoutRegion name="header" schema={headerSchema}>
  {#snippet children(data)}
    {@const typed = data as HeaderData}
    <h1>{typed.title}</h1>
  {/snippet}
</LayoutRegion>

Benefits: Catches typos in enums/literals, validates external data, dev-only (zero production cost).

TypeScript-Only (No Runtime Validation)

If you don't need runtime validation, use TypeScript interfaces for type safety:

Define interface:

// lib/types.ts
export interface PageHeaderData {
  title: string;
  description?: string;
}

Layout with type assertion:

<script lang="ts">
  import { LayoutRegions, LayoutRegion } from '@sveltopia/regions';
  import type { PageHeaderData } from '$lib/types';
</script>

<LayoutRegions>
  <LayoutRegion name="page-header">
    {#snippet children(data)}
      {#if data}
        {@const typed = data as PageHeaderData}
        <h1>{typed.title}</h1>
        {#if typed.description}<p>{typed.description}</p>{/if}
      {/if}
    {/snippet}
  </LayoutRegion>

  {@render children?.()}
</LayoutRegions>

Load function with type checking:

// routes/about/+page.server.ts
import type { PageHeaderData } from '$lib/types';

export const load = () => ({
  regions: {
    'page-header': {
      title: "About",
      description: "Learn more"
    } satisfies PageHeaderData
  }
});

Benefits: Compile-time type safety, zero runtime cost, no dependencies. Trade-off: No validation of data at runtime (typos in enum values won't be caught).

API Reference

Components

<LayoutRegions> Wraps layouts to enable regions.

Props: children?, schemas?, warnings?

<LayoutRegion name> Renders a specific region.

Props: name (required), children?, fallback?, schema?, required?

Functions

useLayoutRegions(options) Hook for pages to set regions.

useLayoutRegions({
  header: { title: "Products" },  // Data
  sidebar: sidebarSnippet,         // Snippet
  footer: null                     // Suppress
});

Returns LayoutRegionsContext for imperative updates:

const ctx = useLayoutRegions({ ... });
ctx?.setRegion('header', { title: 'New Title' });
ctx?.clearRegion('header');

Types

import type {
  LayoutRegionsOptions,
  LayoutRegionsContext,
  RegionSchema,
  RegionSchemas,
  RegionContent,
  WarningsConfig
} from '@sveltopia/regions';

Development Warnings

In development mode, the library provides helpful warnings to catch common mistakes:

Unexpected Region (enabled by default) - Fires immediately when a page sets a region that no layout defines:

[regions] Unexpected region "typoSidebar"
The page is setting a region that no layout is using.
Check that <LayoutRegion name="typoSidebar" /> exists in your layout.

Missing Required Region (enabled by default) - Fires when a page doesn't set a region marked as required:

<LayoutRegion name="header" required>
  ...
</LayoutRegion>

Unused Region (disabled by default) - Fires when a region is defined in the layout but no page sets it. Disabled by default because "catch-all" layouts that define all possible regions are a common valid pattern.

Configuring Warnings

<!-- Enable strict checking (including unused regions) -->
<LayoutRegions warnings={{ unused: true }}>
  ...
</LayoutRegions>
<!-- Disable all warnings -->
<LayoutRegions warnings={false}>
  ...
</LayoutRegions>

Warnings have zero runtime cost in production (only run when dev === true).

Comparison with Alternatives

Compare @sveltopia/regions against other SvelteKit patterns for passing content between pages and layouts:

| Feature | @sveltopia/regions | Props (↓) | Context/Stores | Manual Implementation | | ---------------- | ---------------------------- | --------- | -------------- | --------------------- | | Data Flow | Page → Layout (↑) | Layout → Page (↓) | Bidirectional | Page → Layout (↑) | | SSR-Friendly | Yes (with load functions) | Yes | No | Yes (with work) | | No Prop Drilling | Yes | No | Yes | No | | Type Safe | Yes | Yes | Partial | Yes (with work) | | Dynamic Content | Yes | Partial | Yes | Yes (with work) | | Validation | Yes | Partial | No | No |

Explanation:

  • @sveltopia/regions: Purpose-built for passing content FROM pages UP to parent layouts with three strategies and optional validation
  • Props (↓): Traditional component props - only work in opposite direction (layout → page), not suitable for page headers/breadcrumbs
  • Context/Stores: Can pass data upward, but not SSR-friendly and requires manual context setup in every layout/page
  • Manual Implementation: Build your own context-based system - flexible but requires significant boilerplate and maintenance

Contributing

We welcome contributions! Here's how to get started:

Development Setup:

git clone https://github.com/sveltopia/regions.git
cd regions
pnpm install
pnpm test          # Run tests
pnpm build         # Build package

Before submitting a PR:

  • Run tests: pnpm test
  • Ensure types check: pnpm check
  • Follow the existing code style

See CONTRIBUTING.md for detailed guidelines.

Support

Changelog

See CHANGELOG.md for version history and migration guides.

License

MIT © Sveltopia

See LICENSE for details.