There is no build step, no Node, no database and no PHP. It is HTML, one CSS file, one JS file and some images. If you can upload files, you can host this.
Upload everything inside template/ into your web root. Not the template
folder itself — its contents.
public_html/
├─ index.html
├─ guides.html
├─ 404.html
├─ favicon.ico
├─ robots.txt
├─ sitemap.xml
├─ .htaccess
└─ assets/
Load your domain. That is the whole install.
Any of these work, and the first three are free.
Free, fast everywhere, HTTPS included, and it will not fall over when your server gets popular.
- Push
template/to a GitHub repository. - Cloudflare dashboard → Workers & Pages → Create → Pages → Connect to Git.
- Build command: leave empty. Build output directory:
/. - Deploy, then add your domain under Custom domains.
There is nothing to build, so builds cannot fail.
Drag the template folder onto https://app.netlify.com/drop. That is the
entire process. Add a domain afterwards under Domain settings.
Push template/ to a repository, then Settings → Pages → Deploy from a
branch. Works, but be aware it does not read .htaccess, so /guides will
not work as a shortcut for /guides.html.
Upload the contents of template/ into public_html over FTP or the file
manager. .htaccess does the rest.
Two things people miss:
-
.htaccessstarts with a dot, so most FTP clients hide it. Turn on "show hidden files" or it silently never gets uploaded. -
Some hosts serve
.webpas a download instead of an image. If your backgrounds do not appear, add this to.htaccess:AddType image/webp .webp
Do not host it on the same machine as your FiveM server if you can avoid it. A website getting traffic and a game server holding 128 tick-rate connections want different things from a CPU, and the game loses.
.htaccess is an Apache file and nginx ignores it completely. The equivalent:
server {
listen 443 ssl;
server_name yourserver.com;
root /var/www/yourserver;
index index.html;
# /guides works as well as /guides.html
location / {
try_files $uri $uri.html $uri/ =404;
}
error_page 404 /404.html;
# A year on things whose names change when they change.
location ~* \.(webp|png|jpg|svg|ico|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# An hour on the things you edit.
location ~* \.(html|css|js)$ {
expires 1h;
}
gzip on;
gzip_types text/css application/javascript text/html image/svg+xml;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}A checklist, in the order things get forgotten.
- Replaced every
deathm.exampleURL — there are some inindex.html,guides.html,robots.txtandsitemap.xml. Search the folder fordeathm.exampleand you will find all of them. - Replaced
https://discord.gg/your-invitewith your real invite. - Replaced the logo at
assets/img/logo.webp. - Made an
og-image.jpgat 1200×630 and put it inassets/img/. This is the picture people see when your link is pasted into Discord, and without it they see nothing. - Changed the title and description in
<head>. - HTTPS works and
http://redirects to it. - Opened it on an actual phone.
Deliberately not enabled by default: the pages load fonts from Google and use
inline style attributes, so a policy tight enough to be worth having would
break the design on somebody else's host without explaining why.
If you want one, this matches what the template actually does:
<IfModule mod_headers.c>
Header always set Content-Security-Policy "default-src 'self'; \
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; \
font-src 'self' https://fonts.gstatic.com; \
img-src 'self' data:; \
script-src 'self'; \
frame-ancestors 'self'; \
base-uri 'self'; \
form-action 'self'"
</IfModule>'unsafe-inline' for styles is required because the markup uses inline style
attributes for the background filters. Removing them means moving about twenty
declarations into the stylesheet — worth doing if a policy matters to you,
unnecessary for most servers.
The pages fetch Oswald and Inter from Google. That is one extra connection on first load, and in some jurisdictions people prefer not to send visitor IPs to Google at all.
To host them yourself:
- Download both families from https://fonts.google.com, or use
https://gwfh.mranftl.com which gives you the
woff2files and the CSS. - Put the
woff2files inassets/fonts/. - Delete the three
fonts.googleapis.com/fonts.gstatic.comlines from the<head>of each page. - Add your own
@font-facerules — either in a small<style>block or inbuild/input.cssif you are recompiling.
Use font-display: swap, or the page renders with invisible text until the
fonts arrive.