Frequently asked questions
Short, direct answers about RJLCustom404: what it is, what it costs, where it runs and what to do when something does not look right. If yours is not here, ask.
Still stuck?
Bugs and feature requests belong on GitHub issues. For anything else, the contact form reaches the author directly.
15 questions
What is RJLCustom404?
A free, open-source JavaScript library that renders a complete 404 page from one function call. You give it an empty 404.html, your images and a few options; it draws the heading, the sub-heading, a random image and a button back to your site, responsive out of the box, with zero dependencies.
How do I install it?
Add one script tag before the closing head tag of your 404.html, either hosted from rjl.codes or self-hosted, then call RJLCustom404({...}) with your options and put the file at your site root. The Getting started guide has a complete file to copy.
Is it really free? Can I use it commercially?
Yes. RJLCustom404 is released under the MIT license and costs nothing to use on personal or commercial sites. There is no paid tier and no registration.
How big is it?
One file, under 20 KB minified, with no dependencies and no stylesheet to load. The readable source is about 40 KB.
Does it phone home or track my visitors?
No. The library makes no network requests other than loading the images you configure. It uses localStorage to remember which images and phrases a visitor has already seen, sets no cookies, and sends nothing anywhere.
Does it work with React, Next.js, Vue or Astro?
Yes. Any framework that can output a static 404.html works unchanged. Frameworks that own the 404 route, such as the Next.js app router not-found page or a Nuxt error page, can load the script and call RJLCustom404() when that route mounts.
Does it work with a Content Security Policy?
Yes. Allow the script source in script-src: rjl.codes for the hosted file, or 'self' if you self-host. If you call RJLCustom404() from your own external JavaScript file there is no inline script to allow; if you call it inline, add a hash or nonce for that block. The library injects one style element, so style-src needs 'unsafe-inline' or a nonce.
Should I self-host the file or load it from rjl.codes?
Either works. The hosted file is free, served through Cloudflare and updated in place behind a stable URL. Self-hosting removes any runtime dependency on rjl.codes and keeps everything under your own CSP. Whichever you choose, use the guarded call with a static fallback so a blocked script never leaves a blank page.
Why is my image not showing?
The usual causes are a wrong path, a file that is not deployed, or a pattern that does not match the file names. The library shows [[ /path/to/file.png not found ]] in place of a missing image so you can read the exact path it tried. Images load like any img tag: same-origin paths, or an absolute URL from a host that serves them to your origin. There are no bundled images; you must supply your own.
Can I use my own images?
Yes, and you must. List them with imgFileNames, or use imgPattern with imgCount to generate numbered paths such as /img/404-1.png through /img/404-6.png. One is picked at random per visit and the shuffle is remembered per visitor so nothing repeats until the set is exhausted.
How do I get my hostname in the button?
It is on by default: btnDisplayHostName appends window.location.hostname to btnDisplayText, so the button reads Back to your-site.com. Set btnDisplayHostName to false and write the full label in btnDisplayText to control it yourself.
How do I style it further?
Use the options first: colors, radius, shadow, layout, button or link. For anything else, target the CSS hooks: .custom404-container, .custom404-img, .custom404-header, .custom404-subheader, .custom404-button and #goHomeLink. The library injects its stylesheet when it runs, so give your overrides slightly higher specificity, for example body .custom404-button.
Does it work on mobile?
Yes. Side-by-side layouts collapse to a single column at 768px and below, font sizes and button padding step down at 768px and 480px, and images scale to the available width. There is nothing to configure.
What browsers are supported?
Every evergreen browser: Chrome, Edge, Firefox and Safari on desktop and mobile. Internet Explorer is not supported because the source uses modern JavaScript features such as template literals and padStart.
How do I report a bug or contribute?
Open an issue or a pull request on GitHub at github.com/rjlsoftware/RJLCustom404. For questions that are not bugs, use the contact form on this site. Changes that could break existing sites are avoided; new behaviour ships as new optional options.