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

@tentocms/typegen

v1.0.1

Published

TypeScript type generator for TentoCMS schemas

Downloads

54

Readme

@tentocms/typegen

TypeScript type generator for TentoCMS. Generates fully-typed definitions from your CMS schemas for type-safe content fetching.

Installation

Not yet on npm. @tentocms/typegen is not currently published to the npm registry. Until it is, install it from source: build this package from the TentoCMS monorepo and add it as a local/workspace dev dependency. The command below is the intended usage once the package is published.

npm install -D @tentocms/typegen

Quick Start

npx tentocms-typegen init       # Create config file
npx tentocms-typegen generate   # Generate types
import type { BlogPost } from './types/cms'

const page: BlogPost = await response.json()
console.log(page.content.author.name) // Fully typed

CLI

init — layout-aware output path

init detects your project layout and writes a sensible default output into the generated tentocms.config.js:

| Detected layout | Default output | | --- | --- | | A ./src/ directory exists | ./src/types/cms.ts (classic layout) | | No ./src/ directory | ./types/cms.ts |

Detection is a single check for the absence of ./src/ — there's no nuxt.config/app/-dir inspection. This avoids the old behaviour where Nuxt 4 projects (which have no src/ dir) got a default pointing at a non-existent path. Adjust the output value afterwards if you prefer a different location.

generate — flag reference

| Flag | Description | Resolution order | | --- | --- | --- | | -o, --output <path> | Output file path for the generated types | flag → tentocms.config.js output./src/types/cms.ts (fixed fallback; note this is not layout-aware — the ./src/-detection logic described above only runs inside init, not generate) | | -k, --api-key <key> | TentoCMS API key | flag → tentocms.config.js apiKeyTENTO_API_KEY env var | | -u, --api-url <url> | TentoCMS API base URL | flag → tentocms.config.js apiUrlTENTO_BASE_URL env var | | -c, --config <path> | Path to config file | Declared but currently has no effect. generate always loads ./tentocms.config.js from the current working directory (loadConfig() takes no arguments); passing -c/--config does not change which file is read. | | -e, --env <path> | Load environment variables from this file (see below) | — | | --env-file <path> | Alias of -e/--env (kept for older Node; Node ≥22/24 reserves a bare --env-file) | — | | -w, --watch | Watch for schema changes and regenerate types (polling, not filesystem watching — polls the CMS API) | — | | -i, --interval <seconds> | Polling interval in seconds, watch mode only | flag → tentocms.config.js watch.interval30 (default). Ignored unless -w/--watch is also set. |

init never accepts flags — only generate does.

generate.env loading

generate resolves TENTO_API_KEY and TENTO_BASE_URL from CLI flags → tentocms.config.jsprocess.env. To make local runs ergonomic it also loads a .env file into process.env before reading those variables:

# Auto-loads ./.env if it exists (silent if absent)
tentocms-typegen generate

# Load an explicit env file
tentocms-typegen generate -e ./config/.env.cms
tentocms-typegen generate --env ./config/.env.cms

Rules:

  • -e, --env <path> — load the given file (errors clearly if it doesn't exist).
  • No flag — auto-load ./.env from the current directory if present; do nothing if it's absent.
  • The parser is dependency-free: it skips blank lines and # comments, parses KEY=VALUE, and strips one surrounding pair of single/double quotes from the value.
  • Real environment variables are never overridden — a key already present in process.env always wins. This keeps the existing node --env-file=.env node_modules/.bin/tentocms-typegen generate workflow working (those keys are already set, so the loader is a no-op for them).

Node ≥ 22/24 note: newer Node versions reserve a bare --env-file on the command line for their own native loader and swallow it before it reaches this CLI. Use -e/--env instead (an --env-file alias is registered for older Node only).

*Fields vs *Content types

For every page type, generate emits two interfaces:

  • *Content (e.g. BlogPostContent) — includes the base fields id, slug, title, seo? plus the custom fields. Use it to type a whole page object.
  • *Fields (e.g. BlogPostFields) — only the custom fields (no id/slug/title/seo). The runtime page.fields object contains only the custom fields (id/slug/title live top-level, seo lives under page.seo), so use *Fields to type page.fields directly:
import type { BlogPostContent, BlogPostFields } from './types/cms'

const page = await fetchPage()            // shape ~ Page<...>
const fields: BlogPostFields = page.fields // ✅ exact custom-field shape

Both interfaces are exported. *Content is unchanged for back-compat.

Known limitations

  • Resolved-reference / repeater shapes can differ across components when the source schema models the same field differently. For example, a background field defined as a reference in one component resolves to ResolvedReference, while the same conceptual field modelled as a plain object in another component is emitted as Record<string, unknown>. Likewise, an untyped repeater (a repeater field whose schema declares no sub-fields) falls back to Record<string, unknown>[]. The generator faithfully reflects the source schema — to get consistent, fully-typed output, align the field definitions in your TentoCMS schema (use the same field type and define repeater sub-fields everywhere the field appears).

Full Documentation