React Project to showcase Iiself and other projects
Go to file
Sascha 45ff50e34c fix: return 403, not 500, for disallowed CORS origins
The cors() origin callback rejected disallowed origins by calling
callback(new Error(...)), which Express routes to the generic error
handler - previously hardcoded to always respond 500 and log
"Unhandled error". A rejected origin is expected, routine traffic
(bots, scanners, or a deliberate CORS test), not a server fault, and
was being reported and logged as one.

The request was already being correctly rejected either way (no data
processed, no email sent) - this only fixes the status code and log
noise, not a security gap.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 18:56:35 +02:00
.claude feat: update social links to use Git instead of Codeberg and enhance project descriptions 2026-07-27 13:23:54 +02:00
backend fix: return 403, not 500, for disallowed CORS origins 2026-07-29 18:56:35 +02:00
public feat: add free accessibility audit landing page (B2B) 2026-07-29 17:43:50 +02:00
src feat: add free accessibility audit landing page (B2B) 2026-07-29 17:43:50 +02:00
.gitignore feat: add free accessibility audit landing page (B2B) 2026-07-29 17:43:50 +02:00
README.md feat: add free accessibility audit landing page (B2B) 2026-07-29 17:43:50 +02:00
eslint.config.js feat: update social links to use Git instead of Codeberg and enhance project descriptions 2026-07-27 13:23:54 +02:00
index.html feat: update social links to use Git instead of Codeberg and enhance project descriptions 2026-07-27 13:23:54 +02:00
package-lock.json feat: add free accessibility audit landing page (B2B) 2026-07-29 17:43:50 +02:00
package.json feat: add free accessibility audit landing page (B2B) 2026-07-29 17:43:50 +02:00
prerender.js feat: add free accessibility audit landing page (B2B) 2026-07-29 17:43:50 +02:00
tsconfig.app.json feat: update social links to use Git instead of Codeberg and enhance project descriptions 2026-07-27 13:23:54 +02:00
tsconfig.json init 2025-08-07 17:19:41 +02:00
tsconfig.node.json feat: update social links to use Git instead of Codeberg and enhance project descriptions 2026-07-27 13:23:54 +02:00
vite.config.ts feat: update social links to use Git instead of Codeberg and enhance project descriptions 2026-07-27 13:23:54 +02:00
vitest.config.ts feat: update social links to use Git instead of Codeberg and enhance project descriptions 2026-07-27 13:23:54 +02:00

README.md

Portfolio Page

A modern, responsive portfolio website built with React, TypeScript, and Vite. This project showcases professional skills, projects, certifications, and services in an elegant and interactive interface.

About This Project

This portfolio website serves as a comprehensive showcase of professional experience and capabilities. It features:

  • Modern Design: Clean, responsive design that works seamlessly across all devices
  • Interactive Sections: Engaging hero section, about me, skills showcase, project gallery, certifications, and services
  • Theme Support: Built-in light/dark theme toggle for enhanced user experience
  • Performance Optimized: Built with Vite for fast loading and optimal performance
  • TypeScript: Fully typed codebase for better development experience and code reliability

Features

  • Hero Section: Eye-catching introduction with personal branding and smooth scroll to projects
  • About Section: Professional background and personal story
  • Skills Section: Technical expertise with visual skill indicators
  • Projects Section: Portfolio of completed projects with descriptions and links
  • Certifications Section: Professional certifications and achievements
  • Services Section: Available professional services
  • Contact Section: Email and appointment links (no form - the address is obfuscated)
  • Accessibility Audit Landing Page: /de/audit and /en/audit, with a request form
  • Multi-page Routing: React Router with smooth hash navigation between sections
  • Legal Compliance: German Impressum page for legal requirements
  • Theme Support: Built-in light/dark theme toggle with persistence
  • Responsive Navigation: Mobile-friendly navigation with hamburger menu
  • Audit Endpoint: Separate Node.js/Express service, deployed on its own (see backend/README.md)
  • Enhanced UX: Detailed error handling, loading states, and user feedback

Technology Stack

Frontend

  • React 19 with TypeScript for type-safe component development
  • Vite for fast development and optimized production builds
  • React Router Dom for multi-page navigation and hash-based scrolling
  • SCSS with modular architecture and theme system
  • Lucide React for consistent iconography
  • Fontsource for self-hosted Comfortaa and Quicksand (no Google Fonts CDN)

Backend (backend/, deployed separately)

  • Node.js with Express.js, serving only the audit request endpoint
  • Nodemailer over SMTP
  • express-validator for request validation and sanitisation
  • Express Rate Limit for API protection and spam prevention
  • CORS restricted to an explicit origin allowlist
  • Helmet for response security headers

Development & Quality

  • TypeScript for enhanced developer experience and code reliability
  • ESLint for consistent code standards and best practices
  • Vite HMR for instant development feedback

Planned Additions

Protected Admin Panel

A secure, password-protected administrative interface is planned for future releases. This admin panel will provide:

  • Content Management: Easy editing of personal information, skills, and project details
  • Project Management: Add, edit, and remove projects from the portfolio
  • Skills Management: Update technical skills and proficiency levels
  • Certifications Management: Maintain and update professional certifications
  • Real-time Updates: Changes will be reflected immediately on the public portfolio
  • Secure Authentication: Protected access to prevent unauthorized modifications

This feature will enable dynamic content updates without requiring code changes, making the portfolio easily maintainable and always up-to-date.

Language Localization (i18n)

Multi-language support to make the portfolio accessible to an international audience:

  • Primary Languages: English and German localization
  • Extensible Framework: Architecture designed to support additional languages easily
  • Dynamic Language Switching: Real-time language toggle in the navigation
  • Localized Content: All text content, including:
    • Navigation labels and menu items
    • Section titles and descriptions
    • Button text and form labels
    • Error messages and status notifications
    • Project descriptions and technical details
    • Skills and certifications descriptions
  • Browser Language Detection: Automatic language selection based on user's browser settings
  • Persistent Language Preference: User's language choice saved and remembered across sessions
  • SEO Optimization: Proper language meta tags and hreflang attributes for better search engine visibility
  • Professional Translation: Native-quality translations for both English and German content

The localization system will be implemented using React Context and TypeScript for type-safe translations, ensuring consistent and maintainable multi-language support.

Getting Started

Prerequisites

  • Node.js (version 18 or higher)
  • npm or yarn package manager

Installation

  1. Clone the repository:
git clone https://github.com/LuciusShadow/portfolio-page.git
cd portfolio-page
  1. Install dependencies:
npm install
  1. Start the development server:
npm run dev
  1. Open your browser and navigate to http://localhost:5173

Audit endpoint (only needed to work on the audit form)

cd backend
npm install
cp .env.example .env   # then fill in the SMTP credentials
npm start

Point the frontend at it with VITE_AUDIT_ENDPOINT in a .env at the project root, for example VITE_AUDIT_ENDPOINT=http://localhost:3001/api/audit-request.

See backend/README.md for deployment and the protections in place.

Backend Setup Notes

  • The service is deployed separately from the static site - it runs on the VPS, not on the web host that serves dist/
  • It binds to 127.0.0.1 and expects nginx in front of it for TLS
  • ALLOWED_ORIGINS is an explicit allowlist; requests from other origins are refused
  • The CSP connect-src in public/.htaccess must name the endpoint's host, otherwise the browser blocks the request

Building for Production

npm run build

The built files will be available in the dist directory.

Project Structure

portfolio-page/
├── backend/                    # Node.js Express backend for contact form
│   ├── middleware/            # Validation and security middleware
│   ├── routes/               # API route handlers (contact form)
│   ├── services/             # Email service with Gmail integration
│   ├── server.js             # Express server configuration
│   └── .env                  # Environment variables (Gmail credentials)
├── src/
│   ├── app/                  # Main application components
│   │   ├── page.tsx         # HomePage component with all sections
│   │   └── AppRouter.tsx    # React Router setup with hash navigation
│   ├── assets/              # Static assets (images, icons)
│   ├── components/          # Reusable UI components
│   │   ├── layout/         # Navigation, Footer, MobileMenu
│   │   ├── sections/       # Hero, About, Skills, Projects, etc.
│   │   └── ThemeToggle.tsx # Dark/light theme switcher
│   ├── config/             # Configuration files
│   │   ├── api.ts         # API endpoints configuration
│   │   └── personal.ts    # Personal information and social links
│   ├── data/               # TypeScript type definitions
│   │   ├── Project.ts     # Project data structure
│   │   ├── Skill.ts       # Skills and proficiency levels
│   │   ├── Service.ts     # Professional services offered
│   │   └── Certification.ts # Professional certifications
│   ├── pages/              # Page components for routing
│   │   └── ImprintPage.tsx # German legal compliance page
│   ├── scss/               # Modular SCSS styling
│   │   ├── themes/        # Light/dark theme variables
│   │   ├── layout/        # Navigation, footer styling
│   │   ├── sections/      # Individual section styles
│   │   ├── globals.scss   # Global styles and resets
│   │   ├── variables.scss # SCSS variables and breakpoints
│   │   └── mixins.scss    # Reusable SCSS mixins
│   ├── utils/              # Utility functions
│   │   └── scrollUtils.ts # Smooth scrolling navigation helpers
│   └── main.tsx           # Application entry point
├── dist/                   # Production build output
├── vite.config.ts         # Vite configuration
├── tsconfig.json          # TypeScript configuration
└── package.json           # Dependencies and scripts

Contributing

This is a personal portfolio project. While contributions are not expected, suggestions and feedback are always welcome!

License

This project is for personal use and portfolio demonstration purposes.