# Insert

> The Insert panel adds frames, text, media, embeds, forms, sections, components and icons to a page, written as plain code in your own files.

- Page: https://midcode.app/docs/editor/insert
- From the midcode docs. Every page as Markdown: https://midcode.app/llms.txt

The Insert panel is where new elements come from. Click the plus button ("Insert") in the toolbar at the bottom of the canvas and the panel opens over the left panel, with its search field ready. Close it with the ✕ in its header, or `Esc` once nothing is selected, and the tab you were on comes back.

Everything in the panel is static markup with utility classes, written into the file of the page (or the component) you're on. One insert is one `⌘Z` step and one entry in [Publish](https://midcode.app/docs/publish/publish.md), with any file it brings along.

## Add something

1. Open the panel and pick a tile.
2. **Click** it. With an element selected, the new one goes at the selection. With nothing selected, it goes at the end of the page. The line under the search field says which: "Click adds it at the selection; drag to place it" or "Click adds it at the end of the page; drag to place it".
3. Or **drag** it onto a breakpoint. The frame under the pointer draws where it would land: a line between two elements, or a box around the one it would go into.

The new element is selected as soon as the page shows it, so you can style it straight away in [the style panel](https://midcode.app/docs/editor/styles.md).

Search looks at names, descriptions and keywords ("slider" finds Carousel and Slideshow). `Enter` adds the first match, the one with the ring. With two letters or more the list also offers "Search icons", which opens the icon browser on those words.

## Shortcuts

Each of these adds the item at the selection, like a click on its tile.

| Key | Adds |
| --- | --- |
| `F` | Frame |
| `S` | Stack |
| `T` | Text |
| `⇧G` | Grid |
| `⇧I` | Image (asks for a file first) |
| `⇧V` | Video (asks for a file first) |

In a Next.js App Router project, `F` on the page canvas is the draw tool of [the free canvas](https://midcode.app/docs/editor/free-canvas.md) instead: you draw the frame where you want it. Inside a component, and in every other kind of project, `F` inserts the Frame.

## What's in the panel

| Category | Items |
| --- | --- |
| Basics | Frame, Stack, Row, Grid, Text, Heading, Button, Link, Divider, Spacer |
| Media | Image, Video, Audio, Icon, Sticker |
| Embeds | YouTube, Vimeo, Spotify, SoundCloud, Google Maps, Embed |
| Forms | Contact form, Newsletter, Input, Email, Phone, Textarea, Select, Checkbox, Radio group, Submit button |
| Sections | Navbar, Hero, Hero with image, Logo cloud, Features grid, Feature with image, Stats, Testimonials, Pricing, FAQ, Call to action, Contact, Footer |
| Components | Carousel, Slideshow, Ticker, Tabs, Cookie banner, Language switcher, Shader gradient |

### Basics

Small pieces in one neutral look: they take your site's text color and font, and draw surfaces and lines from it (`bg-current/5`, `border-current/10`).

```tsx
<div className="flex flex-col gap-4">
  <div className="h-24 rounded-2xl bg-current/5" />
  <div className="h-24 rounded-2xl bg-current/5" />
</div>
```

That's a Stack. Buttons are written with `bg-neutral-900 text-white`; if your theme has the colors `primary` and `primary-foreground` (or `foreground` and `background`), midcode writes those instead.

### Media

Image, Video and Audio ask for a file from your Mac. midcode copies it into your project's public folder (`public/images`, `public/videos`, `public/audio`) and writes the element that shows it:

```tsx
<img src="/images/hero-photo.jpg" alt="Hero photo" className="w-full min-w-0 rounded-2xl object-cover" />
```

The alt text starts as the file's name in words. If the same file is already in that folder it's used again; a different file with the same name gets a number (`hero-photo-1.jpg`). Files dropped from Finder onto a breakpoint are inserted the same way. Replacing media and pasting images are on [Text, images and video](https://midcode.app/docs/editor/text-and-media.md).

### Icons and stickers

The Icon and Sticker tiles open a browser: choose a set (Phosphor, Lucide, Heroicons, Material Symbols, Tabler, Feather, Remix Icon, Material Design Icons, Simple Icons, SVG Logos; for stickers Fluent Emoji, Noto Emoji, Twemoji, OpenMoji), a style when the set has several, search, then click or drag one. The sets come from the Iconify API and are kept on your Mac once seen, so the first time needs a connection.

What an icon becomes depends on your `package.json`:

- If the project has the set's React package (`lucide-react`, `@phosphor-icons/react`, `@heroicons/react`, `@tabler/icons-react`), midcode imports the component. The browser's footer names the package when that's the case.
- Otherwise it writes the icon inline, as an `<svg>` that takes the text color.

```tsx title="With lucide-react installed"
import { Heart } from 'lucide-react'

<Heart className="size-6" aria-hidden="true" />
```

```tsx title="Without the package"
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" className="size-6" aria-hidden="true">...</svg>
```

A Lucide or Phosphor name that would shadow something in the page (`Image`, `Link`, `Map`) is imported under its `Icon` alias (`ImageIcon`).

A sticker is a colored SVG. It's saved as a file and shown by an `<img>`:

```tsx
<img src="/stickers/fluent-emoji-flat-rocket.svg" alt="" width="96" height="96" className="size-24" />
```

The file goes to `public/stickers/`. Every SVG midcode writes is cleaned first, so nothing in it can run or load from elsewhere: no scripts, no event handlers, no links to other sites.

### Embeds

An embed tile writes an `<iframe>` with a working example link, so you see a real player at once:

```tsx
<iframe
  src="https://www.youtube.com/embed/k3BPZ87BQmg"
  title="YouTube video"
  className="aspect-video w-full rounded-xl"
  loading="lazy"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
  allowFullScreen
  referrerPolicy="strict-origin-when-cross-origin"
/>
```

Select it and paste your own link in the right panel, under "Embed" → "Link". You can paste a share link, an embed address, a whole `<iframe>` embed code, or a place name for a map. midcode turns it into the address the player needs, and changes the title, the permissions and the size classes when the new link is another kind of player. Loom and Figma links are recognized too. See [element settings](https://midcode.app/docs/editor/components.md).

### Forms

Contact form and Newsletter are whole forms; the rest are single fields with their label. A form is written with `method="post"` and no `action`: set where it sends in the right panel ("Form" → "Action"), and add fields there with "Add field".

A second copy never collides with the first: ids the file already uses get a number (`contact-form-name` becomes `contact-form-name-2`, and its label's `htmlFor` follows), and so do field names taken inside the same form.

### Sections

Whole page blocks, shown in the panel as a live, scaled render of what they write. The ones with a picture use a neutral placeholder, written once to `public/midcode/placeholder.svg`.

### Components

The Components category is interactive: a carousel, a slideshow, a ticker, tabs, a cookie banner, a language switcher, an animated gradient. These need code that runs, so midcode writes each one's source into your project the first time you use it, and imports it:

```diff title="app/layout.tsx"
 import './globals.css'
+import { CookieBanner } from '@/components/midcode/CookieBanner'
 
 export default function RootLayout({ children }: { children: React.ReactNode }) {
   return (
     <html lang="en">
-      <body>{children}</body>
+      <body>
+        {children}
+        <CookieBanner />
+      </body>
     </html>
   )
 }
```

- The file goes in `components/midcode/`, next to your other sources: `src/components/midcode/` when the project keeps its code in `src/`, `app/components/midcode/` in React Router and Remix.
- It's a `.tsx` file when the project has a `tsconfig.json`, and a plain `.jsx` file (same code, types removed) when it doesn't.
- It's written once. If the file is already there, midcode uses it as it is and never writes over it: from then on it's your code.
- The import uses your `tsconfig.json` or `jsconfig.json` path alias when one covers that folder (`@/components/...`), a relative path otherwise. If the file already has something called `Carousel`, the import is `Carousel as MidcodeCarousel`.

Their options (autoplay, arrows, speed, colors) show as typed controls under [Props](https://midcode.app/docs/editor/components.md) when you select one. The Language switcher is written with your project's languages already in its props, when midcode finds them (see [Languages](https://midcode.app/docs/data/languages.md)).

## Where it lands

| You do this | The new element goes |
| --- | --- |
| Click, with a container selected | Last inside it. Containers are `div`, `section`, `main`, `article`, `header`, `footer`, `nav`, `aside`, `form`, `figure`, `ul`, `ol`, `li`, `fieldset`, `details` and `dialog`. |
| Click, with anything else selected | Right after it. Next to a component instance, never into the component's file. |
| Click a section, a Ticker or a Shader gradient | After the page's top-level block that holds the selection. |
| Click, with nothing selected | At the end of the page: last inside the element the page returns, or inside its `<main>`. |
| Add a Cookie banner | Last inside the `<body>` of the root layout: the `layout.tsx` nearest the page in the App Router, `root.tsx` in React Router and Remix. In the Pages Router it goes at the end of the page. |
| Drag | Where the line or the box shows. |
| Drop on the empty canvas | It floats there, in Next.js App Router projects. See [The free canvas](https://midcode.app/docs/editor/free-canvas.md). |

A single element added with nothing selected (a form, an embed, an image) would sit flush against the page's edge, so it comes inside a block of its own:

```tsx
<section className="mx-auto w-full max-w-6xl px-6 py-12">
  <p className="leading-relaxed">Say what matters in a sentence or two, and keep it easy to read.</p>
</section>
```

In [component mode](https://midcode.app/docs/editor/components.md) everything goes into the component's file; with nothing selected, last inside its root. A Cookie banner belongs to the site, so there midcode answers "This goes on the page: go back to the page to add it".

To add one of your own components, drag it from the [Assets tab](https://midcode.app/docs/editor/pages.md). midcode writes `<Card />` and its import.

## What midcode writes

- The code goes in with the indentation of the lines around it, in the file's own unit (two spaces, four, tabs).
- Imports go after the file's last import (after `'use client'` when there are none), with the quotes and semicolons the file already uses. A named import from a module the file already imports from joins that line.
- A page that returns a single component (`return <Home />`) gets a fragment around it and the new element.
- Nothing is written if the result wouldn't parse. You get "Couldn't insert it: the code wouldn't parse" and the file stays as it was.
- Files that come with the insert (a component, a sticker, the placeholder) are part of the same step: `⌘Z` takes the element out and deletes the files it created. If another file has started using one of them since (a second page imports the Carousel), that step can't be undone, and midcode says which file uses it.

### Projects without Tailwind 4

In a project that midcode styles itself, the same snippets are written with the `mid:` prefix, and their root gets `mid-base`, which scopes a small reset to what midcode inserted:

```tsx
<p className="mid-base mid:leading-relaxed">Say what matters in a sentence or two, and keep it easy to read.</p>
```

The components written to `components/midcode/` are prefixed the same way. See [Without Tailwind](https://midcode.app/docs/styling/without-tailwind.md).

## Other frameworks

In Svelte files the snippets are written as HTML: `class` and `for`, lowercase attributes, no self-closing `<div />`. Icons are always inline SVG there, and files go to `static/` in SvelteKit. The Components category is React only: on a Svelte page its tiles are dimmed and say "Needs a React page".

### Vue, Astro, HTML and templates (next release)

The next release inserts into `.vue` and `.astro` files, plain HTML and server templates the same way as into Svelte. Three things are different there:

- An insert that needs an import (an icon from a package, one of your components) gets it in a `.vue` file (in its `<script setup>`) and in an `.astro` file (in its frontmatter), created when the file has none. In a Nuxt project nothing is imported for a component under `components/`, which Nuxt finds by itself. It's still refused in a Vue component written with the Options API, in plain HTML and in server templates: "This needs an import, which midcode can't add to Hero.vue yet. Add it in the code."
- In JSX that isn't React (Solid, Preact, Qwik) the snippets follow the file and write `class` and `for`. midcode's own components are React, so without `react` in `package.json` they're refused: "This component needs a React page".
- Nothing is inserted into content that comes from a Markdown file (a post in Hugo, Jekyll or Eleventy). Select an element of the template around it instead.

## Limits

- The interactive components are React components. There are no Svelte or Vue versions.
- A click needs a place to go. On a page whose file midcode can't add to by itself it says "Select an element first: the new one goes next to it". If it can't tell what a page file renders (it returns a condition, for instance), it asks you to select an element on the canvas first.
- A section goes among the page's top-level blocks. When the page's shape can't be read, it goes next to the selection instead.
- Icons and stickers can't be browsed offline until their set has been loaded once.
- In projects midcode only shows (see [Supported stacks](https://midcode.app/docs/start/supported-stacks.md)), the tiles are disabled.
