, 3 min read

Hosting Static Content with Neocities

I wrote about hosting static sites on various platforms:

  1. Hosting Static Content with surge.sh
  2. Hosting Static Content with now.sh, now.sh renamed themself to vercel.app
  3. Hosting Static Content with netlify.app
  4. Hosting Static Content with Cloudflare

This short post documents how to upload static content to Neocities. A Wiki article on Neocities is here. Neocities currently hosts more than 600,000 websites, as of July 2023. There are two plans in Neocities: a free one with 1 GB of storage and 200MB of bandwidth. A paid one with 50 GB storage and bandwith of 3,000 GB, see supporter.

For the installation process see The Neocities CLI. Certain file types are not allowed in Neocities, see Currently Allowed File Types. For example, you cannot upload C program texts or mp4-files, see below for an example in the log-output.

1. Ruby. First install Ruby, if you haven't done so before.

pacman -S ruby

This will install roughly 25 MB including a number of dependencies.

Then install neocities Ruby script via

gem install neocities

This will install the Ruby neocities script in ~/.local/share/gem/ruby/3.0.0/bin.

The neocities command line provides below subcommands:

  | ~_O |   Neocities

    push        Recursively upload a local directory to your site
    upload      Upload individual files to your Neocities site
    delete      Delete files from your Neocities site
    list        List files from your Neocities site
    info        Information and stats for your site
    logout      Remove the site api key from the config
    version     Unceremoniously display version and self destruct
    pizza       Order a free pizza

2. Login. The first time you access Neocities you are asked for sitename and password. The api key for your site is stored in ~/.config/neocities/config. For example, the first time you issue

neocities list /

you will be prompted for your credentials.

3. Upload. Assume all your files are located in /tmp/build including images, PDFs, JavaScript and CSS, then run

$ cd /tmp/build
$ time neocities push .
 . . .
Uploading pdf/mb3_d6-4-report-on-application-tuning-and-optimization-on-arm-platform.pdf ... SUCCESS
Uploading pdf/md4c.c ...
ERROR: pdf/md4c.c is not a valid file type (or contains not allowed content) for this site, files have not been uploaded (invalid_file_type)
Uploading pdf/meijaard2007.pdf ... SUCCESS
Uploading pdf/ms-oxoab.pdf ... SUCCESS
Uploading pdf/peerj-preprints-826.pdf ... SUCCESS
Uploading pdf/sc11-unrolling-parallel-loops.pdf ... SUCCESS
Uploading pdf/shuttle_primary_computer_system.pdf ... SUCCESS
Uploading sitemap.html ... SUCCESS
Uploading sitemap.xml ... SUCCESS
        real 1184.54s
        user 4.18s
        sys 0
        swapped 0
        total space 0

So uploading my entire website excluding content from Koehntopp, Dr. Vonhoff, Paternoster, Mobility, and Dr.-Ing. Humpich took almost 20 minutes. There is no parallelism in uploading the data. It takes almost 3 minutes to check whether all files are transferred, without actually transferring anything.

Uploading a single file goes like this:

$ neocities upload index.html
Uploading index.html to /index.html ...
SUCCESS: your file(s) have been successfully uploaded

It seems you cannot upload a symbolic link. My blog uses a couple of symbolic links, some for correcting misspellings, some for providing older content which has moved in the meantime.

4. Statistics. You can inquire usage statistics with the info subcommand.

$ neocities info eklausmeier
sitename         eklausmeier
views            408
hits             485
created_at       2019-09-28 11:25:17 +0200
last_updated     2019-09-28 19:02:34 +0200
tags             ["computer", "math", "programming"]

My Neocities account was created in September 2019, and since then it was viewed 400-times. That is no wonder, as it only contained a single index.html, which was uninteresting.

Stats on a Neocities account can be viewed at eklausmeier. Anyone can see these stats. There is no further information what these stats include, so I assume that they also include access from bots. As we know from Filtering Bots and Crawlers from Access.log 90% of the accesses are bots.