For a while now I’ve been meaning to make my own website. In other ocasions I’ve designed what my “ideal website” would look like but I’ve never taken it in to actually uploading my site to the internet.
Until now >:)
A few months ago I discovered Neocities, and after registering myself I now have my own plot on the internet! (You’re currently stepping on it)
Ok but how?
Before diving in to the HTML & CSS, I had to decide what tools to use for my site, they needed to be simple and easy for use and updating. After looking at the options Neocities recommended, I found about Hugo and got to investigating.
Hugo is a static site generator that transforms the content written in Markdown files (a markup simple language that you may have seen as README.md files) into HTML. This is so you don’t have to worry about all the nitty gritty details that come from actually organizing your content.
At least in the ideal world.
As it turns out Hugo doesn’t have a great guide for new users; yes it does have the documentation but in some spots it’s confusing. To build a website in Hugo the documentation assumes you already know Hugo’s concepts, and to learn the framework’s concepts you need to experiment with Hugo beforehand. Yes what I’ve described is circular reasoning.
The Process
Step 1: Get a space in neocities and register it under my username. That was easy.
Step 2: Figure out how what can be used to easily upload content to neocities’ dashboard, because I don’t want to manually set everything myself. Hugo was recommended so I used that.
Step 3: Figure out how Hugo actually works. This took the longest because of what I’ve described earlier. The initial commit took place on Aug 25th, 2024. I may describe how Hugo works and how you can make a website of your own in a future post.
Figuring out how to format HTML and Markdown files so Hugo is happy with them was the hardest part, but from then on I could easily arrange the HTML how I wanted using CSS.
Step 4: Figure out how to deploy the files generated by Hugo in the /public
directory. More on that in the following section.
How did I actually deploy it?
Excelent question! I used a similar methodology to neonaut, who was also developed their Neocities site using Hugo. But instead of using Python as my site pusher, I’ll use Javascript and NPM to make shortcuts for my commands.
Neonaut’s method was using a python file that uses Neocities’ API to recursively upload the files in the /public
directory, so I followed suit with this file I made:
require("dotenv").config();
const NeoCities = require("neocities");
const fs = require("fs/promises");
const path = require("path");
const { NEOCITIES_USER, NEOCITIES_PASS } = process.env;
const nc = new NeoCities(NEOCITIES_USER, NEOCITIES_PASS);
function neocitiesUploadAsync(files) {
return new Promise(function (resolve, reject) {
nc.upload(files, function (resp) {
if (resp.result != "success") {
reject(new Error("Got an error uploading file"), resp);
} else resolve(resp);
});
});
}
/**
* Thank you so much for Neonaut's code solution!
*
* https://neonaut.neocities.org/neocities/#using-python-to-upload
* @param {string} dir Directory to upload
*/
async function pushDir(dir) {
const directory = await fs.opendir(dir, { recursive: true });
for await (const entry of directory) {
if (entry.isFile()) {
// Path that will be uploaded file to
const namePath = path
.format({
base: entry.name,
dir: entry.path.replace("public", "/"),
})
.replaceAll("\\", "/");
// Relative path in my computer from this file
const filePath = path.format({
base: entry.name,
dir: entry.path,
});
neocitiesUploadAsync([
{
name: namePath,
path: filePath,
},
])
.then((resp) =>
console.log(`✅ ${namePath} uploaded successfully`)
)
.catch((err, resp) =>
console.error(`❌ ${fileData.name} ${resp}`, err)
);
}
}
}
pushDir("public");
For those who know something about programming you see that I have two dependencies here, the dotenv
library and the neocities
client API. I also use the function neocitiesUploadAsync
to convert the API into something that uses promises.
The most important piece of code is the creation of the fileData
variable you can see in the for await
loop, which is an object with two properties:
name
: The name of the file that will be uploaded and how it will show up in neocities. Since I’m taking from the root level of the project, I first need to remove thepublic
prefix from the path first.path
: The path of the file to upload, relative to the JS file.
This is the package.json
that I have as of writing this post:
{
"name": "kfcmanwebsite2",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "hugo server --noHTTPCache -D",
"upload": "hugo & node upload-site.js"
},
"dependencies": {
"dotenv": "^16.4.5",
"neocities": "^0.0.3"
}
}
So when I want to upload content to my site, I only run on the command line:
npm run upload
And this is what I get as a result:
> kfcmanwebsite2@1.0.0 upload
> hugo & node upload-site.js
Start building sites …
hugo v0.129.0-e85be29867d71e09ce48d293ad9d1f715bc09bb9+extended windows/amd64 BuildDate=2024-07-17T13:29:16Z VendorInfo=gohugoio
| EN
-------------------+-----
Pages | 17
Paginator pages | 0
Non-page files | 0
Static files | 4
Processed images | 0
Aliases | 0
Cleaned | 0
Total in 80 ms
✅ //tags/hugo/index.html uploaded successfully
✅ //posts/index.html uploaded successfully
✅ //index.xml uploaded successfully
✅ //tags/random/index.html uploaded successfully
✅ //tags/programming/index.html uploaded successfully
✅ //styles.css uploaded successfully
✅ //categories/index.html uploaded successfully
✅ //categories/index.xml uploaded successfully
✅ //sitemap.xml uploaded successfully
✅ //tags/pai-sho/index.xml uploaded successfully
✅ //posts/index.xml uploaded successfully
✅ //posts/2024/journey-to-creating-a-website/index.html uploaded successfully
✅ //images/kfcman wave high 2.png uploaded successfully
✅ //tags/index.xml uploaded successfully
✅ //tags/neocities/index.xml uploaded successfully
✅ //images/pattern.png uploaded successfully
✅ //index.html uploaded successfully
✅ //tags/pai-sho/index.html uploaded successfully
✅ //tags/index.html uploaded successfully
✅ //tags/hugo/index.xml uploaded successfully
✅ //js/events.js uploaded successfully
✅ //tags/random/index.xml uploaded successfully
✅ //tags/programming/index.xml uploaded successfully
✅ //images/kfcman wave low 2.png uploaded successfully
✅ //tags/neocities/index.html uploaded successfully
✅ //posts/test-post/index.html uploaded successfully
✅ //about-me/index.html uploaded successfully
And just like that my site is deployed!
Some stuff will change as I develop my site more, of course. But they this is how I got this stuff running!
…
I don’t know how to give this post a clear conclusion
EDIT 10/AUG/2024: I had to modify upload-site.js
because of bad url formatting, should be fixed now and updated