# How Instatic's Site Import System Handles HTML, CSS, and Media Files

> Instatic's site import system deterministically transforms HTML CSS and media files into typed objects using a three-phase pipeline for undoable imports.

- Repository: [CoreBunch/Instatic](https://github.com/CoreBunch/Instatic)
- Tags: internals
- Published: 2026-07-26

---

**Instatic converts static file bundles into fully-typed `ImportPlan` objects through a deterministic three-phase pipeline—analysis, asset planning, and atomic commit—enabling one-step undoable imports of HTML pages, stylesheets, and media assets.**

Instatic's site import system treats every upload as a headless pipeline that transforms raw static files into structured editor data. According to the CoreBunch/Instatic source code, the system parses HTML documents, extracts CSS rules, and catalogs media assets before executing an atomic transaction that makes the entire operation reversible with a single undo command.

## The Three-Phase Import Pipeline

The import process follows a strict separation between pure analysis and side effects. The architecture moves through distinct phases orchestrated by `buildImportPlan` in [`src/core/siteImport/buildPlan.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/core/siteImport/buildPlan.ts).

### Phase 1: Analysis and HTML/CSS Parsing

During the analysis phase, the system ingests the uploaded **FileMap** and parses every HTML document into a **PagePlan**. The `makeHtmlPagePlan` function in [`src/core/siteImport/htmlPagePlan.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/core/siteImport/htmlPagePlan.ts) extracts page titles, derives URL slugs via `deriveSlug`, and identifies linked stylesheets and script references.

Simultaneously, [`cssToStyleRules.ts`](https://github.com/CoreBunch/Instatic/blob/main/cssToStyleRules.ts) uses the browser's native `CSSStyleSheet.replaceSync()` method to parse stylesheets into typed `StyleRule` objects while capturing `@keyframes`, `@font-face` declarations, and `url()` asset references as `AssetRef` entries.

### Phase 2: Asset Planning and URL Normalization

The `buildAssetPlan` function in [`src/core/siteImport/assetPlan.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/core/siteImport/assetPlan.ts) normalizes every URL found in HTML attributes and CSS values against the FileMap keys. This phase collects all referenced media—including images, videos, and font files—while resolving Google Font `@import` rules through [`src/core/siteImport/fontImports.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/core/siteImport/fontImports.ts). Unreferenced files present in the upload are also preserved for potential upload, ensuring no assets are lost during transfer.

### Phase 3: Atomic Commit and Upload

The final phase executes through `commitImportPlan` in [`src/core/siteImport/commitPlan.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/core/siteImport/commitPlan.ts). First, the adapter's `uploadAsset` method uploads each collected media file. Then `applyAssetRewrites` substitutes all placeholder FileMap keys with final media URLs. Finally, a single `adapter.commit` transaction writes pages, style rules, design tokens, and scripts atomically, guaranteeing the entire import can be undone with one Cmd+Z operation.

## How HTML Pages Are Processed

Each HTML file undergoes transformation via the `makeHtmlPagePlan` utility. The function calls `@core/htmlImport` to parse the `<body>` content into node fragments while extracting `<link rel="stylesheet">` hrefs and both external and inline script tags.

The `resolveHref` utility skips external URLs, data URLs, and fragment identifiers, ensuring only local assets enter the dependency graph. Title extraction falls back to `prettifyTitle` when `<title>` tags are absent.

## How CSS Stylesheets Are Transformed

The `cssToStyleRules` parser in [`src/core/siteImport/cssToStyleRules.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/core/siteImport/cssToStyleRules.ts) processes raw CSS into two categories: class rules with `kind: 'class'` and ambient selectors with `kind: 'ambient'`. The parser strips unsupported at-rules such as `@layer` and conditional `@import`, recording these as warnings rather than failures. Color and font tokens are extracted during this phase for integration into the site's design system.

## Media Asset Handling and Font Resolution

Media processing occurs through the asset planning layer. The system walks every `AssetRef` to locate corresponding files within the FileMap, rewriting original URLs to use FileMap keys as placeholders. For `@font-face` rules referencing external URLs without local files, the system emits `external-font` warnings and drops the incompatible entries.

Google Font imports receive special handling through [`fontImports.ts`](https://github.com/CoreBunch/Instatic/blob/main/fontImports.ts), which converts CSS2 `@import` rules into `ImportGoogleFont` installation requests.

## Conflict Detection and Resolution

Before commit, the [`conflicts.ts`](https://github.com/CoreBunch/Instatic/blob/main/conflicts.ts) module validates the import plan against existing site data. It detects page slug collisions, class name clashes with existing site classes, and CSS custom property (`--var`) name conflicts. The system provides automatic resolutions including auto-rename, skip, and overwrite options, which the review UI exposes for user adjustment before final execution.

## Working with the Import API

Developers can trigger imports programmatically using the core modules.

Creating an import plan:

```typescript
import { buildImportPlan } from '@core/siteImport';
import { ingestInput } from '@core/siteImport/ingestInput';

const fileMap = ingestInput(userDroppedFiles);
const plan = buildImportPlan({
  fileMap,
  currentSite,
  options: { stylesheetModes: {} },
});

```

Committing the plan:

```typescript
import { commitImportPlan } from '@core/siteImport';
import { createSiteImportAdapter } from 'src/admin/modals/SiteImport/shared/createSiteImportAdapter';

const adapter = createSiteImportAdapter(editorStore, mediaApi);
await commitImportPlan(plan, adapter);

```

Processing individual HTML files:

```typescript
import { makeHtmlPagePlan } from '@core/siteImport/htmlPagePlan';

const { pagePlan, warnings, inlineCss } = makeHtmlPagePlan(
  'pages/about.html',
  htmlSourceString,
  fileMap,
);

```

Parsing CSS to rules:

```typescript
import { cssToStyleRules } from '@core/siteImport/cssToStyleRules';

const { rules, assetRefs, warnings } = cssToStyleRules(cssSource, {
  breakpoints: siteBreakpoints,
});

```

## Summary

- Instatic's import pipeline uses a **three-phase architecture** (analysis, asset planning, atomic commit) to transform static files into editor data.
- **HTML parsing** occurs in [`htmlPagePlan.ts`](https://github.com/CoreBunch/Instatic/blob/main/htmlPagePlan.ts), extracting titles, slugs, and asset dependencies while resolving local hrefs.
- **CSS transformation** leverages native browser APIs in [`cssToStyleRules.ts`](https://github.com/CoreBunch/Instatic/blob/main/cssToStyleRules.ts) to produce typed StyleRules and capture asset references.
- **Media handling** through [`assetPlan.ts`](https://github.com/CoreBunch/Instatic/blob/main/assetPlan.ts) normalizes URLs and manages both referenced and unreferenced files, with special logic for Google Fonts.
- **Conflict detection** in [`conflicts.ts`](https://github.com/CoreBunch/Instatic/blob/main/conflicts.ts) prevents slug collisions, class name clashes, and token conflicts before commit.
- **Atomic transactions** via [`commitPlan.ts`](https://github.com/CoreBunch/Instatic/blob/main/commitPlan.ts) ensure the entire import is undoable as a single operation.

## Frequently Asked Questions

### What file types does Instatic's site import system support?

The system primarily processes HTML documents, CSS stylesheets, and media assets including images, video files, and font files. It parses JavaScript references to maintain script associations but focuses on extracting the structural and styling layers for the visual editor.

### How does Instatic handle external URLs during import?

The `resolveHref` utility explicitly skips external URLs, data URLs, and fragment identifiers during the analysis phase. Only local files present in the uploaded FileMap enter the dependency graph, ensuring all imported assets remain self-contained within the project.

### Can I undo a site import after it completes?

Yes. The `commitImportPlan` function executes as a single atomic transaction through `adapter.commit`. This design guarantees that the entire import—including all pages, styles, and uploaded media—can be reverted with a single undo command (Cmd+Z).

### What happens when CSS classes conflict with existing site styles?

The conflict detection system in [`src/core/siteImport/conflicts.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/core/siteImport/conflicts.ts) identifies class name collisions and provides automatic resolution strategies including auto-rename, skip, or overwrite. These resolutions are presented in the review UI for user confirmation before the atomic commit phase.