A personal portfolio website built with React and TypeScript. It is designed to showcase projects, technical skills, and recent blog content to peers, collaborators, and potential hiring managers.
- Single-page portfolio with section-based navigation
- Project showcase with expandable details
- URL deep-link support for project modals via query parameters
- Skills and experience summaries
- Blog feed integration from external source with local backup data
- Contact section with direct social and email links
- Responsive layout across mobile and desktop
- SEO metadata and social sharing tags
- Accessibility-aware UI and practical automated test coverage
- React 18
- TypeScript
- SCSS + Bootstrap/Reactstrap
- React Router
- React Helmet Async
- Create React App (react-scripts)
This project uses Jest, Cypress, and Playwright.
See the full testing strategy and commands in TESTING.md.
- Node.js (LTS recommended)
- npm
git clone https://github.com/JoeCastle/PortfolioV3.git
cd PortfolioV3
npm installnpm startOpen http://localhost:3000.
npm start: starts the app in development modenpm run build: fetches recent posts, updates project date metadata, then builds production assetsnpm test: runs Jest tests viareact-scripts testnpm run pretty: runs Prettier across JS/TS/SCSS/CSS/JSONnpm run cypress:open: opens Cypress UInpm run cypress-component: runs Cypress component testsnpm run cypress-e2e: runs Cypress e2e testsnpm run cypress-e2e:coverage: runs Cypress e2e and generates NYC reportsnpm run playwright:test: runs Playwright testsnpm run playwright:test:headed: runs Playwright in headed modenpm run playwright:test:update-snapshots: updates Playwright visual snapshotsnpm run serve:build: serves thebuilddirectory on127.0.0.1:3000npm run fetch-recent-posts: fetches recent blog posts and validates SEO data contractnpm run update-project-date: updates sitemap/project date metadata
The homepage project modal supports URL query parameters for direct linking.
- Example:
/?project=joebloggs - Example:
/?project=trainingApp
Behaviour:
- A valid
projectparameter scrolls the page to the Projects section and opens the matching modal. - If the project is in the secondary list, the section expands first, then opens the modal.
- Closing the modal removes the
projectparameter from the URL. - Invalid project values are ignored safely.
src/: application source codesrc/components/: page, section, and shared React componentssrc/data/: portfolio/project/skills/blog backup datasrc/scss/: styling architecturecypress/: Cypress component and e2e testse2e/: Playwright tests and reliability helpersscripts/: build-time and data maintenance scriptspublic/: static public assets
Deployment notes and hosting considerations are documented in DEPLOYMENT.md.
- Website/application code: LICENSE-website
- Content (text/media): LICENSE-content