Snippets

Coding examples

Real bits of code taken from my projects, with one-click copy.

Regex form validation

Validates contact form input client-side with a simple email regex plus a few human-friendly checks. Fields get inline styling and the user gets a clear message if anything is missing or invalid.

regex-validation.js javascript
// Basic email validation
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

export function validateContactForm(form) {
  const errors = {};
  const fieldStatus = {};

  const checks = {
    name: (value) => {
      const trimmed = value.trim();
      if (!trimmed) return { valid: false, type: "missing", message: "Please enter your name." };
      return { valid: true };
    },
    email: (value) => {
      const trimmed = value.trim();
      if (!trimmed) return { valid: false, type: "missing", message: "Please enter your email address." };
      if (!emailPattern.test(trimmed)) {
        return { valid: false, type: "invalid", message: "Please enter a valid email address." };
      }
      return { valid: true };
    },
    telephone: (value) => {
      const trimmed = value.trim();
      if (!trimmed) return { valid: false, type: "missing", message: "Please enter your telephone number." };
      if (trimmed.replace(/\D/g, "").length < 10) {
        return { valid: false, type: "invalid", message: "Please enter a valid telephone number." };
      }
      return { valid: true };
    },
    message: (value) => {
      const trimmed = value.trim();
      if (!trimmed) {
        return {
          valid: false,
          type: "missing",
          message: "Please enter a message.",
        };
      }
      if (trimmed.length < 5) {
        return {
          valid: false,
          type: "invalid",
          message: "Message must be at least 5 characters.",
        };
      }
      if (trimmed.length > 1000) {
        return {
          valid: false,
          type: "invalid",
          message: "Message must be 1000 characters or fewer.",
        };
      }
      return { valid: true };
    },
  };

  Object.entries(checks).forEach(([name, check]) => {
    const field = form.elements[name];
    if (!field) return;

    const result = check(field.value);
    fieldStatus[name] = result.valid ? "valid" : "invalid";
    if (!result.valid) errors[name] = { label: name, type: result.type, message: result.message };
  });

  return { isValid: Object.keys(errors).length === 0, errors, fieldStatus };
}

Responsive service navigation (Sass)

Uses a Sass map plus an @each loop to generate themed navigation styles. The result is DRY, consistent and scalable.

service-nav.scss scss
// Sass loop that generates themed navigation dropdown styles
$services: (
  "design": #00e5ff,
  "dev": #ff6a00,
  "seo": #ff2bd6,
);

@mixin mq($min) {
  @media (min-width: $min) {
    @content;
  }
}

.services-nav {
  display: none;

  @include mq(992px) {
    display: flex;
  }
}

@each $name, $color in $services {
  .nav-service--#{$name} {
    position: relative;
    color: #fff;

    &:hover,
    &:focus-visible {
      background: $color;
    }

    &::after {
      content: "";
      position: absolute;
      left: 50%;
      top: 100%;
      transform: translateX(-50%);
      border: 10px solid transparent;
      border-top-color: $color;
      opacity: 0;
      transition: opacity 0.15s ease;
    }

    &:hover::after,
    &:focus-visible::after {
      opacity: 1;
    }
  }
}

Layout-related tweaks (JavaScript)

A tiny utility that keeps layout in sync on wide screens and throttles work with requestAnimationFrame so resize/scroll stays smooth.

layout-tweaks.js javascript
// requestAnimationFrame-throttled layout syncing (wide screens only)
let raf = 0;

export function syncPanels(assignmentsEl, previewEl) {
  const run = () => {
    raf = 0;
    if (window.matchMedia("(min-width: 992px)").matches) {
      previewEl.style.minHeight = `${assignmentsEl.offsetHeight}px`;
    } else {
      previewEl.style.minHeight = "";
    }
  };

  const schedule = () => {
    if (raf) return;
    raf = requestAnimationFrame(run);
  };

  window.addEventListener("resize", schedule);
  window.addEventListener("scroll", schedule, { passive: true });
  schedule();
}

Product filters hook (React/TypeScript)

A pure TypeScript React hook that memoizes the filtering logic and keeps all the domain rules (category, price range, stock status, text search and so on) in one place.

useProductFilters.ts typescript
import { useMemo } from 'react'
import type { Product } from '../data/products'

export type ProductFilters = {
  category: string
  brand: string
  size: string
  gender: string
  year: number | null
  minPrice: number | null
  maxPrice: number | null
  inStockOnly: boolean
  query: string
}

export function useProductFilters(
  products: Product[],
  { category, brand, size, gender, year, minPrice, maxPrice, inStockOnly, query }: ProductFilters,
): Product[] {
  return useMemo(() => {
    const normalizedQuery = query.trim().toLowerCase()

    return products.filter((product) => {
      if (category !== 'All' && product.category !== category) return false
      if (brand !== 'All' && product.brand !== brand) return false
      if (size !== 'All' && product.size !== size) return false
      if (gender !== 'All' && product.gender !== gender) return false
      if (year !== null && product.year !== year) return false
      if (inStockOnly && product.in_stock <= 0) return false

      if (minPrice !== null && product.price_in_pounds < minPrice) return false
      if (maxPrice !== null && product.price_in_pounds > maxPrice) return false

      if (normalizedQuery) {
        const name = `${product.brand} ${product.model}`.toLowerCase()
        if (!name.includes(normalizedQuery)) return false
      }

      return true
    })
  }, [products, category, brand, size, gender, year, minPrice, maxPrice, inStockOnly, query])
}

SMTP mail config (PHP)

Sends a contact notification email using PHPMailer, reading SMTP configuration from environment variables.

mail.php php
<?php
use PHPMailer\PHPMailer\PHPMailer;

/**
 * Send a contact email using SMTP settings from environment variables.
 */
function sendContactEmail(array $data): bool
{
    $host = getenv('SMTP_HOST') ?: '';
    $port = (int) (getenv('SMTP_PORT') ?: 587);
    $username = getenv('SMTP_USER') ?: '';
    $password = getenv('SMTP_PASS') ?: '';

    if ($host === '' || $username === '' || $password === '') {
        return false;
    }

    $mail = new PHPMailer(true);
    $mail->isSMTP();
    $mail->Host = $host;
    $mail->Port = $port;
    $mail->SMTPAuth = true;
    $mail->Username = $username;
    $mail->Password = $password;
    $mail->SMTPSecure = getenv('SMTP_ENCRYPTION') ?: 'tls';

    $mail->setFrom(getenv('SMTP_FROM') ?: $username, 'Portfolio contact form');
    $mail->addAddress(getenv('SMTP_TO') ?: $username);
    $mail->isHTML(false);
    $mail->Subject = 'New portfolio contact form submission';

    $mail->Body = implode("\n", [
        "Name: {$data['name']}",
        "Company: " . ($data['company'] ?: '(not provided)'),
        "Email: {$data['email']}",
        "Telephone: {$data['telephone']}",
        "",
        $data['message'],
    ]);

    return $mail->send();
}

Server-side contact handler (PHP)

Validates request data and builds a structured error response so the front end can show which fields need attention.

contact-handler.php php
<?php

// A server-side contact handler: validate → save to database → send email.
function validateContact(array $post): array
{
    $errors = [];
    $fieldStatus = [];

    $name = trim($post['name'] ?? '');
    $email = trim($post['email'] ?? '');
    $telephone = trim($post['telephone'] ?? '');
    $message = trim($post['message'] ?? '');

    if ($name === '') {
        $errors['name'] = ['type' => 'missing', 'message' => 'Please enter your name.'];
        $fieldStatus['name'] = 'invalid';
    } else {
        $fieldStatus['name'] = 'valid';
    }

    if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors['email'] = ['type' => 'invalid', 'message' => 'Please enter a valid email address.'];
        $fieldStatus['email'] = 'invalid';
    } else {
        $fieldStatus['email'] = 'valid';
    }

    $digits = strlen(preg_replace('/\D+/', '', $telephone));
    if ($digits < 10) {
        $errors['telephone'] = ['type' => 'invalid', 'message' => 'Please enter a valid telephone number.'];
        $fieldStatus['telephone'] = 'invalid';
    } else {
        $fieldStatus['telephone'] = 'valid';
    }

    if (mb_strlen($message) < 5 || mb_strlen($message) > 1000) {
        $errors['message'] = ['type' => 'invalid', 'message' => 'Message must be between 5 and 1000 characters.'];
        $fieldStatus['message'] = 'invalid';
    } else {
        $fieldStatus['message'] = 'valid';
    }

    return ['isValid' => empty($errors), 'errors' => $errors, 'fieldStatus' => $fieldStatus];
}