This is my new websites template named Starfall, open-sourced under the MIT License for everyone to use. https://yusarina.dev
  • HTML 70%
  • CSS 19.1%
  • JavaScript 9.8%
  • PHP 1.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-14 22:04:29 +01:00
assets New Website Versions 2026-08-14 12:39:36 +01:00
css Update to worlds Page 2026-08-14 22:04:29 +01:00
deploy New Website Versions 2026-08-14 12:39:36 +01:00
js Update to worlds Page 2026-08-14 22:04:29 +01:00
.gitignore New Website Versions 2026-08-14 12:39:36 +01:00
.htaccess New Website Versions 2026-08-14 12:39:36 +01:00
400.html Update to worlds Page 2026-08-14 22:04:29 +01:00
403.html Update to worlds Page 2026-08-14 22:04:29 +01:00
404.html Update to worlds Page 2026-08-14 22:04:29 +01:00
422.html Update to worlds Page 2026-08-14 22:04:29 +01:00
500.html Update to worlds Page 2026-08-14 22:04:29 +01:00
502.html Update to worlds Page 2026-08-14 22:04:29 +01:00
503.html Update to worlds Page 2026-08-14 22:04:29 +01:00
contact.php New Website Versions 2026-08-14 12:39:36 +01:00
favicon.ico New Website Versions 2026-08-14 12:39:36 +01:00
index.html Update to worlds Page 2026-08-14 22:04:29 +01:00
LICENSE New Website Versions 2026-08-14 12:39:36 +01:00
lore.html Update to worlds Page 2026-08-14 22:04:29 +01:00
maintenance.html New Website Versions 2026-08-14 12:39:36 +01:00
privacy.html Update to worlds Page 2026-08-14 22:04:29 +01:00
README.md New Website Versions 2026-08-14 12:39:36 +01:00
robots.txt New Website Versions 2026-08-14 12:39:36 +01:00
sitemap.xml New Website Versions 2026-08-14 12:39:36 +01:00
terms.html Update to worlds Page 2026-08-14 22:04:29 +01:00
worlds.html Update to worlds Page 2026-08-14 22:04:29 +01:00

Starfall

A static personal site template. Plain HTML, one stylesheet, one script, no no framework, and no third-party requests at runtime, fonts and icons are self-hosted, so no CDN or analytics provider ever sees a visitor.

Built for yusarina.dev and open-sourced so others can use it. Everything identifying is swappable; see Making it yours.

Design: a deep blue-black ground with a parallax starfield, accented in two colours sampled from a character illustration.


What you get

  • Home, worlds/portfolio, privacy, terms, and seven themed error pages
  • A hidden multi-act story with a puzzle chain (lore.html), delete it if you don't want one
  • A fully self-contained maintenance page that renders even when the rest of the server is unreachable
  • A PHP contact form with a rotating question challenge and a honeypot
  • Responsive, prefers-reduced-motion and prefers-contrast aware, dark-first
  • Generated Open Graph cards

Requirements

Static hosting is enough for everything except the contact form, which needs PHP-FPM and a working local MTA. Nothing else has dependencies: no Node, no build pipeline.


Setup

git clone <this repo> mysite
cd mysite

The repo ships without images (see What is not included), so add your own before deploying.

  1. Serve it. Any static host works for a first look: python -m http.server 8000
  2. Configure nginx using deploy/nginx.conf.example. Replace every example.com, then check the three lines marked ADJUST.
  3. Get a certificate: sudo certbot --nginx -d example.com -d www.example.com
  4. For the contact form: install PHP-FPM and an MTA, then point fastcgi_pass at the right socket. See Contact form.

Making it yours

Search and replace, in roughly this order:

Find Replace with
yusarina.dev your domain: appears in canonical tags, OG tags, sitemap.xml, robots.txt
Yusarina your name: page titles, nav brand, footer
hello@yusarina.com your contact address: contact.php and the legal pages

Then:

  • Content: rewrite index.html. The nav, footer and icon sprite are duplicated across pages, so a change to one needs applying to all.
  • Colour: the whole palette is CSS custom properties in the token block at the top of css/starfall.css. Change those and the entire site follows.
  • Legal pages: privacy.html and terms.html are written for a UK sole individual with no analytics and no cookies. They will not be accurate for you. Read them line by line, they name specific hosting and email providers, a retention period, and a legal basis. Wrong details are worse than none.
  • Lore: delete lore.html, js/lore.js and js/lore-data.js, plus the footer link, if you don't want an easter egg.
  • Fonts: Chakra Petch, Inter and JetBrains Mono, all SIL Open Font License. Swap the files in assets/fonts/ and the @font-face block at the top of css/starfall.css.

Structure

index.html              home
worlds.html             portfolio / gallery with lightbox
privacy.html            privacy policy
terms.html              terms of use
lore.html               hidden story + puzzle chain (optional)
maintenance.html        self-contained, zero external requests
400|403|404|422|500|502|503.html
contact.php             contact form backend
css/starfall.css        the entire design system, @font-face included
js/starfall.js          starfield, nav, lightbox, contact form
js/lore.js              puzzle chain
deploy/                 server config
assets/fonts/           woff2 subsets (latin + latin-ext)
assets/Images/          artwork, OG cards, screenshots
assets/icons/           favicon + marks

Colour

Accents are sampled from the character illustration rather than picked by eye, which is why they feel like they belong to the artwork. If you swap the art, sample your own: pull the dominant hues out of the image and use those.

Values and their WCAG contrast ratios are documented in the token block at the top of css/starfall.css. The convention is:

  • one colour for structure and navigation
  • one for identity, emphasis and live state
  • a highlight tone for small accents only
  • a decorative tone for gradients, never for text

Effects

One canvas (#starfield) and one static overlay (.atmosphere). The starfield caps device pixel ratio at 1.5, caps star count by area, starts only once the page is idle, and stops entirely when the tab is hidden.

backdrop-filter is used only on the nav. Blurring several large regions over an animating canvas re-rasterises them every frame, which is the fastest way to make a page feel sluggish on integrated graphics.


Server

The included .htaccess is an Apache artefact. If you run nginx it is never read, and everything it describes is implemented in deploy/nginx.conf.example instead. That file covers:

  • extensionless URLs, and a 301 from the .html form so each page has exactly one indexable URL
  • themed error pages
  • maintenance mode
  • security headers, with the inheritance trap documented
  • cache rules per file type
  • denials for dotfiles, deploy/, and stray .php

Never reload without nginx -t first: a syntax error takes down every site on the box, not just this one.

Maintenance mode

Create an empty .maintenance file in the document root, delete it to turn off. nginx then returns 503 with Retry-After and serves maintenance.html.

That page inlines its fonts, CSS, JS and icons, so it renders even when nothing else on the server is reachable. It also polls the origin on a backoff and reloads itself once the site answers 200.


Contact form

contact.php uses PHP's mail(), which shells out to sendmail_path. A local MTA is a hard dependency, and without one, mail() returns false and the endpoint answers 500. That is not obvious from the code, and a server rebuild silently removes it.

sudo apt install postfix           # "Internet Site", system mail name = your domain
ls -l /usr/sbin/sendmail           # must exist, this is what mail() calls
sudo tail -20 /var/log/mail.log    # the real diagnostic; look for status=sent

Three things have to line up, and each fails differently:

symptom cause
200, application/octet-stream no PHP block in nginx: the source is being served
502 PHP-FPM socket path wrong (ls -l /run/php/)
500 PHP ran, mail() failed, usually no MTA installed

Test CLI mail before testing the form, so you are debugging one thing at a time.

Known limitations

  • The challenge answer is only verified client-side; contact.php checks the field is present, not correct. A direct POST bypasses it. The honeypot is the only server-side spam check. Harden this if you get abuse.
  • Mail is sent as noreply@yourdomain. If it bounces, check that your SPF record authorises the sending IP and that reverse DNS matches.

What is not included

The MIT licence covers the code. It does not cover artwork, so a fresh clone renders with missing images, which is intentional, not a bug.

Gitignored the character illustration and its generated variants, the OG cards that composite it, screenshots, third-party marks, the live server config, and .maintenance (committing that would 503 the site on next deploy).

Fonts are included, all three are SIL Open Font License and freely redistributable.


Notes

  • Error pages and the lore page are noindex and excluded from sitemap.xml
  • robots.txt allows search/answer AI agents and blocks training crawlers; adjust to taste

License

MIT for the code. See terms.html for the distinction between the code and the site content.