How Instatic Super Import Converts HTML and CSS Sites

Instatic Super Import is a two-phase, headless pipeline that transforms arbitrary HTML, CSS, and asset files into a fully-featured Instatic site through an analysis phase that builds an ImportPlan and an atomic commit phase that persists the data.

Instatic's Super Import feature, implemented in the CoreBunch/Instatic repository, provides a pure, functional approach to site migration. The system operates without browser rendering, instead using static analysis to parse source files and construct a complete migration plan before writing anything to the database. This architecture ensures that users can preview exactly what will be imported—including potential conflicts—before making any changes to their live site.

Overview of the Super Import Pipeline

The conversion process splits cleanly into two distinct phases. Phase 1 (Analysis) is orchestrated by buildImportPlan in src/core/siteImport/buildPlan.ts and performs all parsing, classification, and conflict detection. Phase 2 (Commit) is handled by commitImportPlan in src/core/siteImport/commitPlan.ts and handles asset uploads, URL rewriting, and the final atomic transaction that writes pages, style rules, and tokens to the site.

This separation makes the analysis instant and fully testable while ensuring that the actual import is an all-or-nothing operation that can be undone with a single undo command.

Phase 1: Building the Import Plan

The buildImportPlan function receives a FileMap (a map of all imported files) and the current SiteDocument, returning an ImportPlan that powers the preview wizard. The pipeline executes several discrete steps in sequence.

File Classification and HTML Parsing

First, classifyFiles in src/core/siteImport/classifyFiles.ts tags every entry as HTML, CSS, asset, or other. Then, makeHtmlPagePlan in src/core/siteImport/htmlPagePlan.ts parses each HTML file using DOMParser (or a regex fallback) to extract the page title, linked stylesheet hrefs, script tags, and body content.

The function calls importHtml to convert the body into a node fragment while preserving the document structure for later conversion into Instatic's native page format.

CSS to StyleRule Conversion

Raw CSS text is transformed into Instatic's native format by cssToStyleRules in src/core/siteImport/cssToStyleRules.ts. This pure parser produces StyleRule objects that respect @media queries using the site's defined breakpoints, records asset URLs found within declarations, and emits warnings for duplicate class names across the stylesheet.

The system also expands @import chains and partitions linked stylesheets into those that will be kept as raw CSS versus those converted to Instatic style tokens.

Asset and Font Detection

extractGoogleFontImports in src/core/siteImport/fontImports.ts scans every CSS source for @font-face rules referencing Google Font URLs, deduplicates font families, and merges variant lists. Simultaneously, buildAssetPlan in src/core/siteImport/assetPlan.ts normalizes all URLs (including those inside CSS), creates Asset objects for files requiring upload, and resolves @font-face blocks to ensure fonts are available after migration.

Conflict Detection

Before returning the plan, detectCrossSheetClassConflicts in src/core/siteImport/classCascades.ts identifies classes defined differently across multiple stylesheets. The system also checks the existing site for conflicts involving page paths, class rules, and color or font tokens, surfacing these as UI-friendly warnings in the wizard.

The resulting ImportPlan contains parsed page fragments, complete style rules, asset upload specifications, and a comprehensive conflict report.

Phase 2: Committing the Import Plan

When the user confirms the import (or a programmatic caller invokes the commit), commitImportPlan executes three major steps in sequence.

Asset Upload and URL Rewriting

uploadPlanAssets streams each asset through adapter.uploadAsset. Successful uploads generate a rewriteMap mapping sourcePath to mediaUrl, while failures produce asset-upload-failed warnings. applyAssetRewrites then traverses the entire ImportPlan, replacing every url(...) payload with the newly minted media URL.

Google Font Installation

installPlanGoogleFonts asks the adapter to install each detected Google Font family. This step communicates with the server's font installation endpoints to ensure that referenced typography is available in the Instatic editor immediately after import.

Atomic Transaction Commit

All persistent changes occur within a single adapter.commit block. The transaction adds conditions, commits color tokens, installs fonts, writes font tokens, persists style rules, creates pages using mintPageIds for stable identifiers, and commits page-scoped files.

Internal links are rewritten using mintPageIds before the commit, converting <a href="page.html"> references into cms:page:<id> references that survive future slug changes. Because the entire operation wraps in a history snapshot, users can undo the entire import with Cmd+Z.

Integration with the Admin UI

The Super Import wizard is exposed through the Spotlight command Site Import in src/admin/spotlight/commands/siteImport.ts. The wizard wires the pipeline via createSiteImportAdapter in src/admin/modals/SiteImport/shared/createSiteImportAdapter.ts, which supplies the SiteImportAdapter implementation communicating with server-side import endpoints.

// UI side – start the wizard
await startSiteImportWizard({
  buildPlan: (fileMap, currentSite) => buildImportPlan({ fileMap, currentSite }),
  commitPlan: (plan) => commitImportPlan(plan, siteImportAdapter),
});

The adapter abstraction allows the same core logic to run in different contexts while handling server-specific concerns like authentication and endpoint routing.

Programmatic Usage Examples

You can trigger Super Import outside the admin UI using the core functions directly:

import { buildImportPlan, commitImportPlan } from '@core/siteImport';

async function importFromZip(zipBytes: Uint8Array, currentSite, adapter) {
  // 1. Convert zip to FileMap (implementation dependent on your utils)
  const fileMap = await makeFileMapFromZip(zipBytes);
  
  // 2. Build analysis plan
  const plan = buildImportPlan({ fileMap, currentSite });
  
  // 3. Modify plan to resolve conflicts if needed
  
  // 4. Atomic commit
  const result = await commitImportPlan(plan, adapter);
  console.log('Imported:', result.pages.length, 'pages');
}

For link rewriting, import src/core/siteImport/linkRewrite.ts to handle internal href conversion before committing pages.

Summary

Frequently Asked Questions

What file types does Instatic Super Import support?

Instatic Super Import processes HTML files (converted to pages), CSS files (converted to StyleRules or preserved as raw CSS), and arbitrary asset files including images, fonts, and binary downloads. The classifyFiles function in src/core/siteImport/classifyFiles.ts determines the processing path for each file based on extension and content type.

How does Super Import handle conflicting CSS classes?

During the analysis phase, detectCrossSheetClassConflicts in src/core/siteImport/classCascades.ts identifies classes defined with different properties across multiple stylesheets. These conflicts are flagged in the ImportPlan and presented in the wizard for resolution, allowing users to choose which definition to keep or rename before the commit occurs.

Is the import process reversible?

Yes. The commit phase in src/core/siteImport/commitPlan.ts executes as a single atomic transaction wrapped in a history snapshot. Because the entire import—pages, style rules, tokens, and assets—commits as one operation, users can undo the complete import with a single undo command (Cmd+Z), restoring the site to its pre-import state.

Can Super Import be used programmatically outside the admin UI?

Absolutely. The core logic in src/core/siteImport/buildPlan.ts and src/core/siteImport/commitPlan.ts is headless and framework-agnostic. By providing a custom SiteImportAdapter implementation, developers can trigger imports from command-line scripts, custom plugins, or automated migration tools without loading the React-based admin interface.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →