prongs

Start here

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.

Read https://www.prongs.dev/docs/migrating.md and help me apply it to my app.

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.

Terminal
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:

Migrate this project from shadcn/ui to Prongs. Read https://www.prongs.dev/migration-map.json for the mapping and https://www.prongs.dev/PRONGS.md for the intents. Move one screen at a time: swap its components for the intents the mapping gives, then run npx prongs check on that file and fix what it reports before the next screen.
  • 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, a link that goes somewhere is action.navigate, a box around one thing is layout.panel. Any element without an intent that fits stays as it is, and the check reports it rather than failing.