Skip to content
Back to skills

Enhance File Type

ASecurity

Adding a file type or upgrading any of its capability slots in the files feature (preview, edit, thumbnail, grid card, info, share, versions, conversion, diff, rail panel). Use when supporting a new extension or MIME type, building a previewer, touching FILE_TYPES, PreviewKind, FilePreview.tsx, EDITABLE_KINDS, or surfaces/single-file/, or working the FILE_SURFACES.md wishlist.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 3, 2026
content-marketingpythongoshellbashnodebackend

Works with

  • cli

Security analysis

A100/100

Scanned October 3, 2026

npx -y skills add armanisadeghi/ai-matrx --skill enhance-file-type --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Enhance File Type?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Enhance File Type
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/armanisadeghi-enhance-file-type/badge)](https://www.skillsdirectory.com/skills/armanisadeghi-enhance-file-type)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: enhance-file-type
description: "Adding a file type or upgrading any of its capability slots in the files feature (preview, edit, thumbnail, grid card, info, share, versions, conversion, diff, rail panel). Use when supporting a new extension or MIME type, building a previewer, touching FILE_TYPES, PreviewKind, FilePreview.tsx, EDITABLE_KINDS, or surfaces/single-file/, or working the FILE_SURFACES.md wishlist."
---

# Enhance a file type

The matrx-admin file system has one registry (`FILE_TYPES`), one preview dispatcher (`FilePreview.tsx`), one edit dispatcher (`FileTabsBody.tsx → EditTabContent`), and two viewer shells (`PreviewPane` side panel + `SingleFileShell` full page). A "complete" file type touches ~55 capability slots organized into 9 groups (Identity, List/Grid, Preview, Edit, Companion tabs, Actions, Cross-feature, Creation, Bundle). Every kind lives somewhere on a T0 → T1 → T2 curve and the inventory tracks both current state and per-type wishlists.

## Use this skill when

- Adding a new file extension or MIME type to the registry
- Building a new `<Kind>Preview` previewer or upgrading an existing one
- Adding a `previewKind` to the `PreviewKind` union
- Wiring the Edit tab for a new kind (extending `EDITABLE_KINDS` and Monaco's `LANGUAGE_BY_EXT`)
- Building a rail panel in `surfaces/single-file/` for a new editing/preview mode
- Adding a new control to `FileViewerControlsContext`
- Working any item off `FILE_SURFACES.md (common-docs)`'s per-type wishlist
- Upgrading a thumbnail strategy, Info-tab field, Analysis detector, or action-bar button for a specific kind

## Mental model — 9 capability groups

| Group | What it covers | Where it lives |
|---|---|---|
| 1. Identity | extensions, MIME, category, icon, color, `previewKind`, sensitivity | `FILE_TYPES` registry |
| 2. List + Grid | icons, kind chip, thumbnail strategy, grid card body, quick-look | `FILE_TYPES`, `FileIcon`, grid card components |
| 3. Preview | previewer component, streaming policy, size cap, rail panel, error/loading states | `previewers/<Kind>Preview.tsx`, rail under `single-file/` |
| 4. Edit | `EDITABLE_KINDS`, Monaco language, save handler, format-on-save, starter templates | `EditTabContent`, `CloudFileInlineEditor` |
| 5. Companion tabs | Document (RAG), Analysis, Info, Versions, Share, diff | Each tab's component + backend |
| 6. Actions | universal actions, edit handoff, open-in-feature, convert-to, per-type extras | `preview-actions.ts`, `useFileActions` |
| 7. Cross-feature | inline chip, drag-to-slot, citation deep-links, paste-from-clipboard | Various consumers |
| 8. Creation | "New <type>" entry, templates, virtual-source provisioning | Future work |
| 9. Bundle/Ops | dynamic-import declaration, bundle weight, codec caveats | `FilePreview.tsx`, this doc |

Full slot list (numbered 1–55) lives in `../common-docs/systems/media/file-service/FILE_SURFACES.md` → **Part 1 — Capability framework**. Read that section before scoping any non-trivial change.

## Workflow

Copy this checklist and tick items as you go:

```
- [ ] Step 1 — Scope: identify file type + capability slot
- [ ] Step 2 — Read the inventory entry for that type
- [ ] Step 3 — Map the slot to code surfaces (use the table below)
- [ ] Step 4 — Implement (≤4 files for most changes)
- [ ] Step 5 — Verify in both PreviewPane and SingleFileShell
- [ ] Step 6 — Run lints + tsc
- [ ] Step 7 — Update FILE_SURFACES.md (common-docs) (matrix + wishlist + priorities)
- [ ] Step 8 — Update features/files/FEATURE.md change log
```

### Step 1 — Scope

Decide one of:

**A. New file extension to an existing `previewKind`** — e.g. add `.heif` to image. Single registry change.

**B. New `previewKind`** — e.g. add Jupyter notebook renderer. Touches the `PreviewKind` union, the registry, the preview dispatcher, and a new previewer file.

**C. Capability upgrade on an existing kind** — e.g. add click-and-drag pan to Image, or wire the PDF Extractor into the PDF Edit tab. Touches the previewer/rail/context.

**D. Cross-cutting capability** — e.g. add format-on-save (slot #28), or add `convertTo` to the action bar (slot #42). Touches the platform, then per-kind opt-in.

If unsure which slot a request maps to, scan Part 1 of the inventory.

### Step 2 — Read the inventory entry

Open `../common-docs/systems/media/file-service/FILE_SURFACES.md` and read:

1. **Part 2's wishlist** for the type you're touching (Image / PDF / HTML / Markdown / Video / Code — these have full per-type wishlists today). If your type doesn't have a Part 2 entry yet, find it in Part 3's matrix.
2. **Part 1** to confirm which slot # you're filling.

If your work fulfills a wishlist item, you'll be checking it off in Step 7.

### Step 3 — Map the slot to code

Use this table. Match the slot number to the file(s) you'll touch:

| Slots | Files to touch |
|---|---|
| 1–9 (Identity) | `features/files/utils/file-types.ts` → `FILE_TYPES[]` |
| 10–12 (Icon / thumb strategy) | `file-types.ts` + `FileIcon`; for real thumbs: `useFileAsset` variants |
| 13–14 (Grid card / quick-look) | Grid card components in `features/files/components/...` (search for `FileGridCard`) |
| 15 (Kind-filter chip) | Kind filter chip data |
| 17–23 (Preview tab) | `core/FilePreview/FilePreview.tsx` (dispatcher), `previewers/<Kind>Preview.tsx`, optional `surfaces/single-file/<Mode>Controls.tsx` for the rail, `surfaces/FileViewerControlsContext.tsx` if you need new shared state |
| 24–26 (Edit tab core) | `surfaces/FileTabsBody.tsx → EditTabContent`, `core/FilePreview/preview-actions.ts → EDITABLE_KINDS`, `core/FileEditor/CloudFileInlineEditor.tsx → LANGUAGE_BY_EXT` |
| 27 (Non-text editor) | New component under `core/FileEditor/<Kind>Editor.tsx`, plus a branch in `EditTabContent` |
| 28 (Format-on-save) | `CloudFileInlineEditor.handleSave` — add a per-language formatter dispatch |
| 30–31 (Document / RAG) | Python backend; no per-type front-end work for ingest |
| 32 (Analysis detectors) | `features/file-analysis/**` (detectors live there); register the kind in the Analysis tab |
| 33–34 (Info tab) | `FileInfoTab.tsx` + the metadata source (signed URL extraction, EXIF, etc.) |
| 35–36 (Versions / diff) | `FileVersionsList.tsx`; for diffs, new `<Kind>Diff.tsx` rendered from the versions list |
| 37 (Share) | `FileShareTab.tsx` (uniform — rarely per-type) |
| 38–39 (Actions) | `preview-actions.ts`; for edit gating: `EDITABLE_KINDS` |
| 40–41 (Open-in-feature, per-type extras) | `preview-actions.ts` + the destination feature's route adapter |
| 42 (Convert-to) | Platform-level dropdown (does not exist yet — design first) |
| 43 (Print) | `block-print-system` skill |
| 44 (Inline chip) | `FileResourceChip` |
| 53–54 (Bundle) | `next/dynamic` declaration in `FilePreview.tsx` |

### Step 4 — Implement

Most changes are 1–4 files. Patterns:

**Pattern A — Add an extension to an existing `previewKind`**

Edit `FILE_TYPES` in `features/files/utils/file-types.ts`. Add the ext + MIME to the matching entry. Done.

**Pattern B — Add a new `previewKind`**

1. Add the literal to the `PreviewKind` union in `file-types.ts`
2. Add the registry entries pointing at it
3. Add a `case "<kind>":` in `FilePreview.tsx`'s dispatcher with a `next/dynamic` import
4. Create `core/FilePreview/previewers/<Kind>Preview.tsx`
5. If editable: add `"<kind>"` to `EDITABLE_KINDS` + ensure `EditTabContent` routes it
6. If it has interactive controls in `SingleFileShell`: add a `<Mode>Controls.tsx` panel + register it in `FileViewerControlRail`, and add any shared state to `FileViewerControlsContext`

**Pattern C — Upgrade an existing previewer**

1. Make the change in `previewers/<Kind>Preview.tsx`
2. If it introduces new rail state: extend `FileViewerControlsContext` (typed props + setters)
3. Add/extend the matching `<Mode>Controls.tsx` panel
4. Verify the previewer still works without context (passive mode in `PreviewPane`)

### Step 5 — Verify in both surfaces

This is the #1 thing agents get wrong. Previewers run in two surfaces:

- **`PreviewPane`** — side panel from the files browser. The `FileViewerControlsContext` is **NOT** mounted here. Previewers must work in passive mode with no rail.
- **`SingleFileShell`** — dedicated `/files/f/{id}` route. The rail is mounted, context is populated, controls drive the previewer.

Test paths:
1. `https://www.aimatrx.com/files` → click a file row → verify side-panel preview works
2. `https://www.aimatrx.com/files/f/{id}` → verify full-page preview + rail controls work

Previewers should `useFileViewerControls()`-style read context but **never** require context. Always have a sensible default.

### Step 6 — Lints + tsc

```bash
pnpm lint
NODE_OPTIONS="--max-old-space-size=8192" pnpm tsc --noEmit
```

### Step 7 — Update the inventory

Open `../common-docs/systems/media/file-service/FILE_SURFACES.md` and update:

1. **Part 3 (matrix)** — change the ✅/🟡/🔴/🐛 marker in the relevant row + update the Notes column
2. **Part 2 (wishlist)** — if you completed a wishlist item, either strike it through (`~~item~~ ✅ **Shipped.** …`) or remove it. Add any newly-discovered follow-up items.
3. **Priority recommendations** (end of doc) — if your work knocked out a numbered item, mark it shipped the same way HTML and Image were.

If you added a new `previewKind` or graduated a kind to T1/T2, add a new Part 2 entry following the template (Has / Wishlist / Code touchpoints).

### Step 8 — Update the feature doc

Append a one-line entry to `features/files/FEATURE.md`'s Change Log with the date and a summary. If your change touches an invariant (e.g. "previewers must work without rail context"), update that section too.

## Common pitfalls

1. **Forgetting `EDITABLE_KINDS`.** Adding Monaco support without adding the kind to `EDITABLE_KINDS` means the Edit button stays hidden.
2. **Forgetting Monaco's `LANGUAGE_BY_EXT`.** Adding a `previewKind: "code"` extension without a `LANGUAGE_BY_EXT` entry opens it as `plaintext` in Monaco — no syntax highlighting in Edit.
3. **Tightly coupling a previewer to the rail context.** Previewers run in `PreviewPane` (no rail) AND `SingleFileShell` (with rail). Read `useFileViewerControls()` with a default fallback, never require it.
4. **Size-cap mismatch.** Streaming previewers (image, video, audio, pdf, html) should override `previewSizeCapOverride` via `getFilePreviewProfile` — they don't blob-fetch the whole file. Non-streaming previewers respect the default cap.
5. **Sandbox policy on HTML-like content.** The HTML iframe sandbox is `allow-scripts allow-popups allow-forms` and **does not include `allow-same-origin`**. Anything that needs cookies/localStorage cannot run there — and shouldn't.
6. **Skipping the Part 2 update.** The wishlist is the operating doc. If you ship a wishlist item without checking it off, the next agent will think the work is still open.
7. **Adding a new top-level `.md` for the new feature.** Don't. One doc per concern — extend `FILE_SURFACES.md (common-docs)` and the file's `FEATURE.md`.

## Decision matrix — which surface holds the control?

When a previewer needs an interactive control (zoom, viewport, line-wrap, …):

| Where the control belongs | When |
|---|---|
| Inline in the previewer's own header | The control is fundamental to viewing (e.g. Rendered/Source toggle for HTML). Must work in `PreviewPane`. |
| In a `single-file/<Mode>Controls.tsx` rail panel | The control is power-user / space-intensive (zoom slider, viewport picker, font size, minimap toggle). Only mounted in `SingleFileShell`. |
| Both | Provide a minimal version inline and a richer version on the rail. The inline version reads `FileViewerControlsContext` if mounted, else its own local state. |

Default: rich controls on the rail, with a sensible default applied when the previewer renders without context.

## Bundle budget

Previewers are dynamically imported (`next/dynamic`). Heavy deps (PDF.js, SheetJS, Three.js when added) must stay dynamic — never `import` them at the top of `FilePreview.tsx` or any of its eagerly-loaded ancestors. Annotate bundle weight in `FilePreview.tsx` if it's non-trivial.

## Pre-PR checklist

- [ ] Registry entry has all 9 Group-1 fields populated (or N/A justified)
- [ ] Previewer renders in `PreviewPane` (no rail) without errors
- [ ] Previewer renders in `SingleFileShell` (with rail) with controls wired
- [ ] If editable: `EDITABLE_KINDS` and `LANGUAGE_BY_EXT` both updated
- [ ] Lints pass, `tsc --noEmit` passes
- [ ] `FILE_SURFACES.md (common-docs)` Part 3 markers updated for affected rows
- [ ] `FILE_SURFACES.md (common-docs)` Part 2 wishlist entries struck through / amended
- [ ] `FILE_SURFACES.md (common-docs)` Priority recommendations updated if a numbered item shipped
- [ ] `features/files/FEATURE.md` Change Log appended
- [ ] No new top-level `.md` files created
- [ ] No DEBUG rings / DebugLayerLabel re-introduced

## Additional resources

- **Inventory + framework + wishlists:** `../common-docs/systems/media/file-service/FILE_SURFACES.md`
- **Files feature doc:** `features/files/FEATURE.md`
- **File handler skill:** `features/files/handler/FEATURE.md` (for upload / asset URL questions — different concern)
- **Print system skill:** `.claude/skills/block-print-system/SKILL.md` (for slot #43 — print)
- **Window panels skill:** `.claude/skills/window-panels/SKILL.md` (if your enhancement opens an overlay)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…