How Instatic's Site Import System Handles HTML, CSS, and Media Files
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.
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 extracts page titles, derives URL slugs via deriveSlug, and identifies linked stylesheets and script references.
Simultaneously, 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 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. 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. 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 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, which converts CSS2 @import rules into ImportGoogleFont installation requests.
Conflict Detection and Resolution
Before commit, the 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:
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:
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:
import { makeHtmlPagePlan } from '@core/siteImport/htmlPagePlan';
const { pagePlan, warnings, inlineCss } = makeHtmlPagePlan(
'pages/about.html',
htmlSourceString,
fileMap,
);
Parsing CSS to rules:
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, extracting titles, slugs, and asset dependencies while resolving local hrefs. - CSS transformation leverages native browser APIs in
cssToStyleRules.tsto produce typed StyleRules and capture asset references. - Media handling through
assetPlan.tsnormalizes URLs and manages both referenced and unreferenced files, with special logic for Google Fonts. - Conflict detection in
conflicts.tsprevents slug collisions, class name clashes, and token conflicts before commit. - Atomic transactions via
commitPlan.tsensure 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →