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

umbraco-delivery-type-gen

v0.1.1

Published

Generate accurate TypeScript types from a live Umbraco Delivery API — including BlockList, BlockGrid, RichText and Media — by sampling real responses instead of relying on the OpenAPI spec.

Readme

umbraco-delivery-type-gen

TypeScript type generator for the Umbraco Delivery API.

Infers types directly from live API responses — no Swagger limitations. Works with Umbraco 13+ and correctly handles BlockList, BlockGrid, RichText, Media, and all nested structures.


How it works

Delivery API responses
        │
        ▼
  Fetch N samples per content type
  (uses ?filter=contentType:X)
        │
        ▼
  Merge samples together
  (null in one + string in another = optional string)
        │
        ▼
  Detect Umbraco-specific shapes
  (RichText, Media, Link, BlockList items...)
        │
        ▼
  Generate TypeScript
  (discriminated unions, block element types, helpers)

Installation

# Global install
npm install -g umbraco-delivery-type-gen

# Or run directly with npx
npx umbraco-delivery-type-gen -u https://mysite.com

Usage

# Generate types for all content types
umbraco-delivery-type-gen -u https://mysite.com -o ./types

# With a protected Delivery API
umbraco-delivery-type-gen -u https://mysite.com -k MY_API_KEY

# Fetch more samples for better coverage
umbraco-delivery-type-gen -u https://mysite.com --samples 25

# Only specific content types
umbraco-delivery-type-gen -u https://mysite.com --types blogPost,homePage,newsPage

# Include preview/draft content
umbraco-delivery-type-gen -u https://mysite.com --preview

# Show detailed warnings (null properties, empty arrays, etc.)
umbraco-delivery-type-gen -u https://mysite.com --verbose

Options

| Option | Default | Description | |---|---|---| | -u, --base-url | (required) | Umbraco base URL | | -o, --out | ./umbraco-types | Output directory | | -k, --api-key | — | Delivery API key | | -s, --samples | 10 | Samples per content type | | -t, --types | all | Comma-separated content type aliases | | -p, --preview | false | Include preview content | | -v, --verbose | false | Show property-level warnings |


Output

umbraco-types/
├── base.ts       — Umbraco base models (RichTextModel, ApiMediaWithCropsModel, etc.)
├── blocks.ts     — Block element types (BlockList & BlockGrid variants)
├── content.ts    — Content type interfaces + UmbracoContent union
└── index.ts      — Re-exports everything

Example output

Given a blogPost content type with two published items, the generator produces:

// blocks.ts
export interface HeroBlock {
  content: {
    contentType: 'heroBlock';
    properties: {
      headline: string;
      subheadline?: string;   // null in some samples → optional
      fullWidth: boolean;
    };
  };
  settings: {
    darkMode: boolean;
    padding: string;
  } | null;
}

export interface TextBlock {
  content: {
    contentType: 'textBlock';
    properties: {
      body: RichTextModel;
    };
  };
  settings: null;
}

// content.ts
export interface BlogPost {
  contentType: 'blogPost';
  name: string;
  id: string;
  route: ApiContentRouteModel;
  properties: {
    title: string;
    subtitle?: string;
    publishDate: string;
    richBody: RichTextModel;
    heroImage?: ApiMediaWithCropsModel | null;
    tags: string[];
    blocks: (HeroBlock | TextBlock | ImageBlock)[];
  };
}

export type UmbracoContent = BlogPost | HomePage | NewsPage;

// Discriminated union helper
export function isContentType<T extends UmbracoContent>(
  item: UmbracoContent,
  type: T['contentType']
): item is T {
  return item.contentType === type;
}

Using the types

import type { UmbracoContent, BlogPost, HeroBlock } from './umbraco-types';
import { isContentType } from './umbraco-types';

// Narrowing
function render(item: UmbracoContent) {
  if (isContentType<BlogPost>(item, 'blogPost')) {
    // item is BlogPost here
    console.log(item.properties.title);

    for (const block of item.properties.blocks) {
      if (block.content.contentType === 'heroBlock') {
        // TypeScript knows this is HeroBlock
        console.log(block.content.properties.headline);
      }
    }
  }
}

Umbraco configuration

The Delivery API must be enabled in appsettings.json:

{
  "Umbraco": {
    "CMS": {
      "DeliveryApi": {
        "Enabled": true,
        "ApiKey": "optional-if-protected"
      }
    }
  }
}

Why not use the Swagger spec?

The Delivery API's OpenAPI spec types BlockList and BlockGrid properties as object — which gives you nothing. This tool instead samples real API responses and infers what's actually inside the blocks.

Multi-sample merging means you get full coverage: if heroImage is null in 3 posts and an image object in 7 others, the generator correctly types it as ApiMediaWithCropsModel | null and marks it optional.


Programmatic API

You can also use the generator in your own build tooling:

import { DeliveryCrawler, mergeSamples, generateContentTypes, generateBlockTypes } from 'umbraco-delivery-type-gen';

const config = { baseUrl: 'https://mysite.com', samplesPerType: 10, outDir: './types', verbose: false };
const crawler = new DeliveryCrawler(config);

const contentTypes = await crawler.discoverContentTypes();
const shapes = await Promise.all(
  contentTypes.map(async (ct) => {
    const items = await crawler.fetchSamples(ct);
    return mergeSamples(ct, items);
  })
);

const contentTs = generateContentTypes(shapes);
const { source: blocksTs } = generateBlockTypes(shapes);