# Migrating

Moving an existing app onto Prongs one screen at a time, with a mapping from shadcn/ui and plain HTML. Your code keeps working until you move it.

## Before you start

Adding Prongs does not change the code you already have. It copies its components and starter intents into your project, and nothing in your app uses them until you move a screen over. Start by recording what the check would report today, so only new problems show up from then on.

```bash
npx prongs add
npx prongs check --update-baseline    # records today's findings; new ones still show
npx prongs install-hooks            # optional: checks every file your agent edits
```

## Move one screen at a time

- ### 1. Pick a screen with few components — A settings page or a single form is a better first move than the main dashboard.
- ### 2. Swap its components for intents — Use the mapping below. Each intent's “not for” notes say when the neighbouring one fits better.
- ### 3. Run the check on that file — `npx prongs check app/settings/page.tsx` lists what is still raw or misnamed, with the intent to use.
- ### 4. Keep the look — The colour and radius tokens use shadcn's names, so the values in your existing theme file carry over.

## From shadcn/ui

Each row is a starting point. Read the intent before you commit to it, and keep your own component where none fits.

An AI can do the migration from the same data. Give it this prompt:

- Button — `action.submit, action.start, action.command, action.delete` by what it does: saves or confirms is action.submit, starts something is action.start, deletes is action.delete (or tone="danger")
- Card — `layout.panel` one self-contained thing
- Dialog — `dialog.task` a form or a task that blocks the page
- AlertDialog — `dialog.confirm` a yes or no before something happens
- Sheet — `dialog.sheet` a panel from the edge of the screen
- Alert — `layout.notice` a message that stays on the page
- Sonner / Toast — `layout.toast` a message that leaves on its own
- Input — `field.text, field.email, field.password, field.search, field.number, field.url` by its type attribute
- Textarea — `field.multiline`
- Select — `field.select`
- Checkbox — `field.checkbox` sent with a form
- Switch — `field.switch` takes effect at once
- Slider — `field.range`
- Label — `text.label` or the label that field.* already draws
- Table — `layout.table` records with the same fields
- Tabs — `nav.view` switches which view you see
- Dropdown Menu — `popover.menu`
- Tooltip — `popover.info`
- Accordion — `layout.disclosure`
- Pagination — `layout.pager`
- Breadcrumb — `nav.trail`
- Avatar — `media.person`
- Skeleton — `layout.loading`
- Badge — `text.meta` no badge intent yet: a short status word beside its item

## From plain HTML, Tailwind or another library

Start from what the element does: a button that saves is [`action.submit`](https://www.prongs.dev/docs/intents/action/submit.md), a link that goes somewhere is [`action.navigate`](https://www.prongs.dev/docs/intents/action/navigate.md), a box around one thing is [`layout.panel`](https://www.prongs.dev/docs/intents/layout/panel.md). Any element without an intent that fits stays as it is, and the check reports it rather than failing.
