Skip to content

Commit e80084b

Browse files
committed
feat: add .htaccess for Apache configuration to support Next.js static export
1 parent e4be182 commit e80084b

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

public/.htaccess

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# ============================================================
2+
# Notareum — Apache config for static Next.js export (cPanel)
3+
# ============================================================
4+
5+
Options -Indexes -MultiViews
6+
DirectoryIndex index.html
7+
8+
# ------------------------------------------------------------
9+
# Rewrites: HTTPS + non-www + trailing slash
10+
# ------------------------------------------------------------
11+
<IfModule mod_rewrite.c>
12+
RewriteEngine On
13+
14+
# Force HTTPS
15+
RewriteCond %{HTTPS} !=on
16+
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
17+
18+
# Force non-www
19+
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
20+
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
21+
22+
# Add trailing slash to directory URLs (matches Next.js trailingSlash: true)
23+
RewriteCond %{REQUEST_FILENAME} !-f
24+
RewriteCond %{REQUEST_URI} !(.+)/$
25+
RewriteCond %{REQUEST_URI} !\.[a-zA-Z0-9]+$
26+
RewriteRule ^(.*)$ /$1/ [R=301,L]
27+
28+
# Serve /foo/ as /foo/index.html
29+
RewriteCond %{REQUEST_FILENAME} -d
30+
RewriteRule ^(.*)/$ /$1/index.html [L]
31+
</IfModule>
32+
33+
# ------------------------------------------------------------
34+
# Custom error page
35+
# ------------------------------------------------------------
36+
ErrorDocument 404 /404.html
37+
38+
# ------------------------------------------------------------
39+
# Compression
40+
# ------------------------------------------------------------
41+
<IfModule mod_deflate.c>
42+
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
43+
AddOutputFilterByType DEFLATE application/javascript application/json application/xml
44+
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml
45+
AddOutputFilterByType DEFLATE image/svg+xml font/woff font/woff2 application/font-woff application/font-woff2
46+
</IfModule>
47+
48+
<IfModule mod_brotli.c>
49+
AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript
50+
AddOutputFilterByType BROTLI_COMPRESS application/javascript application/json application/xml
51+
AddOutputFilterByType BROTLI_COMPRESS image/svg+xml font/woff font/woff2
52+
</IfModule>
53+
54+
# ------------------------------------------------------------
55+
# Caching
56+
# ------------------------------------------------------------
57+
<IfModule mod_expires.c>
58+
ExpiresActive On
59+
60+
# HTML — short cache, must revalidate
61+
ExpiresByType text/html "access plus 0 seconds"
62+
63+
# Data
64+
ExpiresByType application/json "access plus 0 seconds"
65+
ExpiresByType application/xml "access plus 0 seconds"
66+
ExpiresByType text/xml "access plus 0 seconds"
67+
68+
# Manifests
69+
ExpiresByType application/manifest+json "access plus 1 week"
70+
ExpiresByType text/cache-manifest "access plus 0 seconds"
71+
72+
# Favicon
73+
ExpiresByType image/x-icon "access plus 1 week"
74+
ExpiresByType image/vnd.microsoft.icon "access plus 1 week"
75+
76+
# Images
77+
ExpiresByType image/png "access plus 1 month"
78+
ExpiresByType image/jpeg "access plus 1 month"
79+
ExpiresByType image/gif "access plus 1 month"
80+
ExpiresByType image/svg+xml "access plus 1 month"
81+
ExpiresByType image/webp "access plus 1 month"
82+
ExpiresByType image/avif "access plus 1 month"
83+
84+
# CSS / JS (hashed by Next.js — safe to cache long)
85+
ExpiresByType text/css "access plus 1 year"
86+
ExpiresByType application/javascript "access plus 1 year"
87+
ExpiresByType text/javascript "access plus 1 year"
88+
89+
# Fonts
90+
ExpiresByType font/woff "access plus 1 year"
91+
ExpiresByType font/woff2 "access plus 1 year"
92+
ExpiresByType application/font-woff "access plus 1 year"
93+
ExpiresByType application/font-woff2 "access plus 1 year"
94+
</IfModule>
95+
96+
<IfModule mod_headers.c>
97+
# Long-cache immutable hashed assets from Next.js
98+
<FilesMatch "\.(?:css|js|woff2?|ttf|otf|eot|svg|jpg|jpeg|png|gif|webp|avif|ico)$">
99+
Header set Cache-Control "public, max-age=31536000, immutable"
100+
</FilesMatch>
101+
102+
# Never cache HTML
103+
<FilesMatch "\.(?:html)$">
104+
Header set Cache-Control "public, max-age=0, must-revalidate"
105+
</FilesMatch>
106+
107+
# ------------------------------------------------------------
108+
# Security headers
109+
# ------------------------------------------------------------
110+
Header always set X-Content-Type-Options "nosniff"
111+
Header always set X-Frame-Options "SAMEORIGIN"
112+
Header always set Referrer-Policy "strict-origin-when-cross-origin"
113+
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()"
114+
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
115+
Header always set Cross-Origin-Opener-Policy "same-origin"
116+
117+
# Remove server fingerprint where possible
118+
Header unset X-Powered-By
119+
Header always unset X-Powered-By
120+
</IfModule>
121+
122+
# ------------------------------------------------------------
123+
# MIME types (in case host is missing any)
124+
# ------------------------------------------------------------
125+
<IfModule mod_mime.c>
126+
AddType application/manifest+json webmanifest
127+
AddType image/svg+xml svg svgz
128+
AddType font/woff woff
129+
AddType font/woff2 woff2
130+
AddType image/webp webp
131+
AddType image/avif avif
132+
</IfModule>
133+
134+
# ------------------------------------------------------------
135+
# Block access to sensitive files
136+
# ------------------------------------------------------------
137+
<FilesMatch "(^\.|\.(env|git|gitignore|gitattributes|md|json|lock|log|sh|bak|swp|dist)$)">
138+
Require all denied
139+
</FilesMatch>
140+
141+
# Allow site.webmanifest and robots.txt explicitly
142+
<Files "site.webmanifest">
143+
Require all granted
144+
</Files>
145+
<Files "robots.txt">
146+
Require all granted
147+
</Files>

0 commit comments

Comments
 (0)