diff --git a/episode-02/README.md b/episode-02/README.md index deb8246..0ee5e15 100644 --- a/episode-02/README.md +++ b/episode-02/README.md @@ -1,10 +1,30 @@ -# Episode 02 +# Episode 02 — Build Your Website with AI -_Title to be added._ +Turn a résumé into a live portfolio website using the **GitHub Copilot CLI** — no web-design +background required. The whole episode is one idea: **a good prompt = context + specifics + style.** -This folder holds the artifacts for Episode 02 of the Student AI Learning Series — -things like the scoping brief, prompts used on camera, demo assets, screenshots, and any -code snippets shown in the video. +- **Persona:** Jamie Rivera (the mock résumé in [`../common/`](../common/)). +- **Deliverable:** a clean, responsive portfolio site generated from Jamie's résumé. + +## The four things every strong résumé nails +Recruiters scan a résumé in about **7 seconds**, so the site is built around four foundations — +each becomes one section of the page: + +1. **Header & headline** — who you are and how to reach you +2. **Experience with impact** — results and numbers, not duties +3. **Skills** — grouped and relevant +4. **Education** + +## What's in this folder +- **`prompt.md`** — the prompt used on camera to generate the site (context + specifics + style). +- **`design-prompts.md`** — follow-up prompts to personalize the look (color, type, hero, motion, and + more), each written to run reliably on the model students get for free. +- **`portfolio/`** — the generated site (plain HTML / CSS / JS, ready for GitHub Pages). +- **`preview.png`** — the finished site. + +## Try it yourself +1. Grab the résumé from [`../common/`](../common/) (or use your own). +2. Paste `prompt.md` into the Copilot CLI, swapping in your details. +3. Open `portfolio/index.html` in a browser — that's your site. +4. Use `design-prompts.md` to make it yours, then deploy it free on GitHub Pages. -Drop episode files directly in this folder. Shared assets used across episodes (such as the -mock resume) live in [../common/](../common/). diff --git a/episode-02/design-prompts.md b/episode-02/design-prompts.md new file mode 100644 index 0000000..baa2dba --- /dev/null +++ b/episode-02/design-prompts.md @@ -0,0 +1,132 @@ +# Ep 2 — Design Personalization Prompts + +**Purpose:** once your four foundations are built (Header, Experience, Skills, Education), use these prompts to make the site *yours* — professional, but personal. Every prompt here is written to be **reliable on the lowest student model** (GPT‑5 mini, which Auto serves for straightforward tasks): concrete, one change at a time, describe don't assume. + +--- + +## How to prompt for design (works on any model, including the mini) + +The lesson is still **Context + Specifics + Style** — just applied to *look and feel* instead of content. + +1. **One change per prompt.** Weaker/faster models are most reliable when a prompt does exactly one thing. Chain small wins. +2. **Describe the outcome, then give a concrete anchor.** "Warmer, calmer" is a direction; "cream background, one navy accent" is what makes it land. +3. **Protect what works.** Start design prompts with *"Keep all my content and structure — only change the look."* This stops a model from rewriting your text. +4. **Ask for options, then choose.** "Give me three color directions as hex values" → "Go with #2." Great for exploring without committing. +5. **If a small model over‑reaches,** re‑prompt: *"That changed too much. Only change X; revert everything else."* + +> 💡 Copy a prompt below, replace the **[bracketed]** parts with your taste, and paste it into the Copilot CLI. Do them in order for the smoothest result. + +--- + +## 0 · Set a design direction (do this first) +One vibe guides every later choice, so pick it up front. + +> Keep all my content and structure — only change the look. I want my portfolio to feel **[professional & minimal / warm & approachable / bold & editorial / modern‑tech]**. Propose a cohesive design direction: a palette (one background, one text color, one accent), a heading + body font pairing, and a spacing style. Show me the palette as hex values first, then apply it. + +- **Personalize:** swap the vibe, or add a reference — *"clean like Stripe," "calm like a Notion page," "editorial like a magazine."* +- **Keep it pro:** cohesion beats variety. One accent color, one font pairing, consistent spacing. + +--- + +## 1 · Color & theme +> Keep everything else the same. Change my accent color to **[deep teal #0f766e]** and update buttons, links, and the nav highlight to match. Make sure all text still passes WCAG AA contrast on my background. + +Light / warm alternative: +> Switch to a light theme: near‑white background, dark‑slate text, and a single **[terracotta]** accent. Keep it high‑contrast and professional. + +- **Personalize:** pick a color that means something — your school, heritage, or a favorite. One accent, used consistently, looks intentional. +- **Pitfall:** avoid fully‑saturated red/green *text* on dark backgrounds; always ask it to check contrast. + +--- + +## 2 · Typography +> Keep my content. Use a professional font pairing: a characterful sans‑serif for headings (e.g., **[Space Grotesk]**) and a highly readable sans‑serif for body (e.g., **[Inter]**), loaded from Google Fonts. Set a clear type scale and keep body text at least 16px. + +- **Personalize:** serif headings (e.g., *Fraunces*) read editorial and human; geometric sans reads modern‑tech. Match the font to your vibe from step 0. +- **Keep it pro:** two fonts maximum. Pair one distinctive heading font with one neutral body font. + +--- + +## 3 · The hero — your first impression (the 7‑second zone) +> Keep my content. Redesign my hero to be more striking but uncluttered: a larger name, my one‑line value proposition, and two clear buttons. Add a subtle background — a soft radial gradient in my accent color, low opacity. + +Add a photo or monogram: +> Add a circular headshot to my hero from `assets/me.jpg` at about 120px with a subtle border. If that image doesn't exist, fall back to my initials in a filled circle in my accent color. + +- **Personalize:** your tagline is the most personal line on the page. Make it about the *value you bring*, not just your title — e.g., "I turn messy data into decisions." + +--- + +## 4 · Project cards +> Keep my projects and links. Restyle the project cards: equal height, a gentle hover lift with a soft shadow, a thin accent‑colored top border, and tech tags as small rounded pills. Keep the 16:9 thumbnail area and make the whole card clickable. + +- **Personalize:** choose a card personality — *flat & minimal*, *soft glassy*, or *bordered & structured*. +- **Pitfall:** keep every card the same height so the grid stays tidy on all screen sizes. + +--- + +## 5 · Layout & rhythm +> Give the page more breathing room: increase the space between sections, cap the content width at about 1100px and center it, and add a faint divider line between sections. Keep it fully responsive. + +Denser alternative (for content‑heavy portfolios): +> Make the layout more compact and information‑dense while keeping it readable and aligned. + +- **Keep it pro:** whitespace reads as confidence. When in doubt, add space. + +--- + +## 6 · Motion — subtle and tasteful +> Add gentle, professional motion: fade‑and‑rise each section as it scrolls into view, and a smooth hover transition on buttons and cards. Keep every animation under 300ms and respect `prefers-reduced-motion`. + +- **Pitfall:** motion should be *felt, not noticed*. No bouncing, spinning, or autoplay. If it distracts from the content, cut it. + +--- + +## 7 · Dark / light toggle (a personal feature) +> Add a dark/light mode toggle button in my nav. Remember the choice with `localStorage`, follow the visitor's system setting on first load, and make sure both themes pass AA contrast. + +- **Personalize:** let your *default* theme match your vibe — light for warm/editorial, dark for modern‑tech. + +--- + +## 8 · Signature touches (light branding — pick at most one or two) +> Create a simple monogram favicon from my initials **[JR]** in my accent color and wire it into the page ``. + +More options: +> Add a tasteful footer with my name, a one‑line sign‑off, and links to GitHub, LinkedIn, and email. + +- **Personalize:** a monogram, a subtle custom cursor, or a small signature‑style sign‑off can make the site feel like *you*. +- **Keep it pro:** restraint. One or two signature touches, not five. + +--- + +## 9 · Make it unmistakably yours (a human detail) +> Add one short, professional personal line under About — one sentence about a hobby, what I'm currently learning, or what I care about. Keep it genuine and brief. + +- **Why:** one authentic detail is more memorable than another list of skills. It's the difference between a résumé and a *person*. + +--- + +## 10 · Final polish & the professional checklist +> Do a polish pass: consistent spacing and alignment, AA color contrast, clearly visible keyboard focus states, and check it looks right at 375px, 768px, and 1280px. Tell me anything that still looks off. + +**Professional checklist** +- [ ] One accent color, used consistently +- [ ] Two fonts maximum +- [ ] Project cards all the same height +- [ ] Text passes AA contrast (light *and* dark) +- [ ] Visible keyboard focus outlines +- [ ] Looks right on a phone (375px) +- [ ] Fast — no heavy libraries for a simple site + +--- + +## Attainability on the lowest model + +These prompts are written for **GPT‑5 mini**, the lowest model Auto serves students in the Copilot CLI. The rules that keep them reliable on a small model: + +- **Scope each prompt to one change** and lead with *"keep everything else the same."* +- **Give a concrete value** (a hex code, a px size, a font name) rather than leaving it open. +- **Verify visually and re‑prompt** if it over‑reaches — small models occasionally change more than asked; a one‑line correction fixes it. + +Do them in order, review after each, and the site stays coherent — no matter which model Auto picks. diff --git a/episode-02/portfolio/assets/content-refresh.svg b/episode-02/portfolio/assets/content-refresh.svg new file mode 100644 index 0000000..91fe472 --- /dev/null +++ b/episode-02/portfolio/assets/content-refresh.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/episode-02/portfolio/assets/first-gen-voices.svg b/episode-02/portfolio/assets/first-gen-voices.svg new file mode 100644 index 0000000..ac1030e --- /dev/null +++ b/episode-02/portfolio/assets/first-gen-voices.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/episode-02/portfolio/assets/recycling-dashboard.svg b/episode-02/portfolio/assets/recycling-dashboard.svg new file mode 100644 index 0000000..ea853cf --- /dev/null +++ b/episode-02/portfolio/assets/recycling-dashboard.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/episode-02/portfolio/assets/trail-journal.svg b/episode-02/portfolio/assets/trail-journal.svg new file mode 100644 index 0000000..1c17e13 --- /dev/null +++ b/episode-02/portfolio/assets/trail-journal.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/episode-02/portfolio/css/styles.css b/episode-02/portfolio/css/styles.css new file mode 100644 index 0000000..551107e --- /dev/null +++ b/episode-02/portfolio/css/styles.css @@ -0,0 +1,460 @@ +:root { + --bg: #fffdf9; + --surface: #ffffff; + --surface-soft: #fff6ef; + --text: #2f2a26; + --muted: #6f645d; + --accent: #c96f3d; + --accent-dark: #a95a2e; + --border: #ecdccf; + --radius: 16px; + --shadow: 0 8px 24px rgba(96, 65, 42, 0.08); +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, system-ui, sans-serif; + color: var(--text); + background: var(--bg); + line-height: 1.65; +} + +img { + display: block; + max-width: 100%; +} + +a { + color: var(--accent-dark); + text-underline-offset: 0.18em; +} + +a:hover, +a:focus-visible { + color: var(--accent); +} + +h1, +h2, +h3 { + line-height: 1.2; + margin: 0 0 0.6rem; +} + +h1 { + font-size: clamp(2.1rem, 5vw, 3.4rem); +} + +h2 { + font-size: clamp(1.5rem, 3vw, 2rem); +} + +.container { + width: min(1100px, 92%); + margin-inline: auto; +} + +.narrow { + width: min(780px, 92%); +} + +.skip-link { + position: absolute; + left: -999px; + top: -999px; + background: var(--text); + color: #fff; + padding: 0.7rem 1rem; + border-radius: 10px; +} + +.skip-link:focus { + left: 1rem; + top: 1rem; + z-index: 1000; +} + +.site-header { + position: sticky; + top: 0; + z-index: 100; + border-bottom: 1px solid var(--border); + background: rgba(255, 253, 249, 0.96); + backdrop-filter: blur(4px); +} + +.nav { + min-height: 4.25rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.brand { + color: var(--text); + text-decoration: none; + font-weight: 700; + letter-spacing: 0.01em; +} + +.nav-menu { + margin: 0; + padding: 0; + list-style: none; + display: flex; + gap: 1.3rem; +} + +.nav-menu a { + color: var(--text); + text-decoration: none; + font-weight: 600; +} + +.nav-menu a:hover, +.nav-menu a:focus-visible { + color: var(--accent-dark); +} + +.nav-toggle { + display: none; + width: 44px; + height: 44px; + border: 1px solid var(--border); + border-radius: 10px; + background: var(--surface); + padding: 10px 8px; + cursor: pointer; +} + +.nav-toggle span { + display: block; + height: 2px; + background: var(--text); + margin: 5px 0; +} + +.hero { + padding: clamp(4rem, 8vw, 7rem) 0; +} + +.hero-content { + width: min(800px, 100%); +} + +.eyebrow { + margin: 0; + color: var(--muted); + font-weight: 600; +} + +.headline { + margin: 0; + font-size: clamp(1.2rem, 2.7vw, 1.6rem); + color: var(--accent-dark); + font-weight: 600; +} + +.intro { + margin-top: 1rem; + font-size: 1.06rem; + max-width: 64ch; +} + +.hero-actions { + margin-top: 1.6rem; + display: flex; + flex-wrap: wrap; + gap: 0.8rem; +} + +.btn { + display: inline-block; + text-decoration: none; + font-weight: 700; + border-radius: 999px; + padding: 0.72rem 1.15rem; + transition: transform 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease; +} + +.btn:hover, +.btn:focus-visible { + transform: translateY(-1px); +} + +.btn-primary { + color: #fff; + background: var(--accent); +} + +.btn-primary:hover, +.btn-primary:focus-visible { + background: var(--accent-dark); + color: #fff; +} + +.btn-secondary { + color: var(--text); + background: var(--surface); + border: 1px solid var(--border); +} + +.hero-links { + margin-top: 1.1rem; + display: flex; + flex-wrap: wrap; + gap: 0.8rem; + list-style: none; + padding: 0; +} + +.section { + padding: clamp(3.2rem, 6vw, 4.8rem) 0; +} + +.section-soft { + background: var(--surface-soft); +} + +.about-meta p { + margin: 0.45rem 0; +} + +.skills-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 1rem; +} + +.card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: var(--shadow); + padding: 1.2rem; +} + +.timeline { + margin: 0; + padding: 0; + list-style: none; + position: relative; +} + +.timeline::before { + content: ""; + position: absolute; + left: 11px; + top: 0.6rem; + bottom: 0.6rem; + width: 2px; + background: var(--border); +} + +.timeline-item { + position: relative; + margin: 0 0 1rem 0; + padding-left: 2rem; +} + +.timeline-item::before { + content: ""; + position: absolute; + left: 3px; + top: 1.3rem; + width: 18px; + height: 18px; + border-radius: 50%; + border: 2px solid var(--accent); + background: var(--bg); +} + +.role-meta, +.org { + margin: 0; + color: var(--muted); +} + +.card ul { + margin: 0.7rem 0 0; + padding-left: 1.1rem; +} + +.projects-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1.1rem; +} + +.project-card { + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; + background: var(--surface); + box-shadow: var(--shadow); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.project-card:hover, +.project-card:focus-within { + transform: translateY(-2px); + box-shadow: 0 12px 26px rgba(96, 65, 42, 0.12); +} + +.project-card img { + width: 100%; + aspect-ratio: 16 / 9; + object-fit: cover; + border-bottom: 1px solid var(--border); +} + +.project-content { + padding: 1rem 1rem 1.1rem; +} + +.project-content p { + margin: 0; +} + +.project-content .tags { + margin-top: 0.65rem; + color: var(--muted); + font-size: 0.93rem; + font-weight: 600; +} + +.involvement { + color: var(--muted); +} + +.site-footer { + border-top: 1px solid var(--border); + padding: 1.1rem 0 1.6rem; + color: var(--muted); +} + +@media (max-width: 920px) { + .skills-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 760px) { + .nav-toggle { + display: inline-block; + } + + .nav-menu { + position: absolute; + left: 4%; + right: 4%; + top: calc(100% + 0.4rem); + flex-direction: column; + gap: 0; + background: var(--surface); + border: 1px solid var(--border); + border-radius: 14px; + box-shadow: var(--shadow); + opacity: 0; + visibility: hidden; + transform: translateY(-8px); + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease; + } + + .nav-menu li + li { + border-top: 1px solid var(--border); + } + + .nav-menu a { + display: block; + padding: 0.85rem 1rem; + } + + .nav-menu.is-open { + opacity: 1; + visibility: visible; + transform: translateY(0); + } + + .projects-grid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 560px) { + .skills-grid { + grid-template-columns: 1fr; + } +} + +/* Email popup modal */ +.email-modal[hidden] { display: none; } +.email-modal { + position: fixed; + inset: 0; + z-index: 200; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; +} +.email-modal__overlay { + position: absolute; + inset: 0; + background: rgba(47, 42, 38, 0.5); +} +.email-modal__dialog { + position: relative; + z-index: 1; + width: min(100%, 420px); + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + box-shadow: 0 20px 50px rgba(96, 65, 42, 0.22); + padding: 1.5rem; +} +.email-modal__close { + position: absolute; + top: 0.5rem; + right: 0.7rem; + border: none; + background: transparent; + font-size: 1.6rem; + line-height: 1; + color: var(--muted); + cursor: pointer; +} +.email-modal__close:hover, +.email-modal__close:focus-visible { color: var(--text); } +.email-modal__title { margin: 0 0 0.3rem; } +.email-modal__desc { margin: 0 0 1rem; color: var(--muted); } +.email-modal__address { + display: flex; + align-items: center; + gap: 0.5rem; + background: var(--surface-soft); + border: 1px solid var(--border); + border-radius: 12px; + padding: 0.4rem 0.4rem 0.4rem 0.85rem; + margin-bottom: 0.9rem; +} +.email-modal__address span { + flex: 1; + font-family: "SFMono-Regular", ui-monospace, Consolas, monospace; + font-size: 0.92rem; + overflow-wrap: anywhere; +} +.email-modal__copy { white-space: nowrap; } +.email-modal__copy.copied { background: #3f8f5b; color: #fff; } +.email-modal__mail { width: 100%; text-align: center; } diff --git a/episode-02/portfolio/index.html b/episode-02/portfolio/index.html new file mode 100644 index 0000000..367bcfb --- /dev/null +++ b/episode-02/portfolio/index.html @@ -0,0 +1,208 @@ + + + + + + + Jamie Rivera | Portfolio + + + + + + + +
+
+
+

Seattle, WA

+

Jamie Rivera

+

Storyteller and data-curious.

+

+ I turn ideas into clear stories across writing, audio, and social, then use simple data to show impact. +

+ + +
+
+ +
+
+

About

+

+ I’m a junior Communication & Media Studies major at Cascade State University, with a minor in Data Analytics. + My work sits at the intersection of creativity and clarity: writing content people actually read, producing media that + feels human, and using lightweight data to understand what’s working. I’m currently looking for roles in content, + communications, and community programs. +

+
+

Education: B.A. Communication & Media Studies, Minor in Data Analytics (Expected May 2027)

+

GPA: 3.7 / 4.0

+

Relevant coursework: Digital Media Production, Intro to Data Analytics, Public Relations Writing, Web Content and Design

+
+
+
+ +
+
+

Skills

+
+
+

Tools

+

Microsoft 365 (Word, Excel, PowerPoint), Canva, Adobe Express, Audacity, basic HTML & CSS, Git & GitHub (learning)

+
+
+

Data & Research

+

Spreadsheets, basic charting, survey design

+
+
+

Communication

+

Copywriting, public speaking, social media strategy

+
+
+

Languages

+

English (native), Spanish (conversational)

+
+
+
+
+ +
+
+

Experience

+
    +
  1. +
    +

    Jun 2025 - Present · Seattle, WA

    +

    Marketing & Communications Intern

    +

    Greenline Community Trust

    +
      +
    • Rebuilt the nonprofit’s social presence and grew Instagram following by 40% in one semester.
    • +
    • Write and schedule a weekly newsletter reaching 1,200+ subscribers.
    • +
    • Produce short-form volunteer event recaps, from filming through captions.
    • +
    +
    +
  2. +
  3. +
    +

    Sep 2024 - Present · Seattle, WA

    +

    Peer Writing Tutor

    +

    Cascade State Writing Center

    +
      +
    • Coach 60+ students per term on essays, résumés, and applications.
    • +
    • Led two campus workshops on clear, structured writing.
    • +
    +
    +
  4. +
  5. +
    +

    2023 - 2024

    +

    Barista

    +

    Foghorn Coffee

    +
      +
    • Trained four new hires and kept service moving during high-volume mornings.
    • +
    +
    +
  6. +
+
+
+ +
+
+

Featured Projects

+
+
+ Abstract illustration representing a podcast conversation. +
+

First-Gen Voices Podcast

+

Student podcast featuring first-generation stories, with 15 episodes and 2,000+ downloads.

+

Podcast · Audio

+
+
+
+ Abstract chart shapes representing recycling trends. +
+

Campus Recycling Dashboard

+

Analyzed two years of waste data and translated trends into practical recommendations.

+

Data · Charts

+
+
+
+ Abstract layout blocks representing improved web content flow. +
+

Greenline Content Refresh

+

Rewrote “Get Involved” content and simplified signups to increase form completions.

+

Writing · UX

+
+
+
+ Abstract landscape illustration inspired by Pacific Northwest trails. +
+

Trail Journal

+

A growing photo-and-notes log documenting Pacific Northwest day hikes.

+

Photography · Storytelling

+
+
+
+
+
+ +
+
+

Contact

+

+ I’d love to connect about content, communications, and community-focused opportunities. +

+

+ +

+

+ Founder, First-Gen Voices Podcast · Member, Campus Sustainability Club · Volunteer, Seattle Public Library reading program +

+
+
+
+ + + + + + + + diff --git a/episode-02/portfolio/js/main.js b/episode-02/portfolio/js/main.js new file mode 100644 index 0000000..50d7c0e --- /dev/null +++ b/episode-02/portfolio/js/main.js @@ -0,0 +1,101 @@ +const navToggle = document.querySelector(".nav-toggle"); +const navMenu = document.querySelector(".nav-menu"); +const navLinks = document.querySelectorAll(".nav-menu a"); +const yearNode = document.getElementById("year"); + +if (yearNode) { + yearNode.textContent = new Date().getFullYear(); +} + +if (navToggle && navMenu) { + const setMenuState = (isOpen) => { + navMenu.classList.toggle("is-open", isOpen); + navToggle.setAttribute("aria-expanded", String(isOpen)); + navToggle.setAttribute("aria-label", isOpen ? "Close menu" : "Open menu"); + }; + + navToggle.addEventListener("click", () => { + const expanded = navToggle.getAttribute("aria-expanded") === "true"; + setMenuState(!expanded); + }); + + navLinks.forEach((link) => { + link.addEventListener("click", () => setMenuState(false)); + }); + + document.addEventListener("keydown", (event) => { + if (event.key === "Escape") { + setMenuState(false); + } + }); +} + +// Email popup modal +const emailModal = document.getElementById("emailModal"); +if (emailModal) { + const triggers = document.querySelectorAll(".email-trigger"); + const addressEl = document.getElementById("emailAddress"); + const copyBtn = document.getElementById("copyEmailBtn"); + const mailBtn = document.getElementById("openMailBtn"); + const closers = emailModal.querySelectorAll("[data-close]"); + let lastFocused = null; + let copyResetTimer; + + const resetCopy = () => { + clearTimeout(copyResetTimer); + copyBtn.textContent = "Copy"; + copyBtn.classList.remove("copied"); + }; + + function closeModal() { + emailModal.hidden = true; + resetCopy(); + document.removeEventListener("keydown", onKeydown); + if (lastFocused && typeof lastFocused.focus === "function") lastFocused.focus(); + } + + function onKeydown(event) { + if (event.key === "Escape") closeModal(); + } + + const openModal = (email) => { + if (email) { + addressEl.textContent = email; + mailBtn.href = "mailto:" + email; + } + lastFocused = document.activeElement; + emailModal.hidden = false; + copyBtn.focus(); + document.addEventListener("keydown", onKeydown); + }; + + const copyEmail = async () => { + const email = addressEl.textContent.trim(); + try { + await navigator.clipboard.writeText(email); + } catch (err) { + const ta = document.createElement("textarea"); + ta.value = email; + ta.setAttribute("readonly", ""); + ta.style.position = "absolute"; + ta.style.left = "-9999px"; + document.body.appendChild(ta); + ta.select(); + try { document.execCommand("copy"); } catch (e) { /* no-op */ } + document.body.removeChild(ta); + } + copyBtn.textContent = "Copied!"; + copyBtn.classList.add("copied"); + clearTimeout(copyResetTimer); + copyResetTimer = setTimeout(resetCopy, 2000); + }; + + triggers.forEach((trigger) => { + trigger.addEventListener("click", (event) => { + event.preventDefault(); + openModal(trigger.dataset.email); + }); + }); + copyBtn.addEventListener("click", copyEmail); + closers.forEach((closer) => closer.addEventListener("click", closeModal)); +} diff --git a/episode-02/portfolio/resume/Jamie-Rivera-Resume.docx b/episode-02/portfolio/resume/Jamie-Rivera-Resume.docx new file mode 100644 index 0000000..5108f18 Binary files /dev/null and b/episode-02/portfolio/resume/Jamie-Rivera-Resume.docx differ diff --git a/episode-02/preview.png b/episode-02/preview.png new file mode 100644 index 0000000..c5d5434 Binary files /dev/null and b/episode-02/preview.png differ diff --git a/episode-02/prompt.md b/episode-02/prompt.md new file mode 100644 index 0000000..6329906 --- /dev/null +++ b/episode-02/prompt.md @@ -0,0 +1,30 @@ +Build me a personal portfolio website I can host for free on GitHub Pages. Use only plain HTML, CSS, and a little vanilla JavaScript — no frameworks and no build step. + +CONTEXT — my résumé: +Name: Jamie Rivera — Communication & Media Studies student, based in Seattle, WA. +Headline: Storyteller and data-curious. +Contact: jamie.rivera@cascade.edu +Summary: Junior Communication & Media Studies major with a Data Analytics minor who turns ideas into clear stories across writing, audio, and social. I pair creative work with simple data to show impact, and I'm looking for roles in content, communications, and community programs. +Education: Cascade State University, Seattle, WA — B.A. in Communication & Media Studies, Minor in Data Analytics. Expected May 2027. GPA 3.7/4.0. Relevant coursework: Digital Media Production, Intro to Data Analytics, Public Relations Writing, Web Content and Design. +Experience: +- Marketing & Communications Intern, Greenline Community Trust (Jun 2025–Present, Seattle) — rebuilt the nonprofit's social presence and grew Instagram following 40% in a semester; write and schedule a weekly newsletter reaching 1,200+ subscribers; produce short-form video recaps of volunteer events, from filming to captions. +- Peer Writing Tutor, Cascade State Writing Center (Sep 2024–Present, Seattle) — coach 60+ students per term on essays, resumes, and applications; led two campus workshops on clear, structured writing. +- Barista, Foghorn Coffee (2023–2024) — trained four new hires and kept service moving during high-volume mornings. +Featured projects: +- First-Gen Voices Podcast — Founder & Producer (2024–Present). A student podcast interviewing first-generation college students; 15 episodes and 2,000+ downloads. I own recording, editing, cover art, and release scheduling. +- Campus Recycling Dashboard — Data Analytics course project (Spring 2025). Analyzed two years of campus waste data and built simple charts showing recycling trends; recommended three changes the campus sustainability office later piloted. +- Greenline Content Refresh — Internship project (2025). Rewrote the "Get Involved" page and simplified the volunteer signup flow, lifting form completions. +- Trail Journal — Personal project (ongoing). A growing photo-and-notes log of Pacific Northwest day hikes. +Skills: Microsoft 365 (Word, Excel, PowerPoint), Canva, Adobe Express, Audacity, basic HTML & CSS, Git & GitHub (learning); spreadsheets, basic charting, survey design; copywriting, public speaking, social media strategy; English (native), Spanish (conversational). +Leadership & involvement: Founder, First-Gen Voices Podcast; Member, Campus Sustainability Club; Volunteer, Seattle Public Library reading program. + +SPECIFICS — build these: +- A sticky top navigation and a hero with my name, my headline, a one-line intro, two buttons ("View my work" and "Download résumé"), and contact links (email, and GitHub). +- Sections in this order: About, Skills (grouped by category), Experience (as a timeline), Featured Projects, and Contact. +- Featured Projects is a responsive grid of cards. Each card has: a 16:9 image area at the top, the project title, a one-line description, and small topic tags (e.g., "Podcast · Audio", "Data · Charts", "Writing · UX", "Photography"). These are creative/media projects, not code — so do NOT add "View on GitHub" links; keep the cards descriptive. +- File structure: index.html, css/styles.css, js/main.js, and an assets/ folder for images. +- Fully responsive with a working mobile navigation toggle. Use semantic, accessible HTML. + +STYLE — clean, modern, warm, and professional — this is a storyteller's portfolio, not a developer's. Use a light, readable theme with a single warm accent color, generous whitespace, rounded cards, and subtle hover effects. Use a friendly system font stack. Prioritize readability and a welcoming, human feel. + +Create all of the files now. diff --git a/episode-08/Jamie-Rivera-Portfolio.pptx b/episode-08/Jamie-Rivera-Portfolio.pptx new file mode 100644 index 0000000..88015f6 Binary files /dev/null and b/episode-08/Jamie-Rivera-Portfolio.pptx differ diff --git a/episode-08/Jamie-Rivera-Resume.docx b/episode-08/Jamie-Rivera-Resume.docx new file mode 100644 index 0000000..5108f18 Binary files /dev/null and b/episode-08/Jamie-Rivera-Resume.docx differ diff --git a/episode-08/README.md b/episode-08/README.md index 7402050..0f6c2e8 100644 --- a/episode-08/README.md +++ b/episode-08/README.md @@ -1,10 +1,30 @@ -# Episode 08 +# Episode 08 — MCPs: Give Your Agent Superpowers -_Title to be added._ +An **MCP** (Model Context Protocol server) is like a **USB-C port for your AI** — one standard plug +that lets your Copilot CLI agent use other apps: Word, PowerPoint, a web browser, and GitHub itself. +This episode adds real tools to the portfolio you built in Episode 2. -This folder holds the artifacts for Episode 08 of the Student AI Learning Series — -things like the scoping brief, prompts used on camera, demo assets, screenshots, and any -code snippets shown in the video. +- **Persona:** Jamie Rivera (see [`../common/`](../common/)). + +## The moves in this episode +- **Word MCP → a real résumé.** The agent generates a formatted `.docx` résumé — + **`Jamie-Rivera-Resume.docx`** — which the site's "Download résumé" button points to. +- **PowerPoint MCP → a matching deck.** A slide deck built from the same résumé — + **`Jamie-Rivera-Portfolio.pptx`**. +- **GitHub MCP → find a starting point.** The agent searches all of GitHub for repositories and + templates that fit your vision. The reusable, evergreen prompt is in **`find-repos-prompt.md`**. + +## What's in this folder +- **`find-repos-prompt.md`** — the resilient "find repositories that fit my vision" prompt (never + hardcodes repo names, dates, or star counts, so it stays current). +- **`mcp-config.json`** — the Office (Word + PowerPoint) MCP configuration for the Copilot CLI. +- **`Jamie-Rivera-Resume.docx`** — the Word-MCP résumé. +- **`Jamie-Rivera-Portfolio.pptx`** — the PowerPoint deck. +- **`preview.png`** — the deck's title slide. + +## Setup note +The Office MCP servers run via `uvx` (no local install needed). The Word server needs a raised +startup `timeout` — already set in `mcp-config.json` — or the CLI drops it during startup. Add them +with `copilot --additional-mcp-config "@episode-08/mcp-config.json"`. The GitHub MCP is built into +the Copilot CLI, so the "find repositories" move needs no extra setup. -Drop episode files directly in this folder. Shared assets used across episodes (such as the -mock resume) live in [../common/](../common/). diff --git a/episode-08/find-repos-prompt.md b/episode-08/find-repos-prompt.md new file mode 100644 index 0000000..661be83 --- /dev/null +++ b/episode-08/find-repos-prompt.md @@ -0,0 +1,46 @@ +# Ep 8 — Find GitHub repositories that fit your vision (evergreen query) + +One of the most useful things an MCP unlocks: your agent can **search GitHub for you**. Instead of scrolling through thousands of repos, describe what you want and let the agent find, vet, and shortlist real repositories that match — a starting template, a reference, or inspiration. + +This uses the **GitHub MCP** (built into the Copilot CLI — no extra setup). The prompt is written to stay **resilient and current**: it never hardcodes repo names, usernames, star counts, or a fixed year, so it keeps working as GitHub evolves. + +## The reusable prompt +Replace **[vision]** with your own and paste it into the CLI: + +> Find GitHub repositories that match this vision: **[describe the style, type, and tech — e.g., "a clean, minimalist dark‑mode developer portfolio in plain HTML and CSS that I can fork and customize"]**. +> +> Use the GitHub MCP and keep the search resilient and current: +> - Turn my vision into search qualifiers: the most relevant `topic:` tags, the right `language:` filters, and keywords from my description. +> - Only surface repos usable today: `archived:false`, and recently maintained — compute a `pushed:>` date about two years before **today's** date (don't hardcode a year). +> - Prefer licenses I can reuse (MIT, Apache‑2.0, or clearly stated) and rank by a blend of stars and recent activity, not a fixed star count. +> - Return the top 5. For each: name + link, a one‑line description, stars, last‑updated, license, and one sentence on **why it fits my vision**. +> - If there are fewer than 5 strong matches, broaden the terms and search again before answering. +> - Only list repositories the search actually returns; flag any that look unmaintained or have an unclear license. + +## Why this stays evergreen +It leans only on **stable GitHub search qualifiers**, and lets the agent compute the time‑sensitive parts: + +| Qualifier | Why it's resilient | +|---|---| +| `topic:` (e.g., `portfolio`, `portfolio-template`) | Topics are curated and long‑lived | +| `language:HTML` / `language:CSS` | Language names don't churn | +| `archived:false` | Always excludes dead repos | +| `pushed:>` *(agent computes ~2y ago)* | Relative to *today*, so it never goes stale | +| `license:` filter | Keeps results reusable | +| **Sort** by stars + recent activity | Surfaces what's good *now*, not a frozen list | + +No repo names, usernames, dates, or star thresholds are baked in — so the same prompt works this year and next. + +## Swap the vision — it's fully generic +The exact same prompt finds a starting point for anything: +- *"a modern SaaS landing page with a hero, features, and pricing, using Tailwind CSS"* +- *"a minimalist markdown blog I can deploy on GitHub Pages"* +- *"a React dashboard template with charts, MIT‑licensed"* +- *"a simple restaurant one‑pager with a menu and a contact form"* + +## Good habits to teach on camera +- **Check the license** before forking — ten seconds, saves headaches. +- **Open the top result** and skim the README and last commit — the agent can do this for you. +- **Describe outcomes, not repo names** — you search by *vision*; the agent handles the syntax. + +> This move replaces any hardcoded, dated repo lists. It's the difference between "here are my six repos" (specific, ages badly) and "find me what fits, right now" (generic, always current). diff --git a/episode-08/mcp-config.json b/episode-08/mcp-config.json new file mode 100644 index 0000000..7e24898 --- /dev/null +++ b/episode-08/mcp-config.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "playwright": { + "type": "local", + "command": "npx", + "args": ["-y", "@playwright/mcp@0.0.78", "--isolated", "--browser", "chromium"], + "tools": ["*"], + "timeout": 60000 + } + } +} diff --git a/episode-08/preview.png b/episode-08/preview.png new file mode 100644 index 0000000..28661bb Binary files /dev/null and b/episode-08/preview.png differ