# ============================================================================
# .htaccess Starter Pack
# ============================================================================
# A drop-in starting point for Apache sites. Covers the things almost every
# project needs: forcing HTTPS, picking one canonical hostname (www or
# non-www), browser caching, gzip/brotli compression, and a baseline set of
# security headers.
#
# HOW TO USE
#   1. Rename this file to ".htaccess" (no extension) and put it in your
#      site's document root.
#   2. Read the "www vs non-www" section below and pick ONE direction -
#      it's commented out by default so it doesn't do anything until you do.
#   3. Test on staging first, especially the HTTPS redirect + HSTS header
#      near the bottom - see README.md for why.
#
# RULE ORDER MATTERS. Apache reads this file top to bottom, and rewrite
# rules can short-circuit each other. Keep redirects (HTTPS, www) at the
# TOP, before anything else, so every other rule already sees the final,
# canonical URL. Don't reorder sections unless you understand why they're
# in this order - see README.md's "gotchas" section for the common ways
# this breaks.
# ============================================================================


# ----------------------------------------------------------------------
# 1. REDIRECTS (HTTPS + www/non-www)
# ----------------------------------------------------------------------
# These must run first. mod_rewrite needs to be enabled on the server for
# any of this section to work (it almost always is, but if redirects do
# nothing, that's the first thing to check).

<IfModule mod_rewrite.c>
	RewriteEngine On

	# --- Force HTTPS ---
	# Redirects any plain http:// request to https://. Safe to leave on
	# even if you're not sure - it simply does nothing if the site isn't
	# served over HTTPS yet.
	RewriteCond %{HTTPS} off
	RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

	# --- www vs non-www ---
	# Pick ONE of the two blocks below and uncomment it. Leaving both
	# commented out (the default) means visitors can reach the site at
	# both www.example.com AND example.com, which splits SEO signals
	# across two "different" URLs in search engines' eyes.

	# Option A: force www.example.com -> example.com (no www)
	# RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
	# RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]

	# Option B: force example.com -> www.example.com (with www)
	# RewriteCond %{HTTP_HOST} !^www\. [NC]
	# RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>


# ----------------------------------------------------------------------
# 2. SECURITY HEADERS
# ----------------------------------------------------------------------
# A conservative baseline. Nothing here should break a typical site, but
# read each header's comment - a couple of these can affect embeds or
# third-party widgets if you use them.

<IfModule mod_headers.c>
	# Tells browsers to only ever connect over HTTPS for the next year,
	# including subdomains. Once a browser sees this, it will refuse to
	# load the site over plain HTTP even if a user types http:// - and it
	# remembers that for the full max-age. That's the point, but it also
	# means this is hard to undo quickly if something's misconfigured.
	# Uncomment only once you're confident HTTPS is solid. See README.md.
	# Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

	# Stops the browser from guessing content types (e.g. treating a
	# .txt file as HTML because of its content). Safe to leave on always.
	Header always set X-Content-Type-Options "nosniff"

	# Prevents the site from being loaded inside an <iframe> on another
	# domain - blocks a common clickjacking technique. Set to SAMEORIGIN
	# instead of DENY if you need to iframe your own pages on your own
	# domain (e.g. a widget preview page).
	Header always set X-Frame-Options "SAMEORIGIN"

	# Limits how much of your URL gets sent as the "Referer" header when
	# users click links away from your site. strict-origin-when-cross-origin
	# is a good default: full URL on your own site, just the origin
	# (scheme + host) when leaving it.
	Header always set Referrer-Policy "strict-origin-when-cross-origin"

	# Restricts which browser features (camera, microphone, geolocation,
	# etc.) the page is allowed to use. This starter pack turns off the
	# ones most sites never touch - add back anything you actually use.
	Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"

	# Content-Security-Policy is deliberately NOT included here. A CSP
	# that's too strict breaks fonts, embeds, and third-party scripts, and
	# one that's too loose isn't worth having - it has to be tailored to
	# what your specific site actually loads. See README.md for a starting
	# point and how to test one safely before turning it on.
</IfModule>


# ----------------------------------------------------------------------
# 3. BROWSER CACHING
# ----------------------------------------------------------------------
# Tells browsers how long they're allowed to reuse a file before asking
# the server again. Long cache times for assets that rarely change
# (images, fonts) make repeat visits much faster.

<IfModule mod_expires.c>
	ExpiresActive On

	# Images and fonts: safe to cache for a long time - filenames rarely
	# change without also changing content.
	ExpiresByType image/jpeg "access plus 1 year"
	ExpiresByType image/png "access plus 1 year"
	ExpiresByType image/webp "access plus 1 year"
	ExpiresByType image/svg+xml "access plus 1 year"
	ExpiresByType font/woff2 "access plus 1 year"
	ExpiresByType font/woff "access plus 1 year"

	# CSS/JS: shorter than images because these DO change with releases.
	# If you fingerprint/version your filenames (style.a1b2c3.css), bump
	# this to match the images above instead.
	ExpiresByType text/css "access plus 1 week"
	ExpiresByType application/javascript "access plus 1 week"
	ExpiresByType text/javascript "access plus 1 week"

	# HTML: cached briefly, if at all - you usually want visitors to see
	# content updates without a hard refresh.
	ExpiresByType text/html "access plus 1 hour"
</IfModule>


# ----------------------------------------------------------------------
# 4. COMPRESSION (gzip + Brotli)
# ----------------------------------------------------------------------
# Compresses text-based responses before sending them over the wire.
# Brotli typically compresses better than gzip, but mod_brotli isn't
# installed on every Apache setup (check with your host if you're not
# sure) - gzip is the safe, near-universal fallback below it.

<IfModule mod_brotli.c>
	AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/javascript application/javascript application/json image/svg+xml
</IfModule>

<IfModule mod_deflate.c>
	AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json image/svg+xml

	# Don't bother compressing things that are already compressed - it
	# wastes CPU and can occasionally make the file slightly bigger.
	SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|zip|gz|br)$ no-gzip
</IfModule>
