A single-page React site featuring a security newsletter and technical writeups (TryHackMe/CTF style). Built with Vite + Tailwind, markdown-based content, and client-side routing.
npm install
npm run start- Dev server: http://localhost:5173
- Build:
npm run build - Test:
npm test
/my-portfolio
├─ public/
│ └─ index.html
├─ src/
│ ├─ assets/
│ ├─ components/
│ │ ├─ Layout/
│ │ │ └─ Header.jsx
│ │ │ └─ Footer.jsx
│ │ ├─ Newsletter/
│ │ │ └─ NewsletterHero.jsx
│ │ │ └─ SubscribeForm.jsx
│ │ │ └─ IssueCard.jsx
│ │ ├─ Writeups/
│ │ │ └─ WriteupList.jsx
│ │ │ └─ WriteupCard.jsx
│ │ │ └─ WriteupViewer.jsx
│ │ └─ UI/
│ ├─ pages/
│ │ └─ Home.jsx
│ │ └─ Newsletter.jsx
│ │ └─ Writeups.jsx
│ │ └─ WriteupPage.jsx
│ ├─ data/
│ │ └─ writeups/
│ │ └─ newsletter/
│ ├─ hooks/
│ ├─ utils/
│ ├─ App.jsx
│ ├─ index.js
│ └─ routes.js
├─ .github/workflows/ci.yml
├─ package.json
└─ README.md
- Writeups live in
src/data/writeups/*.md, with frontmatter (seesrc/data/README.md). - Newsletter issues live in
src/data/newsletter/*.(json|md). - Content is loaded at runtime using Vite
import.meta.glob, parsed and sanitized on the client.
- The subscribe form posts to a mock endpoint. Replace with your provider:
- Mailchimp: Use their Marketing API or HTML form action URL.
- Buttondown: POST to
https://api.buttondown.email/v1/subscriberswith API key. - ConvertKit: POST to form endpoint with
emailfield.
In src/components/Newsletter/SubscribeForm.jsx, replace the fetch('/api/mock-subscribe', ...) call with your provider. Add any headers and secrets using environment variables. Avoid exposing secrets on the client—use a serverless function or backend for production.
Local fallback stores emails in localStorage under newsletterSubs.
- Semantic landmarks:
header,main,footer. - Skip link provided in
public/index.html. - Focus outlines are enabled; Tailwind focus utilities used.
- Color choices meet contrast via Tailwind defaults. Adjust in
tailwind.config.cjsif needed.
- React.lazy and Suspense for route-based code splitting.
- Markdown and images load on demand.
- Build uses Vite for fast static output.
- Any static host works (Netlify, Vercel, GitHub Pages). Build with
npm run buildand deploydist/. - Vercel: add a project, import repo, set framework to Vite.
- Netlify: drag-and-drop
dist/or connect repo; build commandnpm run build, publish directorydist.
- New writeup scaffold:
npm run new:writeup "My Target writeup"- Add newsletter issue: create
src/data/newsletter/issue-003.mdor.json.
- Tests: Jest + React Testing Library.
- CI: GitHub Actions runs install, tests, and build.
- Tailwind with PostCSS is preconfigured. Utilities and typography plugin are enabled.
- Three sample writeups and two newsletter issues included. Replace or add more.