# Ship a website

From an empty repo to a fast, live, indexed .com that takes payments.

Run these skills in order; finish each one before the next.

## Step 1: Plan a first sitemap

Purpose:: List the pages of the first website.

Rules::
- 4-7 pages, lowercase, comma separated
- Always home and pricing; add what the idea needs to work
- Every CTA and success metric action has a page

Inventory::
- Your idea line, CTA and success metric

Steps::
1. Start with home, pricing
2. Add signup and signin if users get an account
3. Add the 1-3 pages where the idea and the success metric happen
4. Reply as one comma separated line

Metrics::
- 4-7 pages on one line
- Nothing a first visitor needs is missing

## Step 2: Pick an inspiration website

Purpose:: Lock the main inspiration URL: the live site your first website follows in structure and craft.

Rules::
- Only a site so well known you are sure it is live
- A product in a close niche, with a clear signup and real attention to detail
- Borrow structure and craft, never its brand

Inventory::
- Your idea line, sitemap and CTA

Steps::
1. Think of 3 famous products that sell something close to your idea
2. Open each; note how the home page puts the main action first
3. Keep the one with the clearest, most detailed home
4. Reply with its homepage URL and one line on what you take from it

Metrics::
- One real, live URL
- The line names a structure, not a color

## Step 3: Prove the fit in one sentence

Purpose:: Say in one concrete sentence why this project is a perfect fit for you.

Rules::
- Check the obvious first; the answer is in front of you, not hidden
- What you already have, you offer
- Concrete, not poetic; every claim has evidence

Inventory::
- The project's purpose and idea
- What you are about and what you already have (tools, data, skills, audience)

Steps::
1. Read the project's purpose
2. Read what you are about and what you have
3. Find the overlap: what you already have that this project can offer
4. Write: we have <X> (evidence), so <project> offers <Y> to <buyer>
5. Reply with that one line

Metrics::
- You read it and think "obviously"
- It tells you what must work on day one

## Step 4: Build the best alternative frontend

Purpose:: Build the perfect alternative to your direct competitors: their best parts plus what visitors in this space are used to.

Rules::
- Reference = your captured competitors (funnels and sitemaps) and your inspiration site
- Take the best part of each; keep what is traditional in the space
- Presentation only; login, API and dashboard logic keep working

Inventory::
- Competitor funnels, sitemaps and screenshots
- Your site's repo and a headless browser for screenshots

Steps::
1. Per competitor: note the landing, pages and flow
2. List what they all share (traditional) and the best part of each
3. Build the header, footer and home, then the other public pages from that list
4. Deploy; screenshot desktop and mobile; compare with the competitor screenshots; fix
5. Reply: pages built and which competitor each best part came from

Metrics::
- A visitor of any competitor feels at home
- It looks better than each of them
- Login, signup and dashboard still work

## Step 5: Apply a brand to a built site

Purpose:: Put your brand onto a built frontend without moving anything.

Rules::
- Layout, spacing and sizes stay; swap only colors, fonts, logos, images and names
- Every value comes from your brand kit; no new colors or fonts
- Colors as CSS variables; fonts self-hosted or via the framework's font loader

Inventory::
- Your brand kit: fonts, palette, logo.svg, favicon.svg, og.png
- The site's repo and a headless browser

Steps::
1. Read the brand kit: fonts, colors, buttons
2. Set fonts and color variables once, globally
3. Add logo, favicon and OG image; set the site name and theme color
4. Replace every competitor name, color and image
5. Deploy; screenshot desktop and mobile; compare with the brand draft; fix
6. Reply in one line: what changed

Metrics::
- Same shapes as before, only your brand
- No competitor name left (search the code)

## Step 6: Make the site actually work

Purpose:: What you promised and what competitors basically offer all works, on the design as it is.

Rules::
- Never touch the design: layout, classes and copy stay
- Login and payments via your standard setup; images from a CDN, never the app server
- The production build is the test; keys never in code or replies

Inventory::
- Your fit sentence and competitor basics
- Auth provider, payment provider, database, CDN

Steps::
1. List what must work: the fit sentence + the basics all competitors have
2. Wire login and payments
3. Build the core feature; its images go to the CDN
4. Every link, button and form works; dead links wired or removed
5. Deploy; on a failed build read the log, fix, deploy again
6. Walk it live: signup, free use, upgrade; reply with what works

Metrics::
- A visitor can sign up, use it free and pay
- Zero dead links; screens look the same as before

## Step 7: Add Google sign-in

Purpose:: Visitors sign in with Google on the project, live and local.

Rules::
- One OAuth client per project; rerunning never creates a duplicate
- Secrets live in your env file and host settings; never in git or replies
- One "Continue with Google" button for both sign in and sign up

Inventory::
- Google Cloud project with a published consent screen
- Your auth library (for example NextAuth) and host env settings

Steps::
1. Create a Web OAuth client named after the project
2. Add origins and redirect URIs: localhost, the host URL and the domain (+ www)
3. Save the client id and secret to your env file and the host; redeploy
4. Check /api/auth/providers lists google and the button opens Google, not redirect_uri_mismatch
5. Reply in one line: client name, login works

Metrics::
- Login and signup reach the app
- No secret in the repo

## Step 8: Add payments with your own checkout

Purpose:: Visitors start free and can upgrade to a paid plan on your own checkout page.

Rules::
- One free plan + paid tiers, each with monthly credits in product metadata
- Your own checkout and billing pages (Stripe Elements); never send visitors to a hosted page
- Test mode first, live once the domain is live; keys never printed

Inventory::
- Stripe API keys, your competitors' pricing
- Your app's user table (plan name, credits, customer id)

Steps::
1. Pick the plans from competitor pricing
2. Create products and prices with plan_name and monthly_credits metadata
3. On signup: create the customer and put them on the free plan
4. Billing page: card form (Elements), subscribe, cancel, invoices
5. Webhook: subscription created, updated, deleted and invoice paid update the user's plan
6. Test: sign up, upgrade with a test card, cancel; reply with plans and mode

Metrics::
- New signups land on the free plan
- Upgrading changes the plan and credits in the app

## Step 9: Serve images from a CDN

Purpose:: Project images load fast and cheap from a CDN; the app server serves zero image bytes.

Rules::
- Originals stay local; only compressed WebP copies go up
- One storage zone and one pull zone per project
- No images in the public folder, no proxy routes, no paid image optimizing

Inventory::
- A CDN with storage (Bunny, Cloudflare R2 or similar) and its API key
- Your image folder

Steps::
1. Create the storage and pull zone named after the project
2. Convert images to WebP (plus thumbnails if needed) and upload; skip files already there
3. Write a manifest JSON (url, size, thumb) the site reads
4. Allow the CDN host in the framework's image settings; turn off server optimizing
5. Check one URL answers 200 image/webp
6. Reply in one line: files uploaded, MB stored, sample URL

Metrics::
- Every image URL answers from the CDN
- Re-running uploads nothing twice

## Step 10: Quality control a site

Purpose:: Before you optimise, every standard is present on every public page.

Rules::
- The standards = your design guide (for example Design like Google); check, don't redesign
- Missing standard: add it the smallest way; the design stays
- The production build is the test

Inventory::
- Your design guide and the list of public pages
- A headless browser for desktop (1440x900) and mobile (390x844) screenshots

Steps::
1. Turn the guide's rules and metrics into one checklist
2. Screenshot every public page, desktop and mobile; check each item
3. Add what is missing
4. Deploy; screenshot again and recheck
5. Reply: the checklist with ✅ or ❌ per page

Metrics::
- Every standard is present on every page
- Pages look the same apart from what was missing

## Step 11: Connect a custom domain

Purpose:: The project serves on its own .com: site on the host, images on the CDN, both https.

Rules::
- Domain = <name>.com; the owner buys it, the agent never pays
- DNS through the registrar's API; keys from your env file, never printed
- www redirects to the bare domain

Inventory::
- Registrar API (DNS records), host API (domains), CDN API (hostnames, certificates)
- Your env file with the keys

Steps::
1. If https://<domain> already serves this site, go to 5
2. Add <domain> and www (redirect) to the host project; read the A and CNAME values it asks for
3. Set DNS at the registrar: @ A, www CNAME, images CNAME to the CDN
4. CDN: add images.<domain>, load a free certificate, force SSL; repoint image URLs
5. Set the site URL to https://<domain>; add the domain to your login provider's redirect URIs
6. Reply in one line: https://<domain> live

Metrics::
- https://<domain> serves the project; www redirects
- Canonicals and the sitemap use the domain

## Step 12: Write account emails in your brand voice

Purpose:: The six account emails, and who sends them, speak in the voice of your narrative.

Rules::
- Every email says its fact plainly; the character lives in one line or the subject
- Each moment has its own tone: a welcome, an invoice and a goodbye do not sound the same
- The sender is original and fitting on your own domain, never a stock hello@ or noreply@
- Keep the template placeholders exactly ({name}, {fromPlan}, {toPlan}, {invoiceNumber})

Inventory::
- Your narrative and product name
- Emails: welcome, upgraded, invoiced, canceled, downgraded, removed account

Steps::
1. Read the narrative; decide who speaks and the one image they live in
2. Name the sender and the address after that speaker; verify the domain with your email provider
3. Per email, name what the reader feels then (joy, routine, doubt, leaving)
4. Write each: subject, greeting, the fact, one line in character, sign-off
5. Read all six as the reader; cut every line that tries too hard or could be any SaaS
6. Reply: the From line, then the six emails

Metrics::
- The From line alone already sounds like you
- No email is a joke at the reader's cost, none reads like a template

## Step 13: Get every page to 90+ on PageSpeed

Purpose:: Every public page scores 90+ on PageSpeed, mobile and desktop.

Rules::
- Measure with PageSpeed Insights; fix only what the report blames
- Design and copy stay the same
- At most 3 fix rounds

Inventory::
- PageSpeed Insights (web or API) and your list of public pages

Steps::
1. Run it on home and each public page; note score, LCP, CLS and INP
2. Fix the biggest cause first: images (sizes, priority on the LCP image), fonts (self-hosted, swap), JS (drop unused client code), CLS (fixed sizes)
3. Deploy and run it again
4. Repeat up to 3 rounds
5. Reply one line per page: mobile and desktop, before and after

Metrics::
- All pages 90+ on both
- Pages look the same as before

## Step 14: Set up Search Console and GA4

Purpose:: Google can find, index and measure the site.

Rules::
- Use the official APIs; never fake ownership
- Verify by DNS TXT record on the domain
- Tokens never printed

Inventory::
- Search Console and Site Verification APIs, GA4 Admin API, your registrar's DNS API

Steps::
1. Get a verification token; add it as a TXT record; verify the domain property
2. Submit https://<domain>/sitemap.xml
3. Create a GA4 property and web stream; copy the G- id
4. Add the gtag to the site's root layout, loaded after the page is interactive
5. Deploy; reply in one line: verified, sitemap submitted, GA4 id

Metrics::
- Search Console shows the sitemap as read
- The live HTML has the gtag and GA4 shows a visit

## Step 15: Ship a clean sitemap

Purpose:: https://<domain>/sitemap.xml is clean and every page in it is ready to rank.

Rules::
- Only real public pages: no login, signup, dashboard, account or noindex pages
- Every URL: 200, https on the domain, canonical = itself, unique title and description
- Fix only the sitemap, robots and page metadata

Inventory::
- The live sitemap.xml and robots.txt
- A metadata checker (or curl + grep for title, description, canonical)

Steps::
1. Fetch the sitemap; check the XML, URLs on the domain, lastmod
2. Remove non-indexable routes; add missing public pages
3. Check every URL's status, canonical, title and description; fix empty or duplicate ones
4. robots.txt allows / and points to the sitemap
5. Deploy and check again
6. Reply in one line: URL count, zero errors

Metrics::
- Zero errors on the second check
- Every page in it could rank on its own

Source:: https://isklls.com/playbooks/ship-a-website (iSklls, free skill library)
