Skip to content

Import from URL

Open vercel.com, import it from its address, then edit a heading and a text colour, browse the detected components and open the code.

Paste the address of a public web page and Feega draws it as a frame you can edit: text stays text in the page’s own fonts, the page is rebuilt as stacks (see below), backgrounds, gradients, borders, corners, shadows and blurs become fills, strokes and effects, pictures are copied into your project, SVG icons and logos become vector paths. Dashed borders stay dashed strokes, blended pictures keep their blend mode, and blocks that fade out at an edge keep an editable gradient mask. It is not a screenshot: only what a frame cannot hold as layers (a video, a canvas, an embedded page, a decorative block masked by a picture) comes in as a picture of itself. A block with text, links or buttons inside never does: its words and controls stay layers, and the effect is kept on what can carry it (a shadow, a blend mode, a fade over the content, a picture of its own background).

Open the insert menu (+), go to Import, choose From URL…, paste the address and press Import. The frame lands in the middle of the view, named after the page title.

The page is scrolled to the bottom and back so lazy pictures load and scroll-revealed blocks show. Each block that changes as you scroll (a fade-in, a slide-in, a scroll-linked tab) is kept as it looked while on screen, at its most visible. Running animations are finished, looping ones and carousels go back to their first slide, videos stop, and cookie banners are hidden, including ones that appear late. Then the page is frozen: nothing it does afterwards changes what is read. What the page does not show is not drawn: the answers of a collapsed FAQ come in as hidden layers you can turn on in the layers panel.

Parts of the page that change when you use them come in as components you can play. Before freezing the page, the import uses each one and reads every state it can show:

On the pageBecomesVariants
An FAQ or any <details>Accordion setState=Closed, State=Open
Tabs (role="tablist")Tabs setTab= each tab’s label
A button that opens a panel or a menu (aria-expanded)Disclosure setState=Closed, State=Open
A switch or a checkboxToggle setState=Off, State=On
A Swiper carouselCarousel setSlide=1 to Slide=6
A button, link or card with a CSS :hover stylethe same layera Hover state with the page’s own transition

Each part is its own component set on the Components frame; the page shows the variant it was in. The question, tab, button or switch carries a Change to link to the other variant, so in the prototype player clicking an FAQ question opens its answer and pushes the questions below down, and clicking a tab shows its panel. A part the page does not change when used (its scripts stopped by the freeze) stays a plain block. Hover styles written in JavaScript are not read.

Import vercel.com: the whole page, sections zoomed from Layers, the live page, the Components page with variants, a linked instance and its code.

The imported frame is laid out like a well-built Figma file. The page is a vertical stack of sections; inside, blocks one under the other become vertical stacks, columns side by side become horizontal stacks, a grid becomes rows, and the lines of a paragraph become one text layer. Gaps and paddings come from the page and bind to its spacing variables.

Only what really overlaps stays absolute: decorations behind or above the content, overlays like a cookie banner, glyph-by-glyph counters, and anything inside a block that clips an overflowing child. Every layer lands where the page drew it.

Only layers that do something are kept. A wrapper that draws nothing and holds one layer is removed and its padding moves to the stack around it, so a button holds its label directly; empty layers go; nested stacks running the same way merge. Layers are named by role or content (Nav, Logo, Button, Icon, the label’s text, a section by its first words), never by HTML tag. Colours a person cannot tell apart (#ffffff and #fdfeff) become one colour. Wrappers that clip, and anything inside a component, stay when removing them would change how the page looks or break the link to the main component. A block that holds several layers comes in as a frame with its own size and name, like a group you make yourself: double-click to go inside, Esc to come back out. Double-click or press Enter on a text to type, also inside a button or a card (the change is an override of that instance). In Layers an instance shows its content directly, so a button appears once.

Make the page stack narrower or wider (select the stack under the frame, change W) and sections fill the new width, full-width rows stretch, and wide rows spread their items. Text keeps the size and line breaks it had in the page.

Resizing the imported frame itself works the same way: text and laid-out blocks keep their size in pixels, the page fills the frame, centred content stays centred and narrows with it, and paragraphs that span their column rewrap. Layouts the page changes at a breakpoint (a menu that collapses, columns that stack) do not follow on their own.

Web fonts the page loads are copied into your workspace’s uploaded fonts and used by the frame, so text wraps where it wraps on the page. Text set in system fonts uses the closest free face (Inter for the system UI font, Arimo for Helvetica and Arial, Tinos for Times, Gelasio for Georgia, JetBrains Mono for monospace).

  • Public http/https pages only. Private network addresses and pages behind a login are refused.
  • The page is read in light mode: a site with a dark theme comes in light, a dark-only site comes in dark.
  • The page is read at desktop width (1280 px, with no scrollbar taking width), one frame pixel per page pixel, down to 65 536 px from the top, up to 10 000 layers. A page taller than 16 384 px comes in as frames stacked one under the other.
  • Four imports a minute per person.
  • By default the frame gets Tablet (768) and Phone (390) breakpoint views, each drawn from the page read at that width. Every element the page shows at both widths is one layer: a view changes only its position, size, type size, wrapping and visibility, so editing a headline or a picture on desktop changes it on tablet and phone too. What only the narrower page has (a phone menu, a part drawn as a picture, a headline worded differently) comes in as layers that show only in that view. With breakpoints the page is not split into section frames and repeated parts are not turned into components, so every view stays linked to the same layers. Reading three widths takes longer: untick Add tablet and phone layouts as breakpoints (or pass --no-breakpoints, breakpoints: false over the API and MCP) to read the desktop only and keep section frames and components.

Colours become variables in a collection named after the site (Stripe/Primary), type, shadows and gradients become styles (Stripe Body), and the layers that use them are bound. Primary is the fill of the page’s main buttons, picked by how much they stand out from the page; when no button is coloured, the brand colour of the site wins if the page uses it. Other colours are named by role (Background, Text, Surface, Border, Accent), then by lightness (Navy, Ink for very dark tints, Tint for very light ones), by hue (Green) or by what they paint (Surface 2). The page’s h1 style is H1. Text colours, fills, single solid borders and plain rounded corners are bound; a corner radius is a number variable in px (Radius M), so changing it re-rounds every layer bound to it.

Starting from a website on /start makes the brand first, so the first import already follows its palette.

The import turns the parts of a page a designer would make into components: buttons, badges, nav links, footer links, inputs, tabs, avatars, logos, icons, cards, feature tiles, testimonials, pricing tiers, accordion items and list items. A part that is obviously a component (a button, a badge, an input, a small card) becomes one even when the page shows it once; a plain block becomes one when it repeats. A footer column is a frame of Footer link instances, not a component of its own, and a card as wide as a section or holding more than eight texts stays a block. What a block is comes from the page itself: the element (<button>, a link, a list item), its role, the word its class uses (Button_root), where it sits (nav, footer) and its shape.

Each part becomes one main component and linked instances. Each instance keeps its own text, pictures and colours as overrides, so editing the main updates every copy and Reset brings one back to the main. An instance colour that matches the main’s token is not kept as an override, so it stays bound to the variable.

Copies that differ a little are variants of one set, not separate components: every button is in one Button set, with Style (Primary, Secondary, Outline, Plain), Size (Small, Medium, Large) and Icon (Leading, Trailing, Only, None); cards that gain a line or a picture, and tiles of one grid with the same look, are variants of one card set (Image=On, Items=3). When nothing else tells two variants apart, as for logos with different marks, they are named by their label or image (Variant=Notion) and numbered only when the page gives no name. When two sets of one role stay apart (two kinds of card), each takes the name of the section it is in (Hero Card, Pricing Card), of its label, or of its first words (Pro plan Card).

Components nest like in Figma: a button inside a card is a Button instance inside the Card main, so restyling the Button main restyles the button in every card.

Each main has properties: its texts, nested ones included (Label on a button, Title and Text on a card) and toggles to show or hide its icon or picture. Buttons and links whose background is a colour variable get State=Default, Hover and Pressed variants, bound to Primary hover and Primary pressed (a shade of the same colour, always far enough from it to see), so changing Primary restyles every state.

All mains land on the project’s Components page, one frame per set; that frame is their home, so editing a main there updates the page, and a main nested in another one (the button in a card) still has a single home on its own set. Each set sits on the background it was designed on (a dark hero’s buttons on that dark, a card from a white section on white), so light text stays readable on the light Components page; a variant from another section gets its own patch of that section’s background. They are listed once in the Components panel.

A block is at least 16 px on each side. Copies with a different icon or spacing stay linked: the difference is an override on that instance, as in Figma. A part the page draws as a picture (a header or a scrolling wall drawn with a blur or a mask) stays a picture, so its buttons and links are not components.

Terminal window
feega canvas import-url $PROJECT https://example.com --canvas <canvas> --x 0 --y 0

x and y are the canvas position of the frame centre. The answer has frame_id and truncated (true when the page hit the layer or height cap).

Over MCP: canvas_tool({ project_id, op: "import_url", input: { canvasId, url, x, y } }).

Over HTTP: POST /api/v1/projects/{projectId}/url-import with { canvasId, url, x, y }. Errors: not_public (400), failed (502, the page answered with an error), unreadable (422), too_slow (504, the page could not be read within the browser session), rate_limited (429), no_browser (503), busy (503, every hosted browser session is in use, or the database stayed too busy to save the frame; the dialog retries on its own), rejected (422, the imported document failed validation; detail carries the reason and no frame is created). An import that fails at any step leaves nothing behind: no page frame, no component set.