HTTPS

HTTPS (HyperText Transfer Protocol Secure) ensures encrypted communication between the client and server using TLS (Transport Layer Security). It is a foundational requirement for modern web applications.

Why It Matters

  • Encrypts data in transit (prevents MITM attacks)

  • Enables modern APIs:

    • Service Workers
    • Progressive Web Apps (PWA)
    • Web Push Notifications
  • Improves SEO (Google ranking signal)

  • Required for secure cookies and authentication flows

Implementation Approaches

1. Using Let’s Encrypt (Certbot)

sudo apt update
sudo apt install certbot python3-certbot-nginx

sudo certbot --nginx -d example.com -d www.example.com

2. Force HTTPS Redirect (Nginx)

server {
    listen 80;
    server_name example.com www.example.com;

    return 301 https://$host$request_uri;
}

3. Force HTTPS Redirect (Apache)

<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

4. Enable HSTS (Strict Transport Security)

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Best Practices

  • Use TLS 1.2 or higher
  • Avoid mixed content (HTTP assets on HTTPS pages)
  • Renew certificates automatically
  • Use secure cookies:
Set-Cookie: sessionId=abc123; Secure; HttpOnly; SameSite=Lax

Mobile Friendly

Overview

A mobile-friendly website adapts layout, content, and interactions for smaller screens and touch interfaces.

Key Principles

  • Responsive design (fluid layouts)
  • Touch-friendly UI
  • Optimized images and fonts
  • Avoid horizontal scrolling

Essential Setup

1. Viewport Meta Tag

<meta name="viewport" content="width=device-width, initial-scale=1.0">

2. Responsive Layout (CSS)

.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 16px;
}

3. Media Queries

@media (max-width: 768px) {
  .grid {
    display: block;
  }

  .sidebar {
    display: none;
  }
}

4. Flexible Images

img {
  max-width: 100%;
  height: auto;
}

5. Responsive Typography

body {
  font-size: clamp(14px, 2vw, 18px);
}

Best Practices

  • Minimum touch target: 48px
  • Avoid hover-only interactions
  • Lazy load images:
<img src="image.jpg" loading="lazy" alt="Example">

No Intrusive Interstitials

Overview

Intrusive interstitials are UI elements (popups/modals) that block content and degrade user experience, especially on mobile.

What to Avoid

  • Full-screen popups on page load
  • Delayed popups that obscure content
  • Overlays that require dismissal before viewing content

Acceptable Alternatives

  • Cookie banners
  • Small, dismissible banners
  • Exit-intent popups (desktop only)

Implementation Example

<div class="cookie-banner">
  <p>We use cookies to improve your experience.</p>
  <button onclick="acceptCookies()">Accept</button>
</div>
.cookie-banner {
  position: fixed;
  bottom: 0;
  width: 100%;
  background: #222;
  color: #fff;
  padding: 12px;
  text-align: center;
}

Avoid Blocking Modal on Load

Bad:

window.onload = () => {
  showFullscreenModal();
};

Better:

document.querySelector('#subscribe-btn').addEventListener('click', () => {
  openModal();
});

Best Practices

  • Ensure content is immediately accessible
  • Keep overlays small and dismissible
  • Avoid auto-triggering on page load (especially mobile)

Interaction to Next Paint (INP)

Overview

INP (Interaction to Next Paint) measures responsiveness by tracking the delay between user interaction and visual update.

Key Difference from FID

  • FID: Only initial delay
  • INP: Full interaction lifecycle (input → processing → paint)

Target Metrics

  • Good: ≤ 200ms
  • Needs improvement: 200–500ms
  • Poor: > 500ms

Common Causes of Poor INP

  • Long JavaScript execution
  • Main thread blocking
  • Heavy event handlers
  • Layout thrashing

Optimization Techniques

1. Break Long Tasks

function heavyTask() {
  for (let i = 0; i < 1e9; i++) {}
}

// Instead
function chunkedTask() {
  let i = 0;
  function processChunk() {
    let end = i + 1000000;
    while (i < end) i++;
    if (i < 1e9) {
      setTimeout(processChunk);
    }
  }
  processChunk();
}

2. Use requestIdleCallback

requestIdleCallback(() => {
  performNonCriticalTask();
});

3. Optimize Event Handlers

button.addEventListener('click', () => {
  requestAnimationFrame(() => {
    updateUI();
  });
});

4. Debounce Input Events

function debounce(fn, delay) {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
}

input.addEventListener('input', debounce(handleInput, 300));

5. Avoid Layout Thrashing

Bad:

element.style.width = "100px";
console.log(element.offsetWidth);

Better:

const width = element.offsetWidth;
element.style.width = width + 10 + "px";

Monitoring INP

import { onINP } from 'web-vitals';

onINP(console.log);