Options -Indexes
DirectoryIndex index.php
RewriteEngine On
RewriteRule ^(?:backend|storage|scripts|examples|docs|games)/ - [F,END]
RewriteRule ^site\.(?:local|example)\.php$ - [F,END]
# Dotfiles and .git (certbot's .well-known stays reachable), notes and engine sources.
RewriteRule ^\.(?!well-known/) - [F,END]
RewriteRule \.(?:md|py|pyc|cjs)$ - [F,END]
RewriteRule ^index\.html?$ / [R=302,END]
RewriteRule ^sitemap\.xml$ public-index.php?format=sitemap [QSA,END]
RewriteRule ^llms\.txt$ public-index.php?format=llms [QSA,END]
RewriteRule ^robots\.txt$ public-index.php?format=robots [QSA,END]
RewriteRule ^imports/([A-Za-z0-9][A-Za-z0-9._-]*\.json)$ catalog-download.php?file=$1 [QSA,END]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-z0-9]+(?:_[a-z0-9]+)*)/?$ topic.php?topic=$1 [QSA,END]

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000"
    Header setifempty X-Content-Type-Options "nosniff"
    Header setifempty X-Frame-Options "SAMEORIGIN"
    Header setifempty Referrer-Policy "strict-origin-when-cross-origin"
    Header setifempty Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()"
    Header setifempty Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data:; connect-src 'self'; frame-src 'self' blob:; worker-src 'self' blob:; object-src 'none'; base-uri 'self'; form-action 'self' https://accounts.google.com; frame-ancestors 'self'"
    # Versioned assets (?v=hash) never change under the same URL.
    <If "%{REQUEST_URI} =~ m#/assets/# && %{QUERY_STRING} =~ /(?:^|&)v=/">
        Header set Cache-Control "public, max-age=31536000, immutable"
    </If>
</IfModule>
