Skip to content
Docs

Deploy Popover

The Deploy Popover component provides a popover interface for publishing a deployment to Vercel. It calls the Deploy Files action, tracks the deployment's status in real time, and links to the deployment once it's ready.

Install the deploy-popover block with the Vercel Platforms CLI:

npx @vercel/platforms@latest add deploy-popover

You can also install it with the shadcn CLI:

npx shadcn@latest add https://registry.platforms.guide/deploy-popover.json

The block imports deployFiles and getDeploymentStatus from ../actions/deploy-files. Install and configure the Deploy Files action too, including its Vercel client and environment variables.

  • One-click deployment: A Publish to Production button triggers a production deployment
  • Real-time status tracking: Monitor deployment progress with live updates
  • Deployment states: Visual feedback while the deployment starts, builds, and becomes ready
  • Direct deployment access: A View your deployment button opens the deployment URL in a new tab when it's ready
  • Automatic polling: Built-in SWR polling for deployment status updates
  • Domain and visibility views: UI for choosing a .vercel.app subdomain and public or private visibility, which you connect to your own logic
deploy-popover.tsx
import { DeployPopover } from '@/components/blocks/deploy-popover';
 
export default function MyComponent() {
  return (
    <div className="flex items-center justify-center p-8">
      <DeployPopover />
    </div>
  );
}

The component renders a Publish button that opens the popover, and manages several deployment states:

Initial state before any deployment action. Shows the Publish to Production button.

The deployFiles call is in progress. The button is disabled and shows "Starting deployment..."

Checking deployment status after the deployment is created. The button is disabled and shows "Building application...", "Initializing deployment...", or "Checking deployment status..."

Deployment successfully completed. Shows the View your deployment button.

The deployment's readyState is ERROR. The state carries the message "Your deployment failed.", but the installed block doesn't render it. The button returns to Publish to Production so the user can retry. Render state.message in the block if you want to show the error.

The block is copied into your project as source code, so you customize it by editing the installed file.

The popover doesn't define the files it deploys. It calls deployFiles, and the installed action deploys a hardcoded sample index.html file. To deploy different files, edit the action as shown in Deploy your own files, then pass the files in the popover's deployFiles call.

The popover doesn't choose a project. The Deploy Files action deploys to the project in the DEPLOY_FILES_PROJECT_ID environment variable, or to a project named after the deployment name when that variable isn't set.

Customize the deployment name in the deployFiles call inside the block's useDeployment hook:

deploy-popover.tsx
const { trigger: deploy, isMutating: isDeploying } = useSWRMutation(
  '/api/deploy',
  () =>
    deployFiles({
      deploymentName: 'your-custom-deployment-name',
    }),
);

The Customize Domain and Visibility views store their values in component state only. The installed block doesn't pass either value to deployFiles, and its handleAddDomain handler only returns to the main view. To apply the chosen subdomain, pass it to deployFiles as the domain option, for example by passing customDomain into useDeployment.

The block calls the Deploy Files Server Actions like this:

deploy-popover.tsx
import { deployFiles, getDeploymentStatus } from '../actions/deploy-files';
 
// Deploy files to Vercel
const result = await deployFiles({
  deploymentName: `platforms-deploy-test-${Date.now()}`.toLowerCase(),
});
 
// Check deployment status
const status = await getDeploymentStatus(result.id);

The component uses SWR for automatic status polling with these defaults:

  • Refresh interval: 10 seconds
  • Error retry count: 3 attempts
  • Error retry interval: 2 seconds

You can adjust these in the useSWR configuration:

deploy-popover.tsx
const REFRESH_INTERVAL = 10_000; // 10 seconds
 
useSWR(
  deploymentId ? deploymentId : null,
  (nonNullDeploymentId) => getDeploymentStatus(nonNullDeploymentId),
  {
    refreshInterval: deploymentId ? REFRESH_INTERVAL : 0,
    revalidateOnFocus: false,
    shouldRetryOnError: true,
    errorRetryCount: 3,
    errorRetryInterval: 2000,
  },
);
Last updated September 3, 2026

Was this helpful?

supported.