Phials developer documentation
User guide

Previews

Preview providers control how Phials visualizes a file in the preview pane: optional thumbnail (grid), inline preview, and fullscreen. Each file resolves to at most one winning provider by priority and matching rules.

Types: PreviewProvider, PreviewAPI, FileMatchAPI in the same file.

Related: Plugin overview · Plugin API · Metadata

Mental model

  • thumbnail — small tile in grid views.
  • preview — main preview pane.
  • fullscreen — large / full-tab surface.

Any surface can be omitted. Components are Svelte Component<…> as in the type definition.

Matching files

The host indexes providers by extensions, mimeTypes, and categories (normalized). For each file it derives extension, MIME, and category (folder vs file categories).

Candidates are sorted by priority (higher first). The first that handles the file wins:

  1. If the provider defines canHandle(file, api), it alone decides. The second argument is FileMatchAPI: matchesExtension, matchesMime, matchesCategory. Lists are not re-checked when canHandle is present.
  2. Otherwise the provider must match extension, MIME, or category against its declared sets.

Important: Preview has no global path for providers with empty extensions, mimeTypes, and categories. Such a provider is not indexed unless it appears under an index key — set at least one dimension (or use canHandle with indexing keys so candidates exist).

Priority

Higher priority wins among matches. Ship a low-priority fallback only when you intentionally cover broad categories (for example unknown/archive-like types).

Optional behavior

FieldRole
overridesDoubleClickHost may route double-click to this preview instead of default open.
isEditableWhether an edit affordance is offered when metadata is available.
getQuickActionsHeader actions for the preview chrome.

PreviewAPI

Extends the base plugin API with preview-oriented helpers (for example metadata read helpers, fullscreen navigation). Exact members are in sdk/plugin-types.generated.d.ts. invoke and any file reads still follow your manifest permissions — only declare what you need.

Minimal example

import MyThumb from "./MyThumb.svelte";
import MyPreview from "./MyPreview.svelte";

const myPreview: PreviewProvider = &#123;
	type: "preview",
	id: "my.vendor.preview",
	name: "My Preview",
	priority: 50,
	extensions: ["xyz"],
	mimeTypes: ["application/x-my-format"],
	categories: ["document"],
	thumbnail: MyThumb,
	preview: MyPreview,
&#125;;

export default function createPlugin(): PhialsPlugin &#123;
	return &#123;
		id: "my.vendor",
		name: "My Plugin",
		version: "0.1.0",
		providers: [myPreview],
	&#125;;
&#125;

Pitfalls

  • canHandle without indexing keys — provider never becomes a candidate; keep extensions, mimeTypes, or categories non-empty when using canHandle for gating.
  • PreviewAPI metadata helpers may not populate every extracted field; pair with metadata providers when you need rich extracted data.
  • FileMatchAPI.matchesCategory uses file.category; combine with file.is_dir when you need folder-specific behavior.