CodingIdeas.ai
The Builder's Desk
Build GuideMay 12, 2026·7 min read

How to Build WinStack — A Drag-and-Drop Windows Installer in Two Weeks

Setting up a Windows PC in 2026 still means clicking Next-Next-Finish forty times. Here's exactly how to build the tool that fixes it — visual app selector, one-click PowerShell script, background auto-updater.

C

codingideas.ai

Tracking what developers complain about so you don't have to.


Setting up a new Windows PC in 2026 still means clicking Next-Next-Finish forty times, waiting for five installers to reboot you, and discovering three weeks later that half your apps are running outdated versions.

winget solved the install part. Nobody wrapped it into a product a normal person would actually use.

WinStack is that product: a web app where you pick your apps visually, click Install All, and get a PowerShell script that runs silently. Then a $6/month subscription keeps everything auto-updated in the background, forever.

Who you're building for: IT freelancers setting up client machines, power users who rebuild their PC yearly, remote IT teams managing developer workstations. The $6/month price point is nothing against the hourly rate of the person doing the setup.


What You're Actually Building

Three pieces:

  1. The selector UI — a web app showing 300+ apps with category filters. User picks theirs, hits generate.
  2. The script generator — an API route that turns selected app IDs into a PowerShell winget install script. No UAC prompt per app.
  3. The tray agent — a PowerShell script that runs as a Windows service, pings your Supabase nightly, runs winget upgrade on outdated packages, reports status back to a dashboard.

The subscription gates the tray agent. The script generator is free — it's the acquisition hook.


Architecture

User selects apps in UI
  → JSON config saved to Supabase
  → API generates PowerShell install script
  → User downloads + runs script (one-time setup)
  → Tray agent installed, pings Supabase nightly
  → winget upgrade runs on schedule
  → Device status written back to dashboard

The clever part: the tray agent uses the device token from Supabase to know which apps to keep updated. You can manage 20 machines from one dashboard. That's the team tier at $15/seat.


Tech Stack

  • Next.js — frontend + API routes
  • Supabase — auth, device table, app manifest storage
  • Stripe — subscriptions (Personal $6/mo, Team $15/seat/mo)
  • PowerShell — installer script + tray agent
  • winget — the actual package manager doing the heavy lifting

Build tip: use v0 to scaffold the app selector grid UI, Cursor for the script generator API logic, Lovable for the billing dashboard. The PowerShell tray agent is the only part you'll write from scratch.


MVP File Structure

app/
  page.tsx                      # App selector grid + hero
  api/generate-script/route.ts  # winget script generator
  api/webhook/route.ts          # Stripe webhook handler
  dashboard/page.tsx            # Device list + update status
lib/
  winget-manifest.json          # 300 app definitions
  db/schema.ts                  # Drizzle schema
components/
  AppCard.tsx                   # Selector card (checkbox + icon + name)
  DeviceRow.tsx                 # Device status in dashboard

Step-by-Step Build Guide

Step 1 — Define the app manifest

Create lib/winget-manifest.json. Each entry needs four fields:

{
  "id": "vscode",
  "name": "Visual Studio Code",
  "category": "Developer Tools",
  "winget-id": "Microsoft.VisualStudioCode"
}

Start with 50 apps across 8 categories. Don't try to build the full 300 on day one — validate the UX first.

Step 2 — Bootstrap the project

npx create-next-app winstack --typescript --tailwind

Step 3 — Build the app selector

Use v0 to scaffold a grid of AppCard components with category filter tabs. Each card has a checkbox. The selected IDs go into local state. One "Generate Script" button at the bottom.

This is the whole product from the user's perspective. Spend time here. The script generator is backend — nobody sees it. The selector is the thing people screenshot and share.

Step 4 — Script generator API route

// app/api/generate-script/route.ts
export async function POST(req: Request) {
  const { appIds } = await req.json();
  const manifest = await getManifest();
  
  const wingetIds = appIds
    .map((id: string) => manifest.find(a => a.id === id)?.['winget-id'])
    .filter(Boolean);

  const script = [
    '# WinStack install script — generated by codingideas.ai',
    'Write-Host "Installing apps..." -ForegroundColor Cyan',
    ...wingetIds.map(id =>
      `winget install --id ${id} --silent --accept-package-agreements --accept-source-agreements`
    ),
    'Write-Host "Done." -ForegroundColor Green',
  ].join('\n');

  return new Response(script, {
    headers: { 'Content-Type': 'text/plain' },
  });
}

The --silent flag is what makes this actually useful vs running winget manually. No UI, no popups, no per-app confirmation.

Step 5 — Supabase auth + devices table

Add Google OAuth via Supabase. Create two tables with Drizzle:

users (id, email, stripe_customer_id, plan)
devices (id, user_id, name, token, last_seen, installed_apps jsonb)

The token is a UUID generated when a device first registers. The tray agent uses it to authenticate without storing the user's full credentials on the machine.

Step 6 — Dashboard

The dashboard is simple: a list of devices with their last-seen timestamp and a list of which apps are outdated. Build with Lovable — give it the Drizzle schema and ask for a clean table UI. The main insight here: IT freelancers want to see all their client machines on one screen, which is the upsell from personal to team.

Step 7 — Stripe subscriptions

Two plans:

  • Personal: $6/month — 1 device, auto-updates
  • Team: $15/seat/month — unlimited devices, bulk management

Wire the Stripe webhook to flip a plan field in Supabase. The tray agent checks plan on startup and refuses to run if plan === 'free'. Gate only the auto-update — the script generator stays free.

Step 8 — The PowerShell tray agent

This is the hardest part but also the stickiest. A service that runs on startup, authenticates with the device token, pulls the app list from Supabase, runs winget upgrade, and writes results back.

# agent.ps1 (simplified)
$token = Get-Content "$env:APPDATA\WinStack\device.token"
$config = Invoke-RestMethod "https://winstack.app/api/device/$token/config"

foreach ($appId in $config.apps) {
  winget upgrade --id $appId --silent --accept-package-agreements 2>&1
}

Invoke-RestMethod "https://winstack.app/api/device/$token/report" -Method POST -Body @{
  updated = $config.apps
  timestamp = Get-Date -Format "o"
} -ContentType "application/json"

Package it as a scheduled task (not a Windows Service — Services need admin rights to install; scheduled tasks don't).

Step 9 — Stripe + tray agent connection

When Stripe confirms the subscription, your webhook:

  1. Sets users.plan = 'personal' in Supabase
  2. Generates a device token
  3. Returns a download link for the pre-configured agent script

The "Install the updater" button in the dashboard downloads a .ps1 file with the device token already baked in. One click, then it runs silently forever.

Step 10 — Verify end-to-end

On a fresh Windows VM:

  1. Select 5 apps in the UI
  2. Download the generated script
  3. Run it — all 5 should install without any prompts
  4. Buy a subscription in the test Stripe env
  5. Download + run the tray agent
  6. Confirm the device appears in your dashboard
  7. Manually mark one app as outdated in Supabase — verify the agent upgrades it on next run

Key Features to Ship in V1

  • Visual app selector — 50 apps, 8 categories, search filter
  • Silent installer scriptwinget install --silent for every selected app
  • Tray auto-updater — scheduled task, runs nightly
  • Device dashboard — one screen per user showing all machines + update status

Leave bulk machine management (team tier) for V2. The personal tier is the proof of concept.


Go-Live Checklist

  • [ ] Stripe payment tested end-to-end in test mode, then live mode
  • [ ] Tray agent tested on Windows 10 and Windows 11 (winget availability differs)
  • [ ] Sentry error tracking wired to both the Next.js app and the agent
  • [ ] Privacy policy covers what data the tray agent sends home
  • [ ] 5 beta IT freelancers have run it on a real client machine
  • [ ] Launch post drafted for r/sysadmin, r/msp, and ProductHunt

What to Charge

$6/month personal is a rounding error against the time saved. The real play is the team tier — MSPs (Managed Service Providers) pay $150-300/month for tools that do this badly. $15/seat with 10 seats is $150/month. Three clients gets you to $450/month. That's a viable side project.

The free script generator is the acquisition channel. Anyone who finds it useful enough to use twice will pay $6 to never have to think about updates again.


See the full idea breakdown → · Browse 500+ more ideas →

Ideas mentioned in this post

500+ more ideas based on real builder pain

Fresh ideas every day. No signup required.

Browse all ideas →
🤖

AI-assisted content. This post was drafted with the help of AI using real signals from Reddit, Hacker News, and App Store reviews. Facts and figures are verified before publishing, but if you spot an error let us know.