Portfolio and technical blog for Aebrahm Ramos. React 19 and Vite on the front, a Cloudflare Worker with D1 behind it. Light and dark themes, self-hosted fonts, and an accessibility-first build.
- Fully Responsive Design - Optimized for all device sizes (mobile, tablet, desktop)
- Dark Mode Support - Toggle between light and dark themes with persistent preference
- Smooth Animations - Elegant transitions and scroll-based animations
- Accessibility First - WCAG 2.1 AA compliant with keyboard navigation support
- Performance Optimized - Fast loading with lazy loading and code splitting
- SEO Ready - Proper meta tags, semantic HTML, and sitemap
- Hero - Positioning statement, availability, primary calls to action
- About - Background plus a short fact list
- Experience - Professional timeline
- Projects - Four spotlight case studies, then a compact index of the rest
- Skills - Grouped by area
- Education - Degree and coursework
- Organizations - Leadership roles
- Contact - Form, direct links, resume download (
#resume) - Footer - Secondary navigation
Plus /blog, /blog/:slug, /blog/series/:slug and an authenticated /admin.
- Framework: React 19 + React Router 7
- Build: Vite 7
- Hosting / API: Cloudflare Workers + D1 (
src/worker.js) - Styling: Plain CSS with a design-token layer in
src/m3/tokens/ - Fonts: Geist Variable + Geist Mono, self-hosted via
@fontsource-variable - Icons: Phosphor, via
react-icons/pi - Editor: Tiptap (admin blog editor)
- Mail: EmailJS + reCAPTCHA v3
- Language: JavaScript (ES modules)
- Node.js (v18 or higher)
- npm or yarn
- Clone the repository:
git clone <repository-url>
cd portfolio- Install dependencies:
npm install- Start the development server:
npm run dev- Open your browser and navigate to:
http://localhost:5173
npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production buildnpm run lint- Run ESLint
portfolio/
├── public/ # Static assets
│ └── vite.svg
├── src/
│ ├── components/ # React components
│ │ ├── common/ # Reusable components
│ │ ├── layout/ # Layout components
│ │ └── sections/ # Page sections
│ ├── context/ # React Context providers
│ │ └── ThemeContext.jsx
│ ├── data/ # Static data
│ │ ├── education.js
│ │ ├── experience.js
│ │ ├── projects.js
│ │ └── skills.js
│ ├── m3/ # Design tokens (color, type, shape, spacing, motion)
│ │ ├── tokens/
│ │ └── theme.js # data-theme attribute flip
│ ├── utils/ # Utility functions
│ │ └── helpers.js
│ ├── App.jsx # Main app component
│ ├── main.jsx # Entry point
│ └── index.css # Global styles
├── index.html # HTML template
├── package.json
├── vite.config.js # Vite configuration
└���─ README.md
Update the following files with your information:
-
Data Files (
src/data/)education.js- Add your educational backgroundexperience.js- Add your work experienceprojects.js- Add your projectsskills.js- Add your technical skills
-
Hero Section (
src/components/sections/Hero.jsx)- Update profile image URL
- Update name and description
-
Contact Information (
src/components/sections/Contact.jsx)- Update email, LinkedIn, GitHub links
- Form field names (
firstName,lastName,email,subject,message) must stay in sync with the EmailJS template
Both palettes are static custom properties in src/m3/tokens/color.css, keyed on
:root and :root[data-theme="dark"]. The brand accent is #377dff, rendered as
#1552cc in light mode and #5b9bff in dark so button and link text clears WCAG AA.
src/m3/theme.js only flips the data-theme attribute.
Replace placeholder images in:
- Hero section profile image
- Project thumbnails in
src/data/projects.js
npm run buildThe optimized files will be in the dist/ directory.
- Push your code to GitHub
- Connect your repository to Netlify
- Set build command:
npm run build - Set publish directory:
dist
npm install -g vercel
vercel- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
This portfolio follows WCAG 2.1 Level AA guidelines:
- Semantic HTML5 elements
- Proper heading hierarchy
- Keyboard navigation support
- Focus indicators
- Color contrast ratios
- Alt text for images
- ARIA labels where needed
None at the moment. Please report any issues you find!
This project is open source and available under the MIT License.
Aebrahm Ramos
- Email: aebrahmramos.dev@gmail.com
- LinkedIn: linkedin.com/in/aebrahmramos
- GitHub: github.com/AebrahmRamos
- Phosphor Icons, via React Icons
- Vite team for the blazing fast build tool
Made with ❤️ by Aebrahm Ramos