The Master Blueprint
The Complete Website Build Playbook
From zero to full-stack lead generation machine. 15 phases. Every prompt included.
What you'll build
- Single-screen mobile-first homepage
- 50+ page local SEO architecture
- Full tracking stack (GA4 + GTM + Meta Pixel)
- Lead capture system (forms, quiz, exit intent, newsletter)
- Email notifications + lead confirmation emails
- Database for leads (Supabase)
- Booking integration (Calendly)
- JSON-LD structured data
- Premium design system
Before writing any code, collect every piece of information you'll need. This prevents the stop-start cycle that kills momentum. Fill in the intake form, then create every account in one session.
Client Intake Form
CLIENT INTAKE FORM
==================
BASIC INFO
----------
Full Name: [CLIENT_NAME]
Business Name: [BUSINESS_NAME]
Domain: [DOMAIN.COM]
Primary Email: [CLIENT_EMAIL]
Phone (Call): [PHONE_CALL]
Phone (Text): [PHONE_TEXT]
City: [CITY]
State: [STATE]
PROFESSIONAL BACKGROUND
-----------------------
Title/Role: [TITLE]
Industry: [INDUSTRY]
Years of Experience: [YEARS]
Previous Companies: [COMPANIES]
Notable Achievements: [ACHIEVEMENTS]
Certifications/Credentials: [CREDENTIALS]
SERVICES OFFERED
----------------
Service 1: [SERVICE_1_NAME] - [SERVICE_1_DESCRIPTION]
Service 2: [SERVICE_2_NAME] - [SERVICE_2_DESCRIPTION]
Service 3: [SERVICE_3_NAME] - [SERVICE_3_DESCRIPTION]
Service 4: [SERVICE_4_NAME] - [SERVICE_4_DESCRIPTION]
TARGET AUDIENCE
---------------
Who do you serve: [TARGET_AUDIENCE]
Their biggest problem: [MAIN_PROBLEM]
How you solve it: [SOLUTION]
UNIQUE VALUE PROPOSITION
------------------------
What makes you different: [DIFFERENTIATOR]
Tagline (if any): [TAGLINE]
Key stats/results: [STATS]
SOCIAL LINKS
------------
LinkedIn: [LINKEDIN_URL]
Instagram: [INSTAGRAM_URL]
TikTok: [TIKTOK_URL]
Facebook: [FACEBOOK_URL]
Twitter/X: [TWITTER_URL]
YouTube: [YOUTUBE_URL]
BOOKING
-------
Calendly URL: [CALENDLY_URL]
Meeting Duration: [MEETING_DURATION]
Meeting Name: [MEETING_NAME]
BRANDING
--------
Primary Color: [PRIMARY_COLOR_HEX]
Secondary Color: [SECONDARY_COLOR_HEX]
Accent Color: [ACCENT_COLOR_HEX]
Heading Font: [HEADING_FONT]
Body Font: [BODY_FONT]
Logo File: [LOGO_PATH]
Profile Photo: [PHOTO_PATH]Create These Accounts
| Account | URL | What You Get |
|---|---|---|
| GoDaddy | godaddy.com | Domain purchase |
| Cloudflare | cloudflare.com | DNS/CDN (free tier) |
| Vercel | vercel.com | Hosting (free tier) |
| Supabase | supabase.com | Database (free tier) |
| Resend | resend.com | Email (free 3K/month) |
| Google Analytics | analytics.google.com | GA4 property |
| Google Tag Manager | tagmanager.google.com | GTM container |
| Meta Business | business.facebook.com | Meta Pixel |
| Calendly | calendly.com | Booking (free tier) |
| Search Console | search.google.com/search-console | SEO verification |
| Bing Webmaster | bing.com/webmasters | SEO verification |
Collect Credentials
CREDENTIALS DOCUMENT
====================
CLIENT: [CLIENT_NAME]
DOMAIN: [DOMAIN.COM]
DATE: [DATE]
TRACKING IDS
------------
GA4 Measurement ID: G-[XXXXXXXXXX]
GTM Container ID: GTM-[XXXXXXX]
Meta Pixel ID: [XXXXXXXXXXXXXXXX]
SUPABASE
--------
Project URL: https://[PROJECT_ID].supabase.co
Anon Key: eyJhbGci[...]
RESEND
------
API Key: re_[XXXXXXXXXX]
Verified Domain: [DOMAIN.COM]
From Email: hello@[DOMAIN.COM]
VERIFICATION CODES
------------------
Google Search Console: [VERIFICATION_CODE]
Bing Webmaster: [VERIFICATION_CODE]
CALENDLY
--------
Booking URL: https://calendly.com/[USERNAME]/[MEETING_TYPE]Pro tip
Do all account creation in one sitting. Context-switching between phases is what slows you down. Batch the admin work, then batch the code.
Purchase your domain on GoDaddy, then point it to Cloudflare for DNS management. Cloudflare gives you free CDN, DDoS protection, and easy DNS record management.
Purchase Domain (GoDaddy)
Search for your domain on godaddy.com, purchase it (disable auto-renew extras), and keep the tab open for nameserver changes.
Set Up Cloudflare
Create a free Cloudflare account, click “Add a Site,” enter your domain, select the Free plan. Cloudflare will scan existing DNS records and provide nameserver info.
Update Nameservers
In GoDaddy: My Products → your domain → DNS → Nameservers → Change → Custom. Enter the two Cloudflare nameservers. Wait 15 min to 24 hours for propagation.
Add DNS Records for Vercel
| Type | Name | Content | Proxy |
|---|---|---|---|
| A | @ | 76.76.21.21 | DNS only (gray cloud) |
| CNAME | www | cname.vercel-dns.com | DNS only (gray cloud) |
Pro tip
Keep proxy OFF (gray cloud) for Vercel records. Cloudflare proxy breaks Vercel's SSL certificate provisioning.
Cloudflare Settings
SSL/TLS → Full (strict). Speed → Auto Minify: HTML, CSS, JS. Caching → Standard.
Create a fresh Next.js project with all the packages you'll need. One command to scaffold, one to install dependencies, one to connect to Vercel.
Create Next.js Project
npx create-next-app@latest [PROJECT_FOLDER_NAME] \
--typescript --tailwind --app --src-dir=false
cd [PROJECT_FOLDER_NAME]
pnpm add @supabase/supabase-js resend react-calendly lucide-reactEnvironment Variables
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://[PROJECT_ID].supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=[ANON_KEY]
# Resend
RESEND_API_KEY=re_[API_KEY]Connect to Vercel
vercel linkThen add the same environment variables in Vercel Dashboard → Settings → Environment Variables.
Set up your color palette, typography, and component patterns before building any pages. This prompt goes into Cursor or Claude Code and generates your entire visual foundation.
Cursor prompt — Design System
“Set up the design system in app/globals.css with these specifications: COLORS: - Background: [BACKGROUND_COLOR] (e.g., #0D0D0D) - Card/Surface: [CARD_COLOR] (e.g., #1A1A1A) - Border: [BORDER_COLOR] (e.g., #3D3A35) - Primary Accent: [ACCENT_COLOR] (e.g., #D4A853) - Heading Text: [HEADING_COLOR] (e.g., #FAF8F5) - Body Text: [BODY_COLOR] (e.g., #B8B0A8) - Muted Text: [MUTED_COLOR] (e.g., #8A837B) TYPOGRAPHY: - Heading Font: [HEADING_FONT] (e.g., Cinzel) — Google Fonts - Body Font: [BODY_FONT] (e.g., Inter) — Google Fonts - Headings should be uppercase with letter-spacing: 0.12em LAYOUT: - Mobile-first design - On desktop (768px+), constrain body to max-width 430px centered - Black background (#000) on html for desktop side margins Also set up the fonts in app/layout.tsx using next/font/google.”
Cursor prompt — Component Patterns
“Create reusable component styles. Show me examples of: 1. Primary Button (accent color background, dark text) 2. Secondary Button (border only, light text) 3. Card (dark surface, border, rounded) 4. Section Heading (small label + large title) 5. Input Field (dark background, border, focus state) Use the design system colors. Give me the Tailwind classes for each.”
Pro tip
Replace the placeholder colors with your client's brand colors. The prompt works with any palette — dark mode, light mode, or anything in between.
Create your Supabase project and run the SQL to set up three tables: email captures, contact form submissions, and quiz results. Row Level Security enabled from the start.
Create Supabase Project
Go to supabase.com → New Project. Name it after the client, pick the closest region, generate and save the database password.
Create Tables
-- Email Captures (newsletter, exit intent, lead magnets)
CREATE TABLE email_captures (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
source TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Contact Form Submissions
CREATE TABLE contact_submissions (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
phone TEXT,
company TEXT,
website TEXT,
social_media TEXT,
service TEXT,
bottleneck TEXT,
revenue_range TEXT,
budget TEXT,
how_found TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Quiz Results
CREATE TABLE quiz_results (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
email TEXT NOT NULL,
name TEXT,
score INTEGER NOT NULL,
result_type TEXT NOT NULL,
answers JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Enable Row Level Security
ALTER TABLE email_captures ENABLE ROW LEVEL SECURITY;
ALTER TABLE contact_submissions ENABLE ROW LEVEL SECURITY;
ALTER TABLE quiz_results ENABLE ROW LEVEL SECURITY;
-- Allow anonymous inserts (for public forms)
CREATE POLICY "Allow anonymous inserts"
ON email_captures FOR INSERT WITH CHECK (true);
CREATE POLICY "Allow anonymous inserts"
ON contact_submissions FOR INSERT WITH CHECK (true);
CREATE POLICY "Allow anonymous inserts"
ON quiz_results FOR INSERT WITH CHECK (true);Cursor prompt — Supabase Client
“Create lib/supabase.ts with a Supabase client using the environment variables NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY.”
Pro tip
Always enable Row Level Security on every table, even with anonymous insert policies. Without RLS, anyone with your anon key could read all your leads.
Set up all three tracking platforms, then install them with a single prompt. One prompt handles GA4, GTM, Meta Pixel, and a custom event utility.
Create Tracking Accounts
| Platform | Where | What You Need |
|---|---|---|
| GA4 | analytics.google.com | Measurement ID: G-XXXXXXXXXX |
| GTM | tagmanager.google.com | Container ID: GTM-XXXXXXX |
| Meta Pixel | business.facebook.com | Pixel ID: XXXXXXXXXXXXXXXX |
Cursor prompt — Install Tracking
“Add all tracking scripts to app/layout.tsx: GA4 Measurement ID: G-[XXXXXXXXXX] GTM Container ID: GTM-[XXXXXXX] Meta Pixel ID: [XXXXXXXXXXXXXXXX] Use Next.js Script component with strategy="afterInteractive". Include GTM noscript iframe after opening body tag. Also create lib/tracking.ts with a trackEvent utility that fires events to both Meta Pixel (fbq) and GTM (dataLayer) for: - lead(source) — when email captured - schedule(location) — when Calendly opened/booked - quizComplete(score, resultType) — when quiz finished - formSubmit(formName) — when form submitted - buttonClick(buttonName, location) — general CTA tracking”
Set up Resend for transactional emails. When a lead submits a form, two emails fire: a notification to the client and a confirmation to the lead with next steps.
Verify Domain in Resend
Resend → Domains → Add Domain. Then add the TXT and MX records Resend provides to Cloudflare DNS. Wait 5-10 minutes and click Verify.
| Type | Name | Content |
|---|---|---|
| TXT | resend._domainkey | [FROM RESEND DASHBOARD] |
| TXT | @ | v=spf1 include:resend.com ~all |
| MX | send | feedback-smtp.us-east-1.amazonses.com |
Cursor prompt — Email API Route
“Create app/api/send-email/route.ts using Resend. When type is "contact_form": 1. Send notification to [CLIENT_EMAIL] with all form data 2. Send confirmation to the lead with subject "You're on my radar" that thanks them by first name, explains next steps (review within 24 hours), includes Calendly link: [CALENDLY_URL], and signs off as [CLIENT_NAME] When type is "quiz": 1. Send notification to [CLIENT_EMAIL] with name, email, score, result type 2. Send personalized results email based on result_type: - "foundation" (5-9): Early stage message - "growth" (10-14): Bottleneck message - "scale" (15-17): Optimization message - "optimize" (18-20): Fine-tuning message Include Calendly link in each. Use "hello@[DOMAIN.COM]" as the from address.”
Cursor prompt — Calendly Modal
“Create components/calendly-modal.tsx using react-calendly. Features: - Full-screen modal with close button - InlineWidget with the booking URL: [CALENDLY_URL] - Match page settings to our design system (backgroundColor, primaryColor, textColor) - Use useCalendlyEventListener to detect when booking completes - After booking, show confirmation screen with: - Success message - Call option: tel:+1[PHONE_CALL] - Text option: sms:+1[PHONE_TEXT] - Email option: mailto:[CLIENT_EMAIL] - Fire trackEvent.schedule('modal') on booking”
Two prompts: one for comprehensive meta tags and one for JSON-LD structured data. This is what makes your site show up in Google with rich results.
Cursor prompt — Meta Tags
“Update app/layout.tsx metadata with full SEO: title: "[CLIENT_NAME] | [TITLE] | [TAGLINE]" description: "[150-160 char description with keywords]" keywords: [KEYWORD_1], [KEYWORD_2], [KEYWORD_3], [CITY], [SERVICE_1], [SERVICE_2] author: [CLIENT_NAME] robots: index, follow OpenGraph: type: profile, url, image (/og-image.jpg 1200x630) Twitter Card: summary_large_image Geo tags: geo.region US-[STATE_CODE], geo.placename [CITY], geo.position [LAT];[LNG] Verification: google [CODE], msvalidate.01 [CODE]”
Cursor prompt — JSON-LD Schema
“Create components/structured-data.tsx with JSON-LD schema including: 1. WebSite schema with SearchAction 2. Person schema for [CLIENT_NAME] with name, url, image, jobTitle, description, email, telephone, address, sameAs (social URLs), knowsAbout 3. Organization schema for [BUSINESS_NAME] 4. FAQPage schema with 5-7 Q&As about the client 5. Service schemas for each service offered Add this component to the head in app/layout.tsx.”
Four lead capture mechanisms. Each one saves to Supabase, fires tracking events, and sends emails. Copy-paste each prompt — they're ready to go.
Cursor prompt — Exit Intent Popup
“Create components/exit-intent-popup.tsx that: - Triggers when mouse leaves viewport (clientY < 10) - Shows only once per session (use sessionStorage) - Has an email capture form - Saves to Supabase email_captures with source: "exit_intent" - Fires trackEvent.lead("exit_intent") - Uses our design system - Copy: Headline "Wait — Before You Go", subhead "Get [LEAD_MAGNET_DESCRIPTION]", button "[CTA_TEXT]", social proof "Join [NUMBER]+ [AUDIENCE] already inside"”
Cursor prompt — Quiz Funnel
“Create a quiz funnel built into the homepage or as a modal: 5 questions, one per screen: 1. [QUIZ_Q1] — 4 answer options 2. [QUIZ_Q2] — 4 answer options 3. [QUIZ_Q3] — 4 answer options 4. [QUIZ_Q4] — 4 answer options 5. [QUIZ_Q5] — 4 answer options Scoring: 1-4 points per answer (total 5-20) Results: Foundation (5-9), Growth (10-14), Scale (15-17), Optimize (18-20) Before showing results, capture name + email. Save to Supabase quiz_results table. Call the email API. Fire trackEvent.quizComplete(score, resultType). After results, show call/text/email contact options.”
Cursor prompt — Contact Form (Multi-Step)
“Create components/contact-modal.tsx as a multi-step Typeform-style form: Steps: 0. Intro screen, 1. Name (required), 2. Email (required), 3. Phone (skip), 4. Company (skip), 5. Website (skip), 6. Social handle (skip), 7. Service needed (single select), 8. Biggest challenge (multi-select), 9. Revenue range (single select), 10. Budget (single select), 11. How did you find me (single select), 12. Review screen, 13. Submit Features: Progress bar, back navigation, auto-advance on single select. Save to Supabase contact_submissions. Call email API. Fire trackEvent.formSubmit("contact_form"). Show confirmation after submit.”
Cursor prompt — Footer Newsletter
“Add an email capture section to the footer: - Label: "Stay Connected" or "Get Weekly Insights" - Subhead: "[NEWSLETTER_DESCRIPTION]" - Email input + Subscribe button - Save to Supabase email_captures with source: "footer_newsletter" - Fire trackEvent.lead("footer_newsletter") - Social proof: "Join [NUMBER]+ [AUDIENCE]"”
Cursor prompt — Homepage
“Create a single-screen homepage at app/page.tsx with NO scrolling (fixed viewport). Structure from top to bottom: 1. Profile photo (circular, with accent color glow border) 2. Name: "[CLIENT_NAME]" — large, font-display, uppercase 3. Subtitle: "[TITLE_1] · [TITLE_2] · [TITLE_3]" — accent color 4. Tagline: "[TAGLINE]" — body text color 5. Network/credibility logos row (if applicable) 6. Stats row (4 columns): [STAT_1], [STAT_2], [STAT_3], [STAT_4] 7. Primary CTA button: "[PRIMARY_CTA_TEXT]" — opens Calendly 8. Secondary button: "Call, Text, or Email" — expands to contact options 9. Quiz button: "[QUIZ_CTA_TEXT]" — opens quiz 10. Scarcity line: "[SCARCITY_MESSAGE]" — muted accent color Bottom: Tab bar navigation (Home, Services, Work, Ventures, Insights, About, Contact) Everything should fit on one screen. Use padding-bottom to account for tab bar height.”
Pro tip
The no-scroll homepage forces you to prioritize. If it doesn't fit on one screen, something needs to be cut. This constraint creates better design decisions than unlimited space ever will.
10 cities × 4-5 services = 40-50 pages. Each one targets a specific keyword like “[SERVICE] in [CITY]” and includes geo meta tags, local FAQ content, and cross-links.
Cursor prompt — City Data
“Create lib/city-data.ts with: cities array (10 cities): [ { slug: "[CITY_1_SLUG]", name: "[CITY_1_NAME]", state: "[STATE_1]", lat: [LAT], lng: [LNG] }, // ... 9 more cities ] services array (4-5 services): [ { slug: "[SERVICE_1_SLUG]", name: "[SERVICE_1_NAME]" }, // ... more services ]”
Cursor prompt — City Hub Pages
“Create app/[city]/page.tsx with: - generateStaticParams for all 10 cities - generateMetadata with geo meta tags - Urgency banner: "Only accepting 3 [CITY] clients this month" - Price anchor: "~~$[PRICE] Strategy Call~~ FREE" - Service cards linking to city/service pages - Social proof section with stats and testimonials - FAQ section (3 questions, AEO optimized) - Contact section (call, text, email) - Cross-links to other cities”
Cursor prompt — City + Service Pages
“Create app/[city]/[service]/page.tsx with: - generateStaticParams for all 40 combinations (10 cities x 4 services) - generateMetadata with geo meta tags and service keywords - Same urgency and price anchor - Service benefits in bordered cards - Investment/pricing info - Mid-page CTA (Book + Call) - FAQ section (3 questions) - Cross-links to other services in same city - Cross-links to same service in other cities”
Layer in conversion elements that work across the entire site: sticky header CTA, slide-in offers, floating contact button, and content upgrade CTAs.
Cursor prompt — Sticky Header CTA
“Create components/sticky-header-cta.tsx that: - Appears after scrolling 100px on all pages EXCEPT homepage - Shows on left: "Ready to scale?" + "Only 3 spots left" - Shows on right: "Book Call" button that opens Calendly - Fixed position, respects max-width constraint - Uses design system colors”
Cursor prompt — Slide-in CTA
“Create components/slide-in-cta.tsx that: - Slides in from bottom-right at 50% scroll - Dismissable (X button) - Shows once per session - Offers lead magnet: "[LEAD_MAGNET_NAME]" - CTA button opens quiz or Calendly - Animates in with slide-in-right keyframes”
Cursor prompt — Floating Contact (Mobile)
“Create components/floating-contact.tsx that: - Shows only on mobile (hidden on md: and up) - Fixed position bottom-right, above tab bar - Circular button with message icon - On tap, expands to show: Call, Text, Email options - Second tap collapses”
Cursor prompt — Content Upgrade CTAs
“Create inline CTA components for blog/insights pages: Mid-article CTA (after 2nd section): - "Want me to audit your business?" - Book Free Audit button End-of-article CTA: - "Ready to Build Your System?" - Dual buttons: Book Strategy Call + Take Quiz First - Gradient background with accent border”
Add to Layout
import { StickyHeaderCTA } from "@/components/sticky-header-cta"
import { SlideInCTA } from "@/components/slide-in-cta"
import { FloatingContact } from "@/components/floating-contact"
import { ExitIntentPopup } from "@/components/exit-intent-popup"
// Add inside <body> after {children}:
<StickyHeaderCTA />
<SlideInCTA />
<FloatingContact />
<ExitIntentPopup />Pre-Deploy Checklist
0/11 completed
Deploy
npx vercel --prod --yesPost-Deploy Verification
0/12 completed
Quick Reference Card
QUICK REFERENCE: [DOMAIN.COM]
=============================
TO CHECK LEADS:
supabase.com -> [PROJECT] -> Table Editor
TO CHECK ANALYTICS:
analytics.google.com -> [PROPERTY]
TO UPDATE BOOKING:
calendly.com -> Event Types
TO CHECK EMAILS:
resend.com -> Emails tab
SUPPORT CONTACT:
[YOUR_EMAIL]Maintenance Schedule
| Cadence | Action |
|---|---|
| Weekly | Check lead submissions, respond within 24 hours |
| Monthly | Review analytics, A/B test one element |
| Quarterly | Update testimonials, refresh copy, add content |
Success Metrics
| Metric | Target |
|---|---|
| Lighthouse Performance | 90+ |
| Lighthouse SEO | 95+ |
| Pages Indexed | 50+ |
| Lead Capture Points | 5+ |
| Tracking Pixels | 3 |
| Email Notifications | Working |
| Mobile Responsive | Yes |
| Schema Valid | Yes |
Bonus
ChatGPT Prompts Library
Use these with ChatGPT to generate all your copy. Replace the brackets and paste.
Client Discovery
“I'm onboarding a new client for a personal brand website. Ask me 20 questions to understand their background, expertise, target audience, services, value proposition, and goals.”
Homepage Copy
“Write homepage copy for [CLIENT_NAME], a [PROFESSION] based in [CITY]. Background: [BIO] Services: [LIST] Target audience: [WHO] Tone: [TONE] I need: 1. Hero headline (under 10 words), 2. Hero subheadline (under 25 words), 3. Tagline/signature line, 4. 4 service descriptions (50 words each), 5. 4 stat labels (what metrics to highlight), 6. CTA button text (3 options)”
Quiz Questions
“Create a 5-question assessment quiz for [CLIENT]'s website. Purpose: Identify where leads are in their [JOURNEY_TYPE] Audience: [AUDIENCE] Give me: 5 questions with 4 answer options each, scoring logic (1-4 points per question), 4 result categories with names and descriptions”
FAQ Content
“Write 7 FAQ questions and answers for [CLIENT]'s website. Include: Who is [CLIENT]? What does [CLIENT] do? What services are offered? How much does it cost? Where is [CLIENT] based? How do I get started? What results can I expect? Make answers AEO-optimized (direct, factual, under 100 words each).”
Email Sequences
“Write a 4-email welcome sequence for leads who signed up on [CLIENT]'s website. Audience: [DESCRIPTION] Goal: Get them to book a call at [CALENDLY_URL] Tone: [TONE] Email 1: Immediate welcome. Email 2: Value/insight (Day 1). Email 3: Case study/proof (Day 3). Email 4: Final CTA (Day 7).”
Local SEO City Intros
“Write unique intro paragraphs (50-75 words each) for [CLIENT]'s service pages in these 10 cities: [CITY_LIST] Service: [SERVICE_NAME] Value prop: [VALUE_PROP] Each paragraph should mention the city naturally and include local context.”
Get the prompt cheat sheet
7 copy-paste prompts that build 90% of apps. Delivered instantly.
The playbook gives you the system. The curriculum teaches you the skills.