# How Modly Validates Extension Manifests: A Complete Technical Guide

> Discover how Modly validates extension manifests with its three-stage pipeline. Learn about integrity checks, semantic normalization, and trusted-source verification in this technical guide.

- Repository: [lightningpixel/modly](https://github.com/lightningpixel/modly)
- Tags: how-to-guide
- Published: 2026-08-15

---

**Modly validates extension manifests through a three-stage pipeline that detects the manifest file, performs integrity checks for completion and JSON validity, and applies semantic normalization including trusted-source verification and field augmentation.**

The `lightningpixel/modly` repository implements a robust validation system for extension manifests that ensures only properly structured and trustworthy extensions load into the application. Every time Modly discovers an extension folder—whether for built-in extensions or user-installed packages—it executes a rigorous validation sequence defined primarily in [`electron/main/ipc-handlers.ts`](https://github.com/lightningpixel/modly/blob/main/electron/main/ipc-handlers.ts). Understanding this pipeline is essential for developers building Modly-compatible extensions or debugging installation issues.

## The Three-Stage Validation Pipeline

Modly's manifest validation occurs whenever the `extensions:list` IPC handler scans the extensions directory. The process breaks down into distinct detection, integrity, and semantic phases.

### Stage 1: Manifest Detection and Loading

The validation begins in the `extensions:list` handler located at [`electron/main/ipc-handlers.ts`](https://github.com/lightningpixel/modly/blob/main/electron/main/ipc-handlers.ts) (lines 89-101). For each folder in the extensions directory, the system iterates through `['manifest.json', 'package.json']` to locate a manifest file. The first existing file is read as UTF-8 text and parsed using `JSON.parse()` into a `ParsedManifest` object.

If a [`manifest.json`](https://github.com/lightningpixel/modly/blob/main/manifest.json) exists alongside legacy [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json) files, Modly prioritizes the modern manifest format. The system also checks for a local source injection (`local://`) for extensions installed from local paths, enabling development workflows without registry requirements.

### Stage 2: Basic Integrity Checks

Before parsing content, Modly verifies the extension's installation state and file integrity (lines 90-106). The system performs three critical checks:

- **Incomplete installation**: If the hidden `.modly-incomplete` marker exists, validation returns `manifestError: 'incomplete'`, indicating the installation never finished.
- **Missing manifest**: When neither [`manifest.json`](https://github.com/lightningpixel/modly/blob/main/manifest.json) nor [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json) exists, the error status becomes `'missing'`.
- **Invalid JSON**: If `JSON.parse()` throws an exception, the system sets `manifestError: 'invalid'` and continues to the next extension.

Only manifests passing these checks proceed to semantic validation through the `parseExtensionManifest` function.

### Stage 3: Semantic Validation and Augmentation

The `parseExtensionManifest` routine (lines 11-44) transforms raw JSON into a strongly-typed extension description through systematic normalization:

- **ID fallback**: Assigns a `fallbackId` when the manifest omits an explicit `id` field.
- **Display name resolution**: Derives the display name using the precedence `displayName` → `name` → `fallbackId`.
- **Type enforcement**: Ensures the `type` field equals either `"model"` or `"process"`; for `"process"` types, defaults the `entry` field to [`processor.js`](https://github.com/lightningpixel/modly/blob/main/processor.js).
- **Node normalization**: Supplies default `input` (`"image"`) and `output` (`"mesh"`) values, merges node-level and extension-level `params_schema` and `param_defaults`, and copies Hugging Face-related fields.

If required fields like `nodes` are missing or empty, the function throws an explicit error: `throw new Error('manifest.json: required field "nodes" missing or empty')`.

## Trusted Source Verification

Modly implements security-based validation through the `fetchTrustedRepos()` and `isTrustedSource()` functions. The system downloads the official extensions registry from `https://raw.githubusercontent.com/lightningpixel/modly-official-extension/main/registry.json`, normalizes URLs (lowercased, trailing slashes removed), and caches the result for five minutes.

During validation, `isTrustedSource(source, trustedRepos)` performs a set lookup against these trusted repositories. Built-in extensions automatically receive trusted status regardless of their source URL. This distinction determines whether Modly applies additional security restrictions or allows full extension capabilities.

## Error Handling and User Feedback

Validation errors propagate through the IPC layer to the UI components. The [`ExtensionDrawer.tsx`](https://github.com/lightningpixel/modly/blob/main/ExtensionDrawer.tsx) component (located in `src/areas/models/components/`) interprets `manifestError` values—`missing`, `invalid`, or `incomplete`—and renders user-friendly messages explaining why an extension failed to load.

For installation-time validation, [`electron/main/extension-install-utils.ts`](https://github.com/lightningpixel/modly/blob/main/electron/main/extension-install-utils.ts) performs additional mandatory field checks (`id`, `type`, `entry`) when users install extensions from GitHub, preventing corrupted packages from entering the extensions directory.

## Practical Validation Examples

Retrieve validated extensions through the IPC renderer:

```typescript
// Returns fully-validated manifests or objects with manifestError descriptions
const extensions = await ipcRenderer.invoke('extensions:list');

```

Manually validate a manifest file for testing purposes:

```typescript
import { readFile } from 'fs/promises';
import { parseExtensionManifest } from './electron/main/ipc-handlers';

async function validateManifest(path: string, fallbackId: string) {
  const raw = await readFile(path, 'utf-8');
  const parsed = JSON.parse(raw);
  const trustedRepos = new Set<string>(); // Empty set means untrusted
  return parseExtensionManifest(parsed, fallbackId, trustedRepos, false);
}

```

The `scripts/build-builtins.mjs` script ensures built-in extensions include proper [`manifest.json`](https://github.com/lightningpixel/modly/blob/main/manifest.json) files during the build process, guaranteeing the validator always encounters well-formed manifests for core extensions.

## Summary

- **Three-stage pipeline**: Modly validates manifests through detection (finding [`manifest.json`](https://github.com/lightningpixel/modly/blob/main/manifest.json) or [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json)), integrity checks (incomplete markers and JSON validity), and semantic enrichment (field normalization and type enforcement).
- **Trusted sources**: Extensions become trusted either by being built-in or by matching URLs in the cached official registry fetched from the `modly-official-extension` repository.
- **Error propagation**: The system surfaces specific error types (`missing`, `invalid`, `incomplete`) to the UI, while throwing exceptions for critical schema violations like empty `nodes` arrays.
- **Implementation location**: Core validation logic resides in [`electron/main/ipc-handlers.ts`](https://github.com/lightningpixel/modly/blob/main/electron/main/ipc-handlers.ts), with supplementary installation checks in [`electron/main/extension-install-utils.ts`](https://github.com/lightningpixel/modly/blob/main/electron/main/extension-install-utils.ts).

## Frequently Asked Questions

### What files does Modly look for when validating an extension?

Modly searches for [`manifest.json`](https://github.com/lightningpixel/modly/blob/main/manifest.json) first, then falls back to legacy [`package.json`](https://github.com/lightningpixel/modly/blob/main/package.json). The validation occurs in [`electron/main/ipc-handlers.ts`](https://github.com/lightningpixel/modly/blob/main/electron/main/ipc-handlers.ts) within the `extensions:list` IPC handler, which scans both the user extensions directory and the built-in extensions folder.

### How does Modly handle corrupted or incomplete extension installations?

If the `.modly-incomplete` marker file exists in the extension directory, Modly marks the manifest with `manifestError: 'incomplete'`. For unparseable JSON, it returns `manifestError: 'invalid'`, and when no manifest exists, it returns `manifestError: 'missing'`. The UI component [`ExtensionDrawer.tsx`](https://github.com/lightningpixel/modly/blob/main/ExtensionDrawer.tsx) translates these codes into user-friendly error messages.

### What makes an extension "trusted" in Modly?

An extension gains trusted status through two mechanisms: being a built-in extension (automatic trust), or having its source URL match an entry in the official registry fetched from `https://raw.githubusercontent.com/lightningpixel/modly-official-extension/main/registry.json`. The `fetchTrustedRepos()` function caches these trusted URLs for five minutes to optimize performance.

### Which manifest fields are required for a Modly extension to load successfully?

The manifest must include a `nodes` array with at least one entry. For process-type extensions, the `type` field must equal `"process"` and the `entry` field (defaulting to [`processor.js`](https://github.com/lightningpixel/modly/blob/main/processor.js)) must specify the processor script. The system also requires valid `name` or `displayName` fields, and enforces that `type` must be either `"model"` or `"process"`.