diff --git a/orchestrator/package-lock.json b/orchestrator/package-lock.json index 195831c..7f7c5bf 100644 --- a/orchestrator/package-lock.json +++ b/orchestrator/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@hookform/resolvers": "^5.2.2", + "@paralleldrive/cuid2": "^3.0.6", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.2", @@ -1480,6 +1481,17 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1518,6 +1530,19 @@ "node": ">= 8" } }, + "node_modules/@paralleldrive/cuid2": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-3.0.6.tgz", + "integrity": "sha512-ujtxTTvr4fwPrzuQT7o6VLKs5BzdWetR9+/zRQ0SyK9hVIwZQllEccxgcHYXN6I3Z429y1yg3F6+uiVxMDPrLQ==", + "dependencies": { + "@noble/hashes": "^2.0.1", + "bignumber.js": "^9.3.1", + "error-causes": "^3.0.2" + }, + "bin": { + "cuid2": "bin/cuid2.js" + } + }, "node_modules/@petamoriken/float16": { "version": "3.9.3", "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.3.tgz", @@ -3834,6 +3859,14 @@ "prebuild-install": "^7.1.1" } }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -4763,6 +4796,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/error-causes": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/error-causes/-/error-causes-3.0.2.tgz", + "integrity": "sha512-i0B8zq1dHL6mM85FGoxaJnVtx6LD5nL2v0hlpGdntg5FOSyzQ46c9lmz5qx0xRS2+PWHGOHcYxGIBC5Le2dRMw==" + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", diff --git a/orchestrator/package.json b/orchestrator/package.json index 62d472a..1510a6a 100644 --- a/orchestrator/package.json +++ b/orchestrator/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@hookform/resolvers": "^5.2.2", + "@paralleldrive/cuid2": "^3.0.6", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.2", diff --git a/orchestrator/src/server/services/openrouter.ts b/orchestrator/src/server/services/openrouter.ts index e438728..cb52fea 100644 --- a/orchestrator/src/server/services/openrouter.ts +++ b/orchestrator/src/server/services/openrouter.ts @@ -75,6 +75,7 @@ export async function callOpenRouter( body: JSON.stringify({ model, messages, + stream: false, response_format: { type: 'json_schema', json_schema: { @@ -83,6 +84,7 @@ export async function callOpenRouter( schema: jsonSchema.schema, }, }, + plugins: [{ id: 'response-healing' }], }), }); diff --git a/orchestrator/src/server/services/pdf-skills-validation.test.ts b/orchestrator/src/server/services/pdf-skills-validation.test.ts index d106ea1..6ca353e 100644 --- a/orchestrator/src/server/services/pdf-skills-validation.test.ts +++ b/orchestrator/src/server/services/pdf-skills-validation.test.ts @@ -128,7 +128,7 @@ describe('PDF Service Skills Validation', () => { }); it('should sanitize base resume even if no skills are tailored', async () => { - // Mock profile has an invalid skill (missing visible/description in the raw json implied, + // Mock profile has an invalid skill (missing visible/description in the raw json implied, // though our mock above has them. Let's make a truly invalid one locally) const invalidProfile = { ...mockProfile, @@ -157,4 +157,101 @@ describe('PDF Service Skills Validation', () => { expect(item.description).toBe(''); expect(item.id).toBeDefined(); }); + + it('should generate CUID2-compatible IDs for skills without IDs', async () => { + // Profile with skills missing IDs (common when AI generates them) + const profileWithoutIds = { + ...mockProfile, + sections: { + ...mockProfile.sections, + skills: { + items: [ + { name: 'Skill 1', keywords: ['a'] }, + { name: 'Skill 2', keywords: ['b'] }, + { name: 'Skill 3', keywords: ['c'] } + ] + } + } + }; + mocks.readFile.mockResolvedValueOnce(JSON.stringify(profileWithoutIds)); + + await generatePdf('job-cuid2-test', {}, 'Job Desc', 'dummy.json'); + + expect(mocks.writeFile).toHaveBeenCalled(); + const callArgs = mocks.writeFile.mock.calls[0]; + const savedResumeJson = JSON.parse(callArgs[1] as string); + + const skillItems = savedResumeJson.sections.skills.items; + + // All skills should have IDs + skillItems.forEach((skill: any, index: number) => { + expect(skill.id).toBeDefined(); + expect(typeof skill.id).toBe('string'); + expect(skill.id.length).toBeGreaterThanOrEqual(20); + + // CUID2 format: starts with a letter, lowercase alphanumeric + expect(skill.id).toMatch(/^[a-z][a-z0-9]+$/); + }); + + // IDs should be unique + const ids = skillItems.map((s: any) => s.id); + const uniqueIds = new Set(ids); + expect(uniqueIds.size).toBe(ids.length); + }); + + it('should NOT generate IDs like "skill-0" which are invalid CUID2', async () => { + const profileWithoutIds = { + ...mockProfile, + sections: { + ...mockProfile.sections, + skills: { + items: [ + { name: 'Skill Without ID', keywords: ['test'] } + ] + } + } + }; + mocks.readFile.mockResolvedValueOnce(JSON.stringify(profileWithoutIds)); + + await generatePdf('job-no-skill-prefix', {}, 'Job Desc', 'dummy.json'); + + expect(mocks.writeFile).toHaveBeenCalled(); + const callArgs = mocks.writeFile.mock.calls[0]; + const savedResumeJson = JSON.parse(callArgs[1] as string); + + const skill = savedResumeJson.sections.skills.items[0]; + + // ID should NOT be in the old invalid format + expect(skill.id).not.toMatch(/^skill-\d+$/); + + // Should be valid CUID2 format + expect(skill.id).toMatch(/^[a-z][a-z0-9]+$/); + }); + + it('should preserve existing valid IDs and not regenerate them', async () => { + const validCuid2Id = 'ck9w4ygzq0000xmn5h0jt7l5c'; + const profileWithValidId = { + ...mockProfile, + sections: { + ...mockProfile.sections, + skills: { + items: [ + { id: validCuid2Id, name: 'Skill With Valid ID', keywords: ['test'], visible: true, description: '', level: 1 } + ] + } + } + }; + mocks.readFile.mockResolvedValueOnce(JSON.stringify(profileWithValidId)); + + await generatePdf('job-preserve-id', {}, 'Job Desc', 'dummy.json'); + + expect(mocks.writeFile).toHaveBeenCalled(); + const callArgs = mocks.writeFile.mock.calls[0]; + const savedResumeJson = JSON.parse(callArgs[1] as string); + + const skill = savedResumeJson.sections.skills.items[0]; + + // Should preserve the original valid ID + expect(skill.id).toBe(validCuid2Id); + }); }); diff --git a/orchestrator/src/server/services/pdf.ts b/orchestrator/src/server/services/pdf.ts index 7fafa77..2037672 100644 --- a/orchestrator/src/server/services/pdf.ts +++ b/orchestrator/src/server/services/pdf.ts @@ -8,6 +8,7 @@ import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; import { readFile, writeFile, mkdir, access, unlink } from 'fs/promises'; import { existsSync } from 'fs'; +import { createId } from '@paralleldrive/cuid2'; import { getSetting } from '../repositories/settings.js'; import { pickProjectIdsForJob } from './projectSelection.js'; @@ -67,9 +68,9 @@ export async function generatePdf( // Sanitize skills: Ensure all skills have required schema fields (visible, description, id, level, keywords) // This fixes issues where the base JSON uses a shorthand format (missing required fields) if (baseResume.sections?.skills?.items && Array.isArray(baseResume.sections.skills.items)) { - baseResume.sections.skills.items = baseResume.sections.skills.items.map((skill: any, index: number) => ({ + baseResume.sections.skills.items = baseResume.sections.skills.items.map((skill: any) => ({ ...skill, - id: skill.id || `skill-${index}`, + id: skill.id || createId(), visible: skill.visible ?? true, // Zod schema requires string, default to empty string if missing description: skill.description ?? '', @@ -107,12 +108,12 @@ export async function generatePdf( if (newSkills && baseResume.sections?.skills) { // Ensure each skill item has required schema fields const existingSkills = baseResume.sections.skills.items || []; - const skillsWithSchema = newSkills.map((newSkill: any, index: number) => { + const skillsWithSchema = newSkills.map((newSkill: any) => { // Try to find matching existing skill to preserve id and other fields const existing = existingSkills.find((s: any) => s.name === newSkill.name); return { - id: newSkill.id || existing?.id || `skill-${index}`, + id: newSkill.id || existing?.id || createId(), visible: newSkill.visible !== undefined ? newSkill.visible : (existing?.visible ?? true), name: newSkill.name || existing?.name || '', description: newSkill.description !== undefined ? newSkill.description : (existing?.description || ''), diff --git a/orchestrator/src/shared/rxresume-schema.test.ts b/orchestrator/src/shared/rxresume-schema.test.ts new file mode 100644 index 0000000..450a994 --- /dev/null +++ b/orchestrator/src/shared/rxresume-schema.test.ts @@ -0,0 +1,152 @@ +import { describe, it, expect } from 'vitest'; +import { createId } from '@paralleldrive/cuid2'; +import { idSchema, skillSchema, resumeDataSchema } from './rxresume-schema.js'; + +describe('RxResume Schema Validation', () => { + describe('idSchema (CUID2)', () => { + it('should accept valid CUID2 IDs generated by the library', () => { + // Generate real CUID2 IDs using the official library + const validIds = [ + createId(), + createId(), + createId(), + ]; + + validIds.forEach(id => { + const result = idSchema.safeParse(id); + expect(result.success, `ID "${id}" should be valid`).toBe(true); + }); + }); + + it('should reject invalid IDs like "skill-0"', () => { + const invalidIds = [ + 'skill-0', // contains hyphen + 'skill-1', // contains hyphen + 'skill-123', // contains hyphen + 'item_1', // contains underscore + 'ABC123', // uppercase letters + '', // empty + ]; + + invalidIds.forEach(id => { + const result = idSchema.safeParse(id); + expect(result.success, `ID "${id}" should be invalid`).toBe(false); + }); + }); + }); + + describe('skillSchema', () => { + it('should accept valid skill with CUID2 ID', () => { + const validSkill = { + id: createId(), + visible: true, + name: 'JavaScript', + description: '', + level: 3, + keywords: ['ES6', 'TypeScript'], + }; + + const result = skillSchema.safeParse(validSkill); + expect(result.success).toBe(true); + }); + + it('should reject skill with invalid ID format', () => { + const invalidSkill = { + id: 'skill-0', // Invalid CUID2 + visible: true, + name: 'JavaScript', + description: '', + level: 3, + keywords: ['ES6'], + }; + + const result = skillSchema.safeParse(invalidSkill); + expect(result.success).toBe(false); + if (!result.success) { + expect(result.error.issues[0].path).toContain('id'); + expect(result.error.issues[0].message).toContain('cuid2'); + } + }); + }); + + describe('resumeDataSchema', () => { + it('should reject resume with invalid skill IDs', () => { + const resumeWithInvalidIds = { + basics: { + name: 'John Doe', + headline: 'Developer', + email: 'john@example.com', + phone: '', + location: '', + url: { label: '', href: '' }, + customFields: [], + picture: { + url: '', + size: 64, + aspectRatio: 1, + borderRadius: 0, + effects: { hidden: false, border: false, grayscale: false }, + }, + }, + sections: { + summary: { id: 'summary', name: 'Summary', columns: 1, separateLinks: true, visible: true, content: '' }, + skills: { + id: 'skills', + name: 'Skills', + columns: 1, + separateLinks: true, + visible: true, + items: [ + { + id: 'skill-0', // Invalid! + visible: true, + name: 'JavaScript', + description: '', + level: 1, + keywords: [], + }, + ], + }, + // Minimal required sections + awards: { id: 'awards', name: 'Awards', columns: 1, separateLinks: true, visible: true, items: [] }, + certifications: { id: 'certifications', name: 'Certifications', columns: 1, separateLinks: true, visible: true, items: [] }, + education: { id: 'education', name: 'Education', columns: 1, separateLinks: true, visible: true, items: [] }, + experience: { id: 'experience', name: 'Experience', columns: 1, separateLinks: true, visible: true, items: [] }, + volunteer: { id: 'volunteer', name: 'Volunteer', columns: 1, separateLinks: true, visible: true, items: [] }, + interests: { id: 'interests', name: 'Interests', columns: 1, separateLinks: true, visible: true, items: [] }, + languages: { id: 'languages', name: 'Languages', columns: 1, separateLinks: true, visible: true, items: [] }, + profiles: { id: 'profiles', name: 'Profiles', columns: 1, separateLinks: true, visible: true, items: [] }, + projects: { id: 'projects', name: 'Projects', columns: 1, separateLinks: true, visible: true, items: [] }, + publications: { id: 'publications', name: 'Publications', columns: 1, separateLinks: true, visible: true, items: [] }, + references: { id: 'references', name: 'References', columns: 1, separateLinks: true, visible: true, items: [] }, + custom: {}, + }, + metadata: { + template: 'rhyhorn', + layout: [[['summary'], ['skills']]], + css: { value: '', visible: false }, + page: { margin: 18, format: 'a4', options: { breakLine: true, pageNumbers: true } }, + theme: { background: '#ffffff', text: '#000000', primary: '#dc2626' }, + typography: { + font: { family: 'IBM Plex Serif', subset: 'latin', variants: ['regular'], size: 14 }, + lineHeight: 1.5, + hideIcons: false, + underlineLinks: true, + }, + notes: '', + }, + }; + + const result = resumeDataSchema.safeParse(resumeWithInvalidIds); + expect(result.success).toBe(false); + + if (!result.success) { + // Should have error about the skill ID + const idError = result.error.issues.find( + issue => issue.path.join('.').includes('skills.items') && issue.path.includes('id') + ); + expect(idError).toBeDefined(); + } + }); + }); +}); diff --git a/orchestrator/src/shared/rxresume-schema.ts b/orchestrator/src/shared/rxresume-schema.ts index 565ee21..b487960 100644 --- a/orchestrator/src/shared/rxresume-schema.ts +++ b/orchestrator/src/shared/rxresume-schema.ts @@ -10,7 +10,8 @@ export type FilterKeys = { export const idSchema = z .string() - .describe("Unique identifier for the item"); + .cuid2() + .describe("Unique identifier for the item (CUID2 format)"); export const itemSchema = z.object({ id: idSchema, diff --git a/resume-generator/generate_summary.py b/resume-generator/generate_summary.py index 4879476..a6c7ea0 100644 --- a/resume-generator/generate_summary.py +++ b/resume-generator/generate_summary.py @@ -73,6 +73,8 @@ def _call_openrouter(prompt: str, model: str, api_key: str) -> str: payload = { "model": model, "messages": [{"role": "user", "content": prompt}], + "stream": False, + "plugins": [{"id": "response-healing"}], } response = requests.post(url, headers=headers, json=payload) diff --git a/resume-generator/rxresume_automation.py b/resume-generator/rxresume_automation.py index f7f931e..c86c32e 100644 --- a/resume-generator/rxresume_automation.py +++ b/resume-generator/rxresume_automation.py @@ -38,9 +38,72 @@ def login(page): def import_resume(page, json_path: Path): """Import a resume JSON file.""" + # Log the JSON file size for debugging + try: + import json + with open(json_path, 'r') as f: + data = json.load(f) + print(f" 📋 JSON keys: {list(data.keys())}") + if 'basics' in data: + print(f" 📋 Headline: {data['basics'].get('headline', 'N/A')[:50]}...") + except Exception as e: + print(f" ⚠️ Could not read JSON for logging: {e}") + page.click('h4:has-text("Import")') page.set_input_files('input[type="file"]', str(json_path)) page.click('button:has-text("Validate")') + + # Wait for validation to complete - check for either success (Import button) or error + try: + # Wait for the Import button to become visible (validation succeeded) + page.wait_for_selector('button:has-text("Import"):not([disabled])', timeout=10000) + except Exception as e: + # Save debug files to errors folder (accessible outside Docker) + errors_dir = OUTPUT_DIR.parent / "errors" + errors_dir.mkdir(parents=True, exist_ok=True) + + # Take a screenshot for debugging + try: + screenshot_path = errors_dir / f"debug_{json_path.stem}.png" + page.screenshot(path=str(screenshot_path)) + print(f" 📸 Debug screenshot saved: {screenshot_path}") + except Exception as screenshot_err: + print(f" ⚠️ Could not save screenshot: {screenshot_err}") + + # Copy the failed JSON to errors folder for inspection + try: + import shutil + failed_json_path = errors_dir / f"{json_path.stem}.json" + shutil.copy(str(json_path), str(failed_json_path)) + print(f" 📋 Failed JSON saved: {failed_json_path}") + except Exception as copy_err: + print(f" ⚠️ Could not save failed JSON: {copy_err}") + + # Check for validation error messages in the dialog + error_selectors = [ + 'text=/error|invalid|failed/i', + '[class*="error"]', + '[class*="destructive"]', + '.text-red-500', + '.text-destructive', + '[role="alert"]', + ] + for selector in error_selectors: + error_element = page.query_selector(selector) + if error_element: + error_text = error_element.inner_text().strip() + if error_text: + print(f" ❌ RXResume validation error: {error_text}") + raise RuntimeError(f"RXResume validation failed: {error_text}") + + # Log what's visible in the dialog for debugging + dialog = page.query_selector('[role="dialog"]') + if dialog: + dialog_text = dialog.inner_text()[:500] + print(f" 📋 Dialog content: {dialog_text}") + + raise RuntimeError(f"Import button not found after validation (timeout): {e}") + page.click('button:has-text("Import")') diff --git a/resume-generator/temp_resume_b551b26e-7cf0-4bc5-be69-36d8e813f5b2.json b/resume-generator/temp_resume_b551b26e-7cf0-4bc5-be69-36d8e813f5b2.json deleted file mode 100644 index 681171e..0000000 --- a/resume-generator/temp_resume_b551b26e-7cf0-4bc5-be69-36d8e813f5b2.json +++ /dev/null @@ -1,661 +0,0 @@ -{ - "basics": { - "name": "Shaheer Sarfaraz", - "headline": "Frontend Software Engineer (React/TypeScript) · Autodesk Intern · Open Source & Product Work", - "email": "shaheer30sarfaraz@gmail.com", - "phone": "+44 7359 501592", - "location": "Blackpool, United Kingdom", - "url": { - "label": "https://dakheera47.com/", - "href": "https://dakheera47.com/" - }, - "customFields": [], - "picture": { - "url": "", - "size": 120, - "aspectRatio": 1, - "borderRadius": 0, - "effects": { - "hidden": false, - "border": false, - "grayscale": false - } - } - }, - "sections": { - "summary": { - "name": "Summary", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "summary", - "content": "" - }, - "awards": { - "name": "Awards", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "awards", - "items": [] - }, - "certifications": { - "name": "Certifications", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "certifications", - "items": [] - }, - "education": { - "name": "Education", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "education", - "items": [ - { - "id": "yo3p200zo45c6cdqc6a2vtt3", - "visible": true, - "institution": "University of Lancashire", - "studyType": "BSc (Hons) Computer Science", - "area": "Preston, United Kingdom", - "score": "1st Class", - "date": "September 2022 to June 2026", - "summary": "

Relevant Modules: Web Applications, Algorithms & Data Structures, Game Development, Databases, Software Engineering (Agile group project)

", - "url": { - "label": "", - "href": "https://www.lancashire.ac.uk/undergraduate/courses/computer-science-bsc" - } - }, - { - "id": "ei2fvjokusg3cfmdyolmgcoz", - "visible": false, - "institution": " ", - "studyType": "", - "area": "A Levels", - "score": "", - "date": "", - "summary": "
  • Maths: A

  • Computer Science: B

  • Physics: C

  • Chemistry: E

", - "url": { - "label": "", - "href": "" - } - }, - { - "id": "pm4r5hngvv1w4mc79o22irfx", - "visible": false, - "institution": " ", - "studyType": "", - "area": "GCSEs", - "score": "", - "date": "", - "summary": "
  1. English: A*

  2. Computer Science: A*

  3. Urdu: A

  4. Islamiat: A

  5. Pakistan Studies: A

  6. Biology: A

  7. Chemistry: A

  8. Physics: A

  9. Maths: A

", - "url": { - "label": "", - "href": "" - } - } - ] - }, - "experience": { - "name": "Experience", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "experience", - "items": [ - { - "id": "ng9ui2azk7w4y8oyu8kazqeb", - "visible": true, - "company": "Autodesk", - "position": "Software Engineering Intern", - "location": "Hybrid (Sheffield Based)", - "date": "July 2024 - June 2025", - "summary": "
  • Implemented front-end features and fixes in the Autodesk Construction Cloud Model Coordination app, working in a ~10-year-old React/JavaScript/TypeScript codebase (7k+ commits) using Webpack module federation and Autodesk’s Exoskeleton dev environment

  • Improved reliability of the Cypress end-to-end test suite by diagnosing flaky tests, adding new E2E coverage, and participating in focused “test fest” events ahead of major feature releases

  • Collaborated with cross-functional teams (like the Design System, platform teams) by raising well-scoped bugs, augmenting existing tickets with reproduction steps and context, and aligning on shared component and API changes

  • Helped strengthen team processes by running weekly stand-ups and retrospectives, organising a ticket-scoping meeting, and participating in technical reviews & ADR discussions (e.g. standardising error handling and planning clash data streaming)

", - "url": { - "label": "", - "href": "" - } - }, - { - "id": "lhw25d7gf32wgdfpsktf6e0x", - "visible": true, - "company": "Mirage", - "position": "Co-Founder & Lead Developer", - "location": "", - "date": "December 2019 to Present", - "summary": "
  • Delivered 10+ production websites and webapps for small and medium size clients (e.g. Indus Marine Services, Mumtaz Urdu), from initial scoping to deployment and handover

  • Built with modern web stacks (Next.js, Node/Express, Tailwind, Strapi, WordPress/Elementor where appropriate), setting up CI/CD and hosting

  • Led a small team of four developers, handling code reviews, task breakdown, and client communication

", - "url": { - "label": "", - "href": "https://promirage.com/" - } - }, - { - "id": "k6zxqunkb225hbjso3c3vykk", - "visible": true, - "company": "University of Lancashire", - "position": "Computing Student Mentor", - "location": "Preston, UK", - "date": "July 2023 - July 2024", - "summary": "
  • Academic Support and Leadership: Provided academic guidance to over 10 first-year students once a week, significantly enhancing their understanding and skills in key subjects like programming and web development.

  • Collaborative Learning Environment: Actively fostered a collaborative and supportive learning environment for a group of 10 students. This role also honed my leadership and communication skills, facilitating better academic outcomes for mentees.

", - "url": { - "label": "", - "href": "" - } - }, - { - "id": "a1bg5d8gp8sulf91xzdcsiaq", - "visible": true, - "company": "Research and Knowledge Exchange Institute", - "position": "Undergraduate Research Intern (HCI & EdTech)", - "location": "", - "date": "Summer 2024", - "summary": "
  • Built a mouse “torch-reveal” web app (Astro) to approximate eye-tracking; ran on-campus studies with Revoe Learning Academy pupils—1 eye-tracked, 9 using my app.

  • Logged cursor paths, dwell time, and reveal order; delivered setup notes for staff to run sessions independently.

  • Developed a Questionnaire Randomiser (Next.js): selectable response metrics (smileys / numbers / stars), configurable randomisation strategies, and ZIP export of per-student PDFs ready for print.

  • Extras: lightweight analytics for comparison with the eye-tracking baseline; optional CSV/JSON data export.

", - "url": { - "label": "", - "href": "" - } - }, - { - "id": "tx32suzrg2bs5eumcbjei4ns", - "visible": false, - "company": "University of Lancashire", - "position": "Student Ambassador", - "location": "Preston, UK", - "date": "July 2023 - Present", - "summary": "
  • Diverse Role Engagement: Actively engaged in various tasks, from guiding tours to assisting on open days, demonstrating adaptability and organizational skills.

  • Campus Culture Promotion: Contributed to enhancing the university’s inclusive campus atmosphere, showcasing the university's vibrant community to prospective students.

", - "url": { - "label": "", - "href": "" - } - } - ] - }, - "volunteer": { - "name": "Volunteering", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "volunteer", - "items": [] - }, - "interests": { - "name": "Interests", - "columns": 1, - "separateLinks": true, - "visible": false, - "id": "interests", - "items": [] - }, - "languages": { - "name": "Languages", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "languages", - "items": [] - }, - "profiles": { - "name": "Profiles", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "profiles", - "items": [ - { - "id": "ukl0uecvzkgm27mlye0wazlb", - "visible": true, - "network": "GitHub", - "username": "DaKheera47", - "icon": "github", - "url": { - "label": "", - "href": "https://github.com/DaKheera47" - } - }, - { - "id": "cnbk5f0aeqvhx69ebk7hktwd", - "visible": true, - "network": "LinkedIn", - "username": "ssarfaraz30", - "icon": "linkedin", - "url": { - "label": "", - "href": "https://www.linkedin.com/in/ssarfaraz30/" - } - }, - { - "id": "linnyxv78zdep1xwirpa2ia1", - "visible": true, - "network": "Hashnode", - "username": "DaKheera47", - "icon": "hashnode", - "url": { - "label": "", - "href": "https://dakheera47.hashnode.dev/" - } - } - ] - }, - "projects": { - "name": "Projects", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "projects", - "items": [ - { - "id": "yw843emozcth8s1ubi1ubvlf", - "visible": false, - "name": "Atoro", - "description": "Lead Developer", - "date": "January 2023", - "summary": "
  1. Next.js Implementation for Enhanced SEO: Utilized Next.js to optimize the website for search engines, significantly improving its online visibility and user engagement.

  2. Strapi Backend Integration: Streamlined content management by implementing a Strapi backend, enhancing the efficiency and scalability of the website's content updates.

  3. Responsive Design with Tailwind CSS: Employed Tailwind CSS for a utility-first approach, ensuring the website's responsiveness and seamless user experience across various devices.

  4. Continuous Deployment Pipeline Establishment: Developed a continuous deployment pipeline, ensuring real-time updates and maintaining high performance and reliability of the website.

  5. Optimized Web Performance: Focused on optimizing web performance by efficiently loading images and managing JavaScript bundles, leading to a faster and more efficient user experience.

", - "keywords": [], - "url": { - "label": "", - "href": "https://atoro.promirage.com" - } - }, - { - "id": "ncxgdjjky54gh59iz2t1xi1v", - "visible": false, - "name": "Stellar Consultancy", - "description": "Lead Developer", - "date": "April 2023", - "summary": "
  1. WordPress and Elementor Integration: Expertly utilized WordPress with Elementor to build a robust content management system, enhancing the website's scalability and user interaction capabilities.

  2. Client Engagement and Trust Building: Implemented features to showcase client testimonials, effectively building trust and displaying the success of previous project engagements.

  3. Intuitive Design and User Engagement: Focused on intuitive page design and structuring, streamlining site maintenance and content updates, thereby enhancing user engagement.

  4. Effective Call-to-Actions: Crafted clear call-to-actions and provided essential contact information, significantly improving user interaction and conversion rates.

  5. Portfolio Display for Business Showcase: Presented past work and services offered through a comprehensive portfolio display, allowing visitors to assess the quality and impact of Stellar Consultancy's services.

", - "keywords": [], - "url": { - "label": "", - "href": "https://stellarconsultancy.ca" - } - }, - { - "id": "tcecguinuctb8mu2xqrn97m8", - "visible": true, - "name": "Mumtaz Urdu", - "description": "Developer", - "date": "July 2022", - "summary": "
  1. Server-Rendered Web Application Development: Created the Mumtaz Urdu platform with Next.js to optimize server-side rendering for enhanced SEO and performance.

  2. UI Development with Tailwind CSS: Implemented utility-first Tailwind CSS, ensuring rapid, responsive design for a seamless user interface.

  3. Scalable Storage Solution: Integrated scalable Amazon S3 storage, supporting the application's growth and robust data management.

  4. Progressive Web App Implementation: Developed PWA features for Mumtaz Urdu, offering users native-like mobile access and increased engagement.

  5. High Traffic Data Management: Engineered Mumtaz Urdu's backend with Next.js and MongoDB, enabling the handling and efficient processing of vast amounts of user data for thousands of monthly users.

  6. Test-Driven Development: Embraced TDD practices to ensure reliable and high-quality code, facilitating regular testing throughout the development process for continuous improvement.

", - "keywords": [], - "url": { - "label": "", - "href": "https://www.mumtazurdu.com/" - } - }, - { - "id": "to47h749kaj6t02j3f9kprxq", - "visible": false, - "name": "PyScreeze", - "description": "Open Source Contribution", - "date": "January 2022", - "summary": "
  1. Innovative Feature Implementation: Implemented the locateCenterOnScreenNear function for PyScreeze, enhancing the library's functionality by enabling precise image location near a specified point on the screen.

  2. Open Source Contribution: Marked my debut in open-source contributions with this significant addition to PyScreeze, showcasing my initiative and ability to contribute effectively to community-driven projects.

  3. Collaborative Development and Recognition: Collaborated with the project's maintainer, asweigart, to refine and integrate the function into the main codebase, receiving recognition for this valuable contribution to the project.

", - "keywords": [], - "url": { - "label": "", - "href": "https://github.com/asweigart/pyscreeze/pull/79" - } - }, - { - "id": "gt7yq82ulor5hmmutdhuvfo1", - "visible": false, - "name": "Threegency", - "description": "Lead Developer", - "date": "February 2023", - "summary": "
  • Framework: Utilized Next.js to build a server-rendered React website, enhancing SEO and ensuring optimal performance.

  • Styling: Employed Tailwind CSS for utility-first styling, facilitating rapid UI development.

  • Content Management: Leveraged Strapi as a CMS, enabling streamlined content updates and administration.

  • Data Handling: Utilized GraphQL for data handling, ensuring efficient and flexible data retrieval.

", - "keywords": [], - "url": { - "label": "", - "href": "https://www.threegency.com" - } - }, - { - "id": "c8fcu3nz541a4d5zcurx6b8c", - "visible": false, - "name": "AutoClass", - "description": "GUI Automation", - "date": "November 2021", - "summary": "
  • Framework: Written in Python, leveraging the versatility and ease-of-use of the language.

  • Automation Library: Utilized PyAutoGUI for automating user interactions, enhancing the utility of the application.

  • Iterative Improvement: Progressively refined over a year, demonstrating a commitment to robustness and reliability.

  • Project Purpose: Developed to automate the process of joining Zoom classes, alleviating the repetitive morning routine.

", - "keywords": [], - "url": { - "label": "", - "href": "https://github.com/DaKheera47/autoclass" - } - }, - { - "id": "rv23bgibq6bye6rujmcx1ygc", - "visible": false, - "name": "Meet Link Generator", - "description": "GUI Automation", - "date": "January 2022", - "summary": "
  • Functionality: Generates Google Meet links with specific words in the URL by brute-forcing the creation of thousands of links until the desired pattern is achieved. Doing so enables creation of Google Meet links with specific codes or phrases.

  • Optimized Automation: The final product uses Python with PyAutoGUI for efficient and rapid creation of new Google Meet links.

  • Speed and Efficiency: Drastically improved performance, finally achieving the link generation time to under 1 second per link, limited only by internet speed.

  • Interface Interaction: Utilizes the Google Meet homepage's features for quicker link generation, avoiding full page refreshes for speed.

", - "keywords": [], - "url": { - "label": "", - "href": "https://github.com/DaKheera47/meet-link-generator" - } - }, - { - "id": "tu98rghbi5c43ogget5mh7ih", - "visible": false, - "name": "UCLan Server-side Web Application Project", - "description": "", - "date": "UCLan Year 1", - "summary": "
  • Backend Development with PHP and MySQL: Developed the backend for a Student’s Union Shop web application, integrating PHP and MySQL for dynamic data handling and backend database communication.

  • User Authentication and Session Management: Implemented user sign-up and login functionality using PHP sessions, enabling secure and personalized shopping experiences.

  • Dynamic Content Display from Database: Enhanced the application to dynamically display products and offers directly from the database, moving away from static HTML content.

  • Advanced Search and Personalization Features: Integrated advanced product search capabilities and personalized user greetings, improving user interactivity and engagement.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "ov4lkbc1vl169ynfnj91m1lm", - "visible": false, - "name": "Square About", - "description": "", - "date": "UCLan Year 1", - "summary": "
  • Advanced 3D Game Development: Implemented a complex 3D game using TL-Engine, featuring intricate gameplay mechanics and immersive 3D visuals.

  • Dynamic Gameplay Elements: Integrated multiple spheres with varying behaviors, including super-spheres requiring multiple hits, enhancing the game's challenge and engagement levels.

  • Interactive Game Controls: Developed features for speed control and directional change, allowing players to interact dynamically with the game environment.

  • Strategic Game Mechanics: Added a bullet firing mechanism with a limited ammo concept, introducing strategic elements and a scoring system to the gameplay.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "s3r37gdr0oa84a6dp6r5nl58", - "visible": false, - "name": "Car Smash", - "description": "", - "date": "UCLan Year 1", - "summary": "
  1. 3D Car Smash Game Development: Developed a 3D car smash game using TL-Engine, showcasing skills in game engine utilization and 3D gaming.

  2. Collision Detection Mechanics: Implemented advanced collision detection between player's car and enemy vehicles, enhancing gameplay realism.

  3. Dynamic Game States and Camera Views: Integrated multiple game states and camera views, including a chase camera and first-person view, for an immersive gaming experience.

  4. Enhanced Player Interaction: Created a more realistic driving experience with accelerated movement and bounce effects on collisions, and introduced particle systems for visual effects.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "gylzkvl103m9s7ywag4xpdy4", - "visible": false, - "name": "Tweet Filter", - "description": "", - "date": "UCLan Year 1", - "summary": "
  1. Tweet Filtration System: Crafted a C++ program to filter out prohibited words from tweets, showcasing text processing and file handling capabilities.

  2. Advanced Text Manipulation: Enhanced the program to filter varying cases and contexts of banned words, even within larger strings, demonstrating attention to detail in string operations.

  3. Output Generation: Implemented functionality to write filtered tweets to new files, maintaining data integrity and displaying proficiency in file I/O operations.

  4. Algorithm Optimization: Utilized data structures like vectors and implemented mathematical techniques for efficient word frequency analysis and sentiment determination.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "enav754zxhuc9uycbb83s94q", - "visible": false, - "name": "Burger Ordering App", - "description": "", - "date": "UCLan Year 1", - "summary": "
  1. Interactive Console Application: Engineered a C++ console application simulating a burger ordering process, highlighting proficiency in creating user-interactive software.

  2. Complex Logic Implementation: Designed and implemented complex logic for burger size and topping selection, including pricing and order summary features.

  3. Data Handling and User Input: Developed robust credit system and user input validation for an intuitive ordering experience, showcasing attention to detail and user-centric design.

  4. Readable and Maintainable Code: Produced well-documented, maintainable code with clear variable naming and structured formatting, demonstrating best practices in software development.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "hl6jgeswr01tlul3iwoat05d", - "visible": false, - "name": "LinkLander", - "description": "Android Studio, Kotlin", - "date": "December 2023 - Ongoing", - "summary": "
  • Innovative Android Utility: Developed LinkLander, a Kotlin-based Android application that simplifies the process of downloading online content directly to devices.

  • User-Centric Design: Focused on addressing Android system limitations by providing a seamless shortcut for redirecting links to an online video downloading service.

  • Simplicity and Efficiency: Emphasized a user-friendly interface, enhancing the Android experience by streamlining content downloads.

  • Technical Proficiency in Kotlin: Leveraged the capabilities of Kotlin for Android development to create a practical solution for niche digital tasks.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "v4s0ljbiiio198y8l1wl0ym6", - "visible": false, - "name": "AR App Development with AGILE", - "description": "Unity, C#", - "date": "October 2023 - Ongoing", - "summary": "
  • Agile Development in Action: Participated in an Agile team project, developing an AR application for supporting disabled students with a team of five, demonstrating an application of Agile methodologies in a real-world scenario.

  • Mobile AR Application Prototype: Developed a proof-of-concept prototype using Unity and C# for mobile platforms, showcasing technical skills in modern app development environments.

  • Collaborative Software Engineering: Engaged in a collaborative environment, contributing code and ideas, emphasizing teamwork and shared responsibility in software creation.

  • Presentation and Critical Analysis: Delivered a comprehensive presentation and critical report, evaluating the Agile process, product development, and personal learning outcomes.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "fwxrq682hqrj1y76rmziqrbk", - "visible": true, - "name": "Indus Marine Services", - "description": "System Design & Development", - "date": "May 2022 - Ongoing", - "summary": "
  1. Induction System for Marine Services: Designed & developed an induction system for Indus Marine Services in the UAE, streamlining the employee onboarding process with interactive testing and certification issuance.

  2. Admin-Centric Functionality: Devised a back-end system allowing admins to oversee inductee progress, manage documents, and curate customized quizzes as per requirements

  3. Client Engagement Interface: Implemented a user-friendly front-end where inductees receive personalized email prompts, complete quizzes, and obtain certifications, all contributing to a seamless induction experience.

  4. Robust Tech Stack Integration: Utilized a sophisticated stack comprising Node.js, Express, EJS, and Tailwind CSS to build a responsive, scalable, and easily navigable system.

", - "keywords": [], - "url": { - "label": "", - "href": "http://www.ims-auh.com" - } - }, - { - "id": "jdfyaez8vq1b7xfr9rmxmz06", - "visible": false, - "name": "VECTOR AI", - "description": "Website Development", - "date": "February 2024 - February 2024", - "summary": "
  1. Innovative AI Development: As the driving force behind VECTOR's website development, I spearheaded the technical design using Astro, with a cutting-edge stack including React and Tailwind CSS.

  2. Data-Driven Content Strategy: Leveraged Astro content management capabilities to structure and present data, ensuring content is dynamic, easily accessible, and optimized for both performance and scalability.

  3. Astro for Enhanced Performance: Utilized Astro for static site generation, making VECTOR's website performance fast for a pleasant user experience

  4. React for Responsive Interaction: Utilized React’s robust ecosystem to develop interactive elements, ensuring that each module of VECTOR’s platform is engaging and seamless for users across various touchpoints.

", - "keywords": [], - "url": { - "label": "", - "href": "https://vector-ai.co/" - } - }, - { - "id": "qdhmfkqpfql19ohfas1g91ek", - "visible": false, - "name": "UCLan's First Hackathon", - "description": "Hackathon, Team Work", - "date": "February 2024", - "summary": "
  1. Second Place in UCLan Hackathon: Earned second place in UCLan's first hackathon by developing an app to simplify university life. Focused on enhancing the attendance monitoring process for student mentors.

  2. TRPC for End-to-End Type Safety: Utilized TRPC to ensure end-to-end type safety, enhancing the app's reliability and streamlining the development process.

  3. Supabase Backend Integration: Implemented Supabase as a backend solution, providing a robust and scalable database for managing attendance data efficiently.

  4. Amazon SES and OAuth Integration: Integrated Amazon SES for email notifications and OAuth for secure Google login, improving user experience and communication.

", - "keywords": [], - "url": { - "label": "", - "href": "" - } - }, - { - "id": "rw3x7tapntrt877rbl4pnxz7", - "visible": true, - "name": "NASA Space Apps Challenge", - "description": "A 48-hour, global hackathon powered by NASA open data", - "date": "Oct 4–5, 2025", - "summary": "
  1. Full-Stack Integration: Wired up backend services to a responsive frontend, enabling real-time exploration of Kepler/K2/TESS catalogs and smooth model-scoring UX.

  2. Data Harmonization Pipeline: Cleaned, merged, and standardized multi-mission catalogs into a unified schema, unblocking ML teammates and cutting data-prep time by 60%+ during the hack.

  3. Analytics UI & Upload Flow: Built an upload → validate → score workflow and a clear results dashboard so researchers can triage candidates in minutes, not hours.

  4. Delivery Under Pressure: Coordinated a 5-person multidisciplinary team to ship a working web app in 48 hours, with demo-ready reliability for judging.

", - "keywords": [], - "url": { - "label": "", - "href": "https://exploranium.vercel.app/dashboard" - } - }, - { - "id": "i2t6epmx5v7s0d8rqtxsigp3", - "visible": true, - "name": "Strong Statistics", - "description": "Self-hosted strength analytics app using FastAPI and Next.js to visualize Strong app data with full local privacy and active open-source adoption.", - "date": "September 2025 - Present", - "summary": "
  1. Self-Hosted Strength Analytics Platform: Developed strong-statistics, an open-source web app that visualizes detailed workout analytics from the Strong and Hevy fitness app, giving users local control of their training data.

  2. Full-Stack Architecture: Built a modular stack with FastAPI, Next.js, Tailwind CSS, and SQLite, deployed via Docker Compose for seamless self-hosting and persistent local data storage.

  3. Active Open-Source Ecosystem: Published on GitHub with community engagement from global users — external contributors opened feature requests and bug reports, validating real-world adoption and reliability.

  4. Continuous Personal Use & Maintenance: Regularly updated and used in live deployment at lifting.dakheera47.com, tracking hundreds of sets over time with persistent analytics and performance trends.

", - "keywords": [], - "url": { - "label": "", - "href": "https://lifting.dakheera47.com/" - } - } - ] - }, - "publications": { - "name": "Publications", - "columns": 1, - "separateLinks": true, - "visible": true, - "id": "publications", - "items": [] - }, - "references": { - "name": "References", - "columns": 1, - "separateLinks": true, - "visible": false, - "id": "references", - "items": [ - { - "id": "f2sv5z0cce6ztjl87yuk8fak", - "visible": true, - "name": "Available upon request", - "description": "", - "summary": "", - "url": { - "label": "", - "href": "" - } - } - ] - }, - "skills": { - "name": "Skills", - "columns": 2, - "separateLinks": true, - "visible": true, - "id": "skills", - "items": [ - { - "id": "jfgzfcwcg65k9gemuxlfe9m3", - "visible": true, - "name": "Frontend Development", - "description": "", - "level": 0, - "keywords": [ - "React", - "Next.js", - "Tailwind CSS", - "Strapi CMS", - "Elementor", - "GraphQL", - "TypeScript", - "CI/CD", - "PWA Development", - "AstroJS", - "React Testing Library" - ] - }, - { - "id": "sk3957foopxir2hw4xzxqahh", - "visible": true, - "name": "Backend Development", - "description": "", - "level": 0, - "keywords": [ - "Node.js", - "Express.js", - "MongoDB", - "Supabase", - "Firebase", - "Docker", - "FastAPI", - "AWS S3", - "AWS SES" - ] - }, - { - "id": "d9bddwdj6qreknhk644rm0bs", - "visible": true, - "name": "Leadership and Problem-Solving", - "description": "", - "level": 0, - "keywords": [ - "Agile Project Management", - "Conflict Resolution", - "Creative Problem-Solving", - "Decision-Making", - "Effective Communication", - "Adaptability" - ] - }, - { - "id": "gk4hrky0wnbsbdcmmud48zjh", - "visible": true, - "name": "Other Programming", - "description": "", - "level": 0, - "keywords": [ - "Python Scripting", - "PyAutoGUI", - "Git", - "GitHub", - "Selenium", - "Data Analysis", - "Web Scraping", - "Data Cleaning" - ] - } - ] - }, - "custom": {} - }, - "metadata": { - "template": "onyx", - "layout": [ - [ - [ - "summary", - "education", - "experience", - "projects", - "references" - ], - [ - "profiles", - "skills", - "certifications", - "interests", - "languages", - "awards", - "volunteer", - "publications" - ] - ] - ], - "css": { - "value": "* {\n\toutline: 1px solid #000;\n\toutline-offset: 4px;\n}", - "visible": false - }, - "page": { - "margin": 34, - "format": "a4", - "options": { - "breakLine": false, - "pageNumbers": false - } - }, - "theme": { - "background": "#ffffff", - "text": "#000000", - "primary": "#475569" - }, - "typography": { - "font": { - "family": "IBM Plex Sans", - "subset": "latin", - "variants": [ - "regular" - ], - "size": 13 - }, - "lineHeight": 1.75, - "hideIcons": false, - "underlineLinks": true - }, - "notes": "" - } -} \ No newline at end of file