diff --git a/docs/sprint-artifacts/2-1-create-resume-page-route.context.xml b/docs/sprint-artifacts/2-1-create-resume-page-route.context.xml new file mode 100644 index 0000000..41cc64a --- /dev/null +++ b/docs/sprint-artifacts/2-1-create-resume-page-route.context.xml @@ -0,0 +1,100 @@ + + + 2 + 2.1 + Create Resume Page Route + ready-for-dev + 2025-11-30 + BMAD Story Context Workflow + docs/sprint-artifacts/2-1-create-resume-page-route.md + + + + user + to access my resume at `/resume` + I can view it before downloading + + - Create resume page route (AC: #1, #2) + - Configure page metadata (AC: #4, #5) + - Implement print mode detection (AC: #6) + - Add placeholder content (AC: #1) + - Test page functionality + + + + + Given I navigate to `/resume`, when the page loads, then I see the resume preview + The page is standalone (no site header/footer) + The page has a white background + The page title is "Resume - Ali Arghyani" + Meta tags are set for SEO (noindex for privacy) + Given I add `?print=true` query parameter, when the page loads, then the download button is hidden (for PDF generation) + + + + + + docs/architecture.md + Resume Export Feature - Architecture Document +
Novel Pattern: WYSIWYG PDF Export
+ Single component renders both web preview and PDF source. Query Parameter: `?print=true` hides download button in PDF. +
+ + docs/architecture.md + Resume Export Feature - Architecture Document +
Project Structure
+ File: `app/pages/resume.vue` - /resume route (standalone page) +
+ + docs/sprint-artifacts/tech-spec-epic-2.md + Epic Technical Specification: Resume Preview Page +
AC1: Standalone Resume Route
+ Page is standalone (no site header/footer), page title is "Resume - Ali Arghyani", meta tag `` is present +
+
+ + + + + + + + + +
+ + + - Use `definePageMeta({ layout: false })` for standalone page + - Use `useHead()` or `useSeoMeta()` for metadata + - Use `useRoute().query.print` for print mode detection + - File location must be `app/pages/resume.vue` (Nuxt file-based routing) + - White background: `bg-white` class + + + + + useRoute + Nuxt composable + const route = useRoute(); const isPrintMode = computed(() => route.query.print === 'true') + nuxt/app + + + useHead + Nuxt composable + useHead({ title: string, meta: Array<{ name: string, content: string }> }) + nuxt/app + + + + + Nuxt 4 testing with Vitest. Test page routing, metadata, and print mode detection. + tests/, app/**/*.spec.ts + + Navigate to /resume and verify page renders + Check that no layout is applied (standalone) + Verify page title in document.title + Check for noindex meta tag in DOM + Test with ?print=true parameter and verify isPrintMode is true + + +
diff --git a/docs/sprint-artifacts/2-1-create-resume-page-route.md b/docs/sprint-artifacts/2-1-create-resume-page-route.md new file mode 100644 index 0000000..85ac38a --- /dev/null +++ b/docs/sprint-artifacts/2-1-create-resume-page-route.md @@ -0,0 +1,151 @@ +# Story 2.1: Create Resume Page Route + +Status: ready-for-dev + +## Story + +As a user, +I want to access my resume at `/resume`, +so that I can view it before downloading. + +## Acceptance Criteria + +1. **AC1:** Given I navigate to `/resume`, when the page loads, then I see the resume preview +2. **AC2:** The page is standalone (no site header/footer) +3. **AC3:** The page has a white background +4. **AC4:** The page title is "Resume - Ali Arghyani" +5. **AC5:** Meta tags are set for SEO (noindex for privacy) +6. **AC6:** Given I add `?print=true` query parameter, when the page loads, then the download button is hidden (for PDF generation) + +## Tasks / Subtasks + +- [ ] Create resume page route (AC: #1, #2) + - [ ] Create `app/pages/resume.vue` file + - [ ] Use `definePageMeta({ layout: false })` for standalone page + - [ ] Add basic page structure with white background + +- [ ] Configure page metadata (AC: #4, #5) + - [ ] Set page title using `useHead()` or `useSeoMeta()` + - [ ] Add `` for privacy + - [ ] Ensure title format: "Resume - Ali Arghyani" + +- [ ] Implement print mode detection (AC: #6) + - [ ] Use `useRoute().query.print` to detect print parameter + - [ ] Pass print mode state to child components + - [ ] Verify download button visibility logic + +- [ ] Add placeholder content (AC: #1) + - [ ] Import `ResumePreview` component (will be created in Story 2.2) + - [ ] For now, add placeholder text: "Resume Preview Coming Soon" + - [ ] Ensure page renders without errors + +- [ ] Test page functionality + - [ ] Navigate to `/resume` and verify standalone layout + - [ ] Check page title in browser tab + - [ ] Inspect meta tags in DOM + - [ ] Test `/resume?print=true` parameter handling + - [ ] Verify white background styling + +## Dev Notes + +### Architecture Alignment + +**From Architecture Doc:** +- File location: `app/pages/resume.vue` (confirmed in Project Structure section) +- Layout: Use `definePageMeta({ layout: false })` for standalone page +- Query parameter: `?print=true` hides download button for PDF generation +- SEO: `noindex` meta tag for privacy (resume not indexed by search engines) + +**From Tech Spec Epic 2:** +- AC1-AC6 map directly to this story +- Page serves dual purposes: (1) user preview, (2) PDF generation source +- WYSIWYG approach: same page renders for web and PDF + +### Project Structure Notes + +**File to Create:** +- `app/pages/resume.vue` - Main resume route + +**Dependencies:** +- Nuxt 4 routing (file-based) +- `useHead()` or `useSeoMeta()` composable for metadata +- `useRoute()` composable for query parameter detection + +**Future Integration:** +- Story 2.2 will create `ResumePreview.vue` component to replace placeholder +- Story 2.5 will create `ResumeDownloadButton.vue` that respects print mode + +### Implementation Notes + +**Page Structure:** +```vue + + + +``` + +**Testing Checklist:** +- [ ] Page accessible at `http://localhost:3000/resume` +- [ ] No site navigation visible (header/footer) +- [ ] White background applied +- [ ] Browser tab shows "Resume - Ali Arghyani" +- [ ] Meta tag `` present in DOM +- [ ] `?print=true` parameter detected correctly + +### References + +- [Source: docs/architecture.md#Novel-Pattern-WYSIWYG-PDF-Export] +- [Source: docs/architecture.md#Project-Structure] +- [Source: docs/sprint-artifacts/tech-spec-epic-2.md#AC1-Standalone-Resume-Route] +- [Source: docs/epics.md#Story-2.1-Create-Resume-Page-Route] + +## Dev Agent Record + +### Context Reference + +- docs/sprint-artifacts/2-1-create-resume-page-route.context.xml + +### Agent Model Used + + + +### Debug Log References + + + +### Completion Notes List + + + +### File List + + + +--- + +**Change Log:** +- 2025-11-30: Story drafted by SM agent (mahdi) diff --git a/docs/sprint-artifacts/2-2-create-resume-preview-container-component.context.xml b/docs/sprint-artifacts/2-2-create-resume-preview-container-component.context.xml new file mode 100644 index 0000000..6c3d95e --- /dev/null +++ b/docs/sprint-artifacts/2-2-create-resume-preview-container-component.context.xml @@ -0,0 +1,147 @@ + + + 2 + 2.2 + Create Resume Preview Container Component + ready-for-dev + 2025-11-30 + BMAD Story Context Workflow + docs/sprint-artifacts/2-2-create-resume-preview-container-component.md + + + + developer + a container component that renders the full resume + I have a single source of truth for web and PDF + + - Create ResumePreview component file + - Implement two-column layout + - Configure container dimensions + - Apply color scheme and typography + - Add print styles + - Integrate data from composable + - Add placeholder sections + - Test component rendering + + + + + Two-column layout with left sidebar (35% width) and right main content (65% width) + Container has A4 aspect ratio (210mm × 297mm) + Page margins are 24px (1.5rem) + Background is white + Color scheme is blue (#2563eb) and white + Typography uses Inter font for English text + Proper heading hierarchy (h1 for name, h2 for sections) + Body text is 14px (0.875rem) + ATS-readable font sizes + Layout is responsive - desktop shows two-column side by side, mobile shows single column (sidebar on top) + Print styles included - `.no-print` class hides elements in print + Page breaks are controlled + Colors print correctly (`printBackground: true`) + + + + + + docs/architecture.md + Resume Export Feature - Architecture Document +
Consistency Rules - Color Scheme
+ Primary (headers, icons): Blue - text-blue-600, bg-blue-600. Background: White - bg-white. Text: Dark gray - text-gray-800. +
+ + docs/architecture.md + Resume Export Feature - Architecture Document +
Consistency Rules - Typography
+ Name: Inter, 2rem, Bold. Section Headers: Inter, 1rem, Semibold. Body Text: Inter, 0.875rem, Normal. +
+ + docs/architecture.md + Resume Export Feature - Architecture Document +
Consistency Rules - Spacing
+ Page margins: 1.5rem (24px). Section gap: 1.5rem. Sidebar width: 35%. Main content width: 65%. +
+ + docs/sprint-artifacts/tech-spec-epic-2.md + Epic Technical Specification: Resume Preview Page +
AC2: Two-Column Layout
+ Two-column grid: Left sidebar (35% width): Contact, Skills, Education, Languages. Right main content (65% width): Header, Summary, Experience. Container has A4 aspect ratio (210mm × 297mm). +
+
+ + + app/composables/useResumeData.ts + composable + useResumeData + Provides reactive access to resume data for this component + + + app/types/resume.ts + types + Resume, ResumeBasics, WorkExperience, Education, Skill, Language + TypeScript interfaces for resume data structure + + + app/data/resume.en.ts + data + resumeData + Sample resume data to display + + + app/pages/resume.vue + page + resume page + Will import and render this ResumePreview component + + + + + + + + + + +
+ + + - Use CSS Grid for two-column layout + - Tailwind classes for all styling + - A4 dimensions: max-w-[210mm] min-h-[297mm] + - Margins: p-6 (1.5rem = 24px) + - Responsive breakpoint: md:grid-cols-[35%_65%] + - Print styles: @media print with .no-print class + - Color palette: Blue #2563eb, White #ffffff, Gray #1f2937 + - Typography: text-sm (0.875rem) for body, text-base for headers + - File location: app/components/resume/ResumePreview.vue + + + + + useResumeData + composable + const { resume, formatDate, getFullName, getPdfFilename } = useResumeData() + app/composables/useResumeData.ts + + + Resume + TypeScript interface + interface Resume { basics: ResumeBasics; work: WorkExperience[]; education: Education[]; skills: Skill[]; languages?: Language[] } + app/types/resume.ts + + + + + Nuxt 4 component testing with Vitest. Test layout, responsive behavior, and print styles. + app/components/**/*.spec.ts + + Mount component and verify two-column grid structure + Check container dimensions match A4 (210mm × 297mm) + Verify padding is 1.5rem (24px) + Check background color is white + Verify blue color (#2563eb) is applied + Test responsive behavior at mobile breakpoint + Verify .no-print class exists in styles + + +
diff --git a/docs/sprint-artifacts/2-2-create-resume-preview-container-component.md b/docs/sprint-artifacts/2-2-create-resume-preview-container-component.md new file mode 100644 index 0000000..24d745d --- /dev/null +++ b/docs/sprint-artifacts/2-2-create-resume-preview-container-component.md @@ -0,0 +1,232 @@ +# Story 2.2: Create Resume Preview Container Component + +Status: ready-for-dev + +## Story + +As a developer, +I want a container component that renders the full resume, +so that I have a single source of truth for web and PDF. + +## Acceptance Criteria + +1. **AC1:** Given the ResumePreview component is rendered, when it displays, then it shows a two-column layout with left sidebar (35% width) and right main content (65% width) +2. **AC2:** The container has A4 aspect ratio (210mm × 297mm) +3. **AC3:** Page margins are 24px (1.5rem) +4. **AC4:** Background is white +5. **AC5:** Color scheme is blue (#2563eb) and white +6. **AC6:** Typography uses Inter font for English text +7. **AC7:** Proper heading hierarchy (h1 for name, h2 for sections) +8. **AC8:** Body text is 14px (0.875rem) +9. **AC9:** ATS-readable font sizes +10. **AC10:** Layout is responsive - desktop shows two-column side by side, mobile shows single column (sidebar on top) +11. **AC11:** Print styles included - `.no-print` class hides elements in print +12. **AC12:** Page breaks are controlled +13. **AC13:** Colors print correctly (`printBackground: true`) + +## Tasks / Subtasks + +- [ ] Create ResumePreview component file (AC: #1-#13) + - [ ] Create `app/components/resume/ResumePreview.vue` + - [ ] Set up component structure with script setup and TypeScript + +- [ ] Implement two-column layout (AC: #1, #10) + - [ ] Use CSS Grid for two-column layout + - [ ] Set sidebar width to 35%, main content to 65% + - [ ] Add responsive breakpoint for mobile (single column) + - [ ] Ensure sidebar appears above main content on mobile + +- [ ] Configure container dimensions (AC: #2, #3) + - [ ] Set container to A4 aspect ratio (210mm × 297mm) + - [ ] Apply 24px (1.5rem) margins + - [ ] Use Tailwind classes: `max-w-[210mm] min-h-[297mm] p-6` + +- [ ] Apply color scheme and typography (AC: #4-#9) + - [ ] Set white background: `bg-white` + - [ ] Define blue primary color: `text-blue-600` (#2563eb) + - [ ] Configure Inter font (already available via @nuxt/fonts) + - [ ] Set body text size: `text-sm` (0.875rem) + - [ ] Ensure proper heading hierarchy (h1, h2) + +- [ ] Add print styles (AC: #11-#13) + - [ ] Create `.no-print` utility class + - [ ] Add `@media print` styles + - [ ] Set `printBackground: true` for colors + - [ ] Control page breaks with `break-inside-avoid` + +- [ ] Integrate data from composable + - [ ] Import `useResumeData()` composable + - [ ] Access `resume` reactive reference + - [ ] Prepare for child component integration (Stories 2.3, 2.4) + +- [ ] Add placeholder sections + - [ ] Add comment placeholders for child components + - [ ] Structure: Sidebar (Contact, Skills, Education, Languages) + - [ ] Structure: Main (Header, Summary, Experience) + +- [ ] Test component rendering + - [ ] Import component in `pages/resume.vue` + - [ ] Verify two-column layout on desktop + - [ ] Test responsive behavior on mobile + - [ ] Check print preview (Ctrl+P) + - [ ] Verify A4 dimensions and margins + +## Dev Notes + +### Architecture Alignment + +**From Architecture Doc:** +- File location: `app/components/resume/ResumePreview.vue` +- Layout: CSS Grid for two-column design +- Styling: Tailwind CSS utilities +- Data source: `useResumeData()` composable from Epic 1 + +**From Tech Spec Epic 2:** +- AC1-AC13 map directly to this story +- Container is the main orchestrator for all resume sections +- WYSIWYG pattern: same component for web and PDF + +### Learnings from Previous Story + +**From Story 2.1 (Status: drafted)** +- Page route created at `app/pages/resume.vue` +- Standalone layout configured with `definePageMeta({ layout: false })` +- Print mode detection implemented via `useRoute().query.print` +- White background and metadata already set +- **Integration Point**: Import `ResumePreview` component to replace placeholder + +[Source: docs/sprint-artifacts/2-1-create-resume-page-route.md] + +### Project Structure Notes + +**File to Create:** +- `app/components/resume/ResumePreview.vue` - Main container component + +**Dependencies:** +- `app/composables/useResumeData.ts` (Epic 1 - completed) +- `app/types/resume.ts` (Epic 1 - completed) +- `app/data/resume.en.ts` (Epic 1 - completed) +- Tailwind CSS (existing) +- @nuxt/fonts with Inter (existing) + +**Future Integration:** +- Story 2.3 will create Header, Summary, Experience components +- Story 2.4 will create Contact, Skills, Education, Languages components +- Story 2.5 will create Download Button component + +### Implementation Notes + +**Component Structure:** +```vue + + + + + +``` + +**Responsive Breakpoints:** +- Desktop (md: 768px+): Two columns side by side +- Mobile (< 768px): Single column, sidebar stacked on top + +**Color Palette:** +- Primary Blue: `#2563eb` (text-blue-600, bg-blue-600) +- Background: `#ffffff` (bg-white) +- Sidebar Background: `#eff6ff` (bg-blue-50) +- Text: `#1f2937` (text-gray-800) +- Secondary Text: `#6b7280` (text-gray-600) + +**Typography Scale:** +- Name (h1): 2rem (text-3xl), font-bold +- Section Headers (h2): 1rem (text-base), font-semibold +- Body Text: 0.875rem (text-sm), font-normal + +**Testing Checklist:** +- [ ] Component renders without errors +- [ ] Two-column layout displays correctly on desktop +- [ ] Single column layout on mobile (< 768px) +- [ ] A4 dimensions maintained (210mm × 297mm) +- [ ] Margins are 24px (1.5rem) +- [ ] White background applied +- [ ] Blue color scheme visible +- [ ] Inter font loaded and applied +- [ ] Print preview shows correct styling +- [ ] `.no-print` class works in print mode + +### References + +- [Source: docs/architecture.md#Project-Structure] +- [Source: docs/architecture.md#Novel-Pattern-WYSIWYG-PDF-Export] +- [Source: docs/architecture.md#Consistency-Rules] +- [Source: docs/sprint-artifacts/tech-spec-epic-2.md#AC2-Two-Column-Layout] +- [Source: docs/sprint-artifacts/tech-spec-epic-2.md#Detailed-Design] +- [Source: docs/epics.md#Story-2.2-Create-Resume-Preview-Container-Component] + +## Dev Agent Record + +### Context Reference + +- docs/sprint-artifacts/2-2-create-resume-preview-container-component.context.xml + +### Agent Model Used + + + +### Debug Log References + + + +### Completion Notes List + + + +### File List + + + +--- + +**Change Log:** +- 2025-11-30: Story drafted by SM agent (mahdi) diff --git a/docs/sprint-artifacts/2-3-create-resume-header-main-content-components.context.xml b/docs/sprint-artifacts/2-3-create-resume-header-main-content-components.context.xml new file mode 100644 index 0000000..7d56e17 --- /dev/null +++ b/docs/sprint-artifacts/2-3-create-resume-header-main-content-components.context.xml @@ -0,0 +1,131 @@ + + + 2 + 2.3 + Create Resume Header & Main Content Components + ready-for-dev + 2025-11-30 + BMAD Story Context Workflow + docs/sprint-artifacts/2-3-create-resume-header-main-content-components.md + + + + user + to see my name, title, summary, and work experience prominently + recruiters see the most important information first + + - Create ResumeHeader component + - Create ResumeSummary component + - Create ResumeExperience component + - Integrate components into ResumePreview + - Test components rendering + + + + + Header shows full name in large bold text (2rem, font-bold) + Job title appears below name (1.25rem, text-gray-600) + Blue accent line or background element is present + Summary shows "Profile" or "Summary" section header + Professional summary paragraph is displayed + Line height is 1.6 for readability + Experience shows for each job: position title (bold), company name, date range (formatted: "Jan 2022 - Present"), bullet points for highlights (• character) + Jobs are sorted by date (most recent first) + "Present" is shown for current jobs (no endDate) + + + + + + docs/architecture.md + Resume Export Feature - Architecture Document +
Data Architecture
+ WorkExperience interface: company, position, startDate (YYYY-MM), endDate (optional), highlights (string[]) +
+ + docs/sprint-artifacts/tech-spec-epic-2.md + Epic Technical Specification: Resume Preview Page +
AC5: Header Section, AC10: Summary Section, AC11: Experience Section
+ Header: Name in 2rem bold, job title 1.25rem gray, blue accent line. Summary: Section header, paragraph with line-height 1.6. Experience: Position, company, date range, bullet highlights. +
+
+ + + app/components/resume/ResumePreview.vue + component + ResumePreview + Parent container where these components will be integrated + + + app/composables/useResumeData.ts + composable + useResumeData, formatDate + Provides data and date formatting helper + + + app/types/resume.ts + types + WorkExperience, ResumeBasics + TypeScript interfaces for props + + + + + + + + +
+ + + - Header: text-3xl font-bold for name, text-xl text-gray-600 for title + - Blue accent: border-b-4 border-blue-600 + - Summary: text-base font-semibold for header, leading-relaxed (1.6) for paragraph + - Experience: Sort by startDate descending, format dates with formatDate() helper + - Bullet character: • (U+2022) + - File locations: app/components/resume/ResumeHeader.vue, ResumeSummary.vue, ResumeExperience.vue + - Props pattern: Accept specific data fields, not entire resume object + + + + + ResumeHeader Props + Vue component props + interface Props { name: string; label: string } + app/components/resume/ResumeHeader.vue + + + ResumeSummary Props + Vue component props + interface Props { summary: string } + app/components/resume/ResumeSummary.vue + + + ResumeExperience Props + Vue component props + interface Props { work: WorkExperience[] } + app/components/resume/ResumeExperience.vue + + + formatDate + helper function + formatDate(date: string, locale?: string): string + app/composables/useResumeData.ts + + + + + Vue component testing with Vitest. Test props, rendering, and date formatting. + app/components/**/*.spec.ts + + Mount ResumeHeader with sample data, verify name displays with correct styling + Verify job title displays below name + Check for blue border element + Mount ResumeSummary, verify paragraph renders + Check computed line-height is 1.6 + Mount ResumeExperience with multiple jobs, verify all fields display + Test job sorting by date + Test with job missing endDate, verify "Present" displays + + +
diff --git a/docs/sprint-artifacts/2-3-create-resume-header-main-content-components.md b/docs/sprint-artifacts/2-3-create-resume-header-main-content-components.md new file mode 100644 index 0000000..14b7e52 --- /dev/null +++ b/docs/sprint-artifacts/2-3-create-resume-header-main-content-components.md @@ -0,0 +1,257 @@ +# Story 2.3: Create Resume Header & Main Content Components + +Status: ready-for-dev + +## Story + +As a user, +I want to see my name, title, summary, and work experience prominently, +so that recruiters see the most important information first. + +## Acceptance Criteria + +### ResumeHeader.vue +1. **AC1:** Given the header component renders, when it displays, then it shows full name in large bold text (2rem, font-bold) +2. **AC2:** Job title appears below name (1.25rem, text-gray-600) +3. **AC3:** Blue accent line or background element is present + +### ResumeSummary.vue +4. **AC4:** Given the summary component renders, when it displays, then it shows "Profile" or "Summary" section header +5. **AC5:** Professional summary paragraph is displayed +6. **AC6:** Line height is 1.6 for readability + +### ResumeExperience.vue +7. **AC7:** Given the experience component renders, when it displays, then it shows for each job: position title (bold), company name, date range (formatted: "Jan 2022 - Present"), bullet points for highlights (• character) +8. **AC8:** Jobs are sorted by date (most recent first) +9. **AC9:** "Present" is shown for current jobs (no endDate) + +## Tasks / Subtasks + +- [ ] Create ResumeHeader component (AC: #1-#3) + - [ ] Create `app/components/resume/ResumeHeader.vue` + - [ ] Accept props: `name` (string), `label` (string) + - [ ] Display name with `text-3xl font-bold` (2rem) + - [ ] Display job title with `text-xl text-gray-600` (1.25rem) + - [ ] Add blue accent line: `border-b-4 border-blue-600` + +- [ ] Create ResumeSummary component (AC: #4-#6) + - [ ] Create `app/components/resume/ResumeSummary.vue` + - [ ] Accept props: `summary` (string) + - [ ] Add section header "Profile" with `text-base font-semibold` + - [ ] Display summary paragraph with `leading-relaxed` (line-height: 1.6) + - [ ] Use `text-sm text-gray-800` + +- [ ] Create ResumeExperience component (AC: #7-#9) + - [ ] Create `app/components/resume/ResumeExperience.vue` + - [ ] Accept props: `work` (WorkExperience[]) + - [ ] Add section header "Experience" with `text-base font-semibold` + - [ ] Sort jobs by startDate (most recent first) + - [ ] For each job, display: + - Position title: `font-semibold text-gray-900` + - Company name: `text-gray-700` + - Date range: Use `formatDate()` helper from composable + - Highlights: `