Introduction

This is my "slutprojekt" or final project (though, if I finish early, I'll probably make something else after it) in my web development course, and I have chosen to create a forum without using a CMS. I've wanted to have my own forum for a while, but I didn't want to use WordPress (I know there's more than just that) as it's quite slow, bloated, and uncustomizable.

The reason I chose to create a forum is that I want to have a place where viewers can discuss my videos, as well as other general topics such as music, etc.

I am writing it with pure HTML, PHP, and JS. As for styling, I use Bootstrap for its simplicity and ease of use, but I have styled it a bit with CSS so it looks better as I really don't like the default colors that are provided (and so that my site doesn't just look like "yet another Bootstrap" site). I am trying to use as little JavaScript as possible because I want people with security/privacy-hardened browsers to be able to use my site with as few issues as possible.


Items after a "" are a section, items after a "——" are subsections of the section above them, and so on. Table of Contents
Intro
To-do List
—— Mandatory
—— Important
—— "Optional"
"Usage Instructions"
Site Styling
Site Content
—— Forum
—— Account
——— Persistent Login
Use of AI
Problems
Improvements
General Info
—— Validation Errors
—— Testing
—— Image Optimization
Milestones
Notes to Myself

To-do List

This to-do list covers the things that I need (or want) to do.

Items under the "Mandatory" heading are required by my web development course, and the items under the "Optional" heading are not required, but still important (though not as important as the items under the "Important" heading). Items that are extra important, but not required by the course, go under the "Important" heading.

Mandatory

Important

Less Important


Usage Instructions

This section covers how to deploy this website.

It is assumed that you already have a Brevo account with an API key (I currently have no plans to support other services). As of now, this is a requirement, but I may add a toggle for mail functionality in the future.

You should also have a working php install, along with composer. You should also have Apache or Nginx setup.

  1. clone this repo: git clone https://github.com/mrblomblo/website-forum.git

  2. Rename "config-template.php" to "config.php", and fill in the variables and the Brevo API key.

  3. Edit "sendmail.php" and change all references of "Blomblo", such as my online alias and email addresses, to your own details.

  4. Edit "header.php" and change the website title to what you want.

  5. Do a case-insensitive search in all files for any remaining references to "Blomblo", "Mr. Blomblo", "Mr Blomblo", "blomblo.com", "mrblomblo.com", and "forum.blomblo.com" (or, if you are able to, do a regex search for "*blomblo*"). Then replace those references with your own. (I may add a global variable in the "config.php" file where you can change this very easily)

  6. Install some composer packages, you do this by running composer install in the terminal while in the same directory that "composer.json" is in.

  7. Create a database. More instructions regarding this will come at a later date.

The forum should now be functional after completing the above steps.


Styling

I use Bootstrap (my first time using Bootstrap), which I have styled quite a bit as I don't like the default colors at all. I also styled it so it would have a look that is at least somewhat consistent with the rest of my sites I made in the web development course. This is also the first time that I am using CSS variables, which I highly recommend everyone to use, as it makes the styling process so much easier and more intuitive.

One of my biggest reasons for choosing Bootstrap is that I have already showed my teacher that I am able to build aesthetically pleasing and responsive sites by hand, so I thought that it would be okay to try something else now (I also picked it to save time on the styling and layout of my site).

To be honest, I have probably styled Bootstrap in the wrong way, as I have read a lot about bootstrap using something called "SCSS". But I just themed it the good 'ol way with CSS.

A small, but very aesthetically pleasing thing I did, is to make sure that pages always take up at least 100% of the viewport's height. This is so the footer is always grounded to the bottom of the page. I did that on this site, and it makes a big difference in comparison to my school site and my first site where I don't have it!

I've also made posts animate in to view when you are scrolling, which has significantly improved the feel of the site. I have of course made it play nice with people who have disabled JavaScript and/or those who prefer reduced motion. I may do it for the thread list in the forum as well.


Content

This section covers the content of the site, such as your user account, the forum itself, etc.

Forum

This site is a forum, but as of the 21st March, 2025 I only have a "Comments Section", which I largely ripped straight from the Guestbook project on my school site. I use it as a testing ground for new features, and it will be archived and viewable as a thread after I have created the actual forum. The biggest upgrade to this new comments section over the one in the Guestbook is that this one is paginated. I currently have 25 posts per page, but I want to make it configurable in the future.

Account

You create an account with an email, username, and password. The password has reasonable restrictions, and you can't have the same username as another user. I already have a spam email domain filter, but I'm also going to have a limit of one account per email to make spam more difficult. Though, I've yet to implement any form of email verification.

When logging in, you have the choice of either only staying logged in for the duration of the session, or for 3 years (or until you clear your cookies).

There is a dropdown named "Account" in the navbar which either displays "Register" & "Log in" or "Manage" & "Sign out" depending on if you are logged in or not.

When you enter the Account Management page, you see information about your account such as creation date, email, unique ID, user number, etc. You can also change your username, password, and email, along with signing out or deleting your account.

There is a public-facing userpage, which is found at /users/?id=. The purpose of this page is to display basic and public information of the site's users, such as their username, forum posts, registration date, etc. Clicking a username in a forum post will lead you to this page.

How does the persistent login work?

There is a "Keep me logged in" checkbox on the page where you log in, that checkbox is checked by default to make the lives of users slightly easier.

How it works in the back-end ##### The back-end of the persistent-login system It works by generating a 16-byte "username" (the selector) and a 32-byte "password" (the actual token). The selector and a hash of the token are then stored in a table in the database, then the selector and token (not the hash of the token) are stored in a "remember_me" cookie in your browser in the "\:\" format. There is a "username" (selector) so that the whole table of persistent logins isn't being searched every time someone opens the site and isn't logged in, instead, only the rows that contain the username (selector) are searched. The reason the token is stored as a hash is so that an attacker can't breach the database and use the selector/token pairs to log into users' accounts, instead, they have to steal the pair directly from the user's cookie. Here is an example of how the selector/token pair looks like in the cookie, and how the pair looks like in the database (Note the *%3A* around the middle, that is how ":" looks after URL encoding): *Cookie (unhashed token, **can** be used to steal someone's account):* - `00be28a9dd0d344f2095c27c1783d7e0``%3A``99b3a1334115131de56c99496451b532cfffc7d3e90e2f7ff9d9832149713e94` *Database (hashed token, **can not** be used to steal someone's account):* - `00be28a9dd0d344f2095c27c1783d7e0``%3A``ffba5b1376aeff871a51540d490ed3a222bb369cbea9e041e53a37d11313a511` Note that the selector and token are stored in their own columns in the database, I only combined them here and added the "%3A" so that it would be in the same format as the cookie.

Use of AI

The only AI models I use are Claude Sonnet 3.5 and Claude Sonnet 3.7, and they have been used for the following:

Another great use that I have found for AI is for just talking about a problem or idea, which makes you think harder about it, perhaps even from a new perspective.

For example, just now I was talking to Sonnet 3.7 about the best way to generate 6-digit verification codes, and just talking helped me come up with a new idea that we both agreed is better than the other ideas I had.


Problems

This section will cover various problems that I have encountered, along with their solution if I managed to fix the problem. The problems will be sorted with the oldest at the top, and the newest at the bottom (as in when they were thought of/discovered, not actually created). This section will not cover validation errors as they can be found in their own section.

Solution: I forgot that I am using Nginx, and .htaccess is only a thing on Apache... "I" (AI) solved it by modifying the Nginx config file.

This is an issue that popular services such as Discord and Roblox have as well, and if they haven't been able to fix it, then I sure can't!

Solution: I added code that displays errors to the head.php file that is loaded on every page, which showed that I had accidentally left a call to the create token function from the login page. It also showed that I was attempting to close the SQL stmt twice. After deleting the problematic code, I tried visiting the site on a fresh session again, and there was no white page of doom.

I have yet to find a solution for this problem.

Solution: When logging in and having "Keep me logged in" checked, it now only deletes token/selector pairs that have expired (those that are older than three years), not all other pairs.

Solution: I had previously created a completely unnecessary trigger in the SQL configuration, which also was the cause of the issue. Removing it fixed it.

I have yet to find a solution for this problem.

Solution: After around 30 minutes of searching on the internet, asking my teacher, and asking AI, it was found that downgrading the PHP version from 8.3 to version 8.2 fixed the issue. Why? I have no idea.

I sat here for literally an hour looking for solutions, but I am utterly incapable of finding one that works.

Solution: Change all instances of "cookieNotice" to "cookieNoticeDoNotDetectByCookieBlocker" so it doesn't get styled in a way I don't want it to be styled (as well as making it more difficult for those who block cookie notices).

Solution: Add a check in the comment-saving logic that compares the amount of characters present in the message with the character limit variable (cannot, to my knowledge, be bypassed by users).

Solution: Change (for example) .link-danger to .link-danger, .link-danger:visited, .link-danger:focus in the CSS file.

Solution: I had forgotten to changed the time-handling to unix-time after updating the DB and all other forms of time-handling to it. The previous "solution" did not fix it. It seems to have been fixed by naming the session.

Solution: Update the logic for setting the cookie.


Improvements

(Leave this section alone until I am done with the site!)


General Info

I am trying to use as little JavaScript as possible so that users with more privacy-hardened browsers (such as those using the NoScript extension) can use the forum with as few issues as possible. Trust me, I know from experience that it is annoying when sites use JS for more than is needed (looking at you, React sites).

I have created 15 different standard profile pictures that are based on the Catppuccin Mocha theme (like the whole site). I've also generated 15 more expressive profile pictures with AI because I'm not an artist, and I don't want to pay someone for profile pictures.

All data on the forum is stored in a MySQL database. User's passwords and persistent session tokens are stored hashed using PHPs native hashing function.

Why did I wait so long to create the actual forum? I waited because I wanted to have more experience with PHP and SQL so I would make less mistakes, and to make life easier for me. I used the Comments Section as a "playground" or "sandbox" to test features and stuff before deciding it was good enough to copy to, and adapt to the forum topics.

Validation Errors

This subsection will cover any validation errors that have to stay, along with the reason for me not fixing them.

There is an error in the console that warns you about an aria-hidden thing. It only seems to show up when the cookie notice is shown, and does not show up in sessions where you don't ever see the cookie notice.

I have yet to do any HTML or CSS validation, check back later!

Testing

When testing the site, I use the following browsers:

A classmate who uses Opera GX has noticed problems when trying to open the site (it does not open at all, returning an error about the SSL certificate), but I don't know if there is some conflict with the school's network and Opera GX, or if it's something else. Either way, I am not installing that pile of garbage that tracks you just so I can test my site with it as well. I did however make some changes to the SSL configuration, which I hope fix the issue.

While I'm in the testing phase, and especially while editing the CSS of the site, I append "?v=" to the filename of the styles.css file. This makes sure that a cached version of the file isn't being used, which means that you are always served the newest version. This is especially important because I use CloudFlare's caching (which turned off on the 13th of April, 2025) along with PageSpeed to improve the speed of my site along with slightly lessening the load on the server.

I also test it using several different sizes and resolutions, most frequently with a 6.5" 9:21 4K smartphone, a 14" 16:9 FHD laptop, and a 28" 16:9 4K monitor, but I may use othe configurations as well!

Image Optimization

I have optimized all images with the help of GIMP, where I have either scaled them down, converted to WebP with a lower quality (likely 80%), or both. For the profile pictures, I have scaled them to 256x256px and made them WebP at 80% quality.


Milestones

This section covers milestones and other changes done to the site. It may be a bit long, so click here to skip to next section.

2025, 23rd of May

2025, 22nd of May

2025, 16th of May

2025, 15th of May

2025, 14th of May

2025, 13th of May

2025, 11th of May

2025, 10th of May — The Profile Picture Day

2025, 9th of May — A Very Productive Day

2025, 8th of May — The Better Forum Day

2025, 7th of May

2025, 2nd of May — The Forum Day

2025, 23rd of April

2025, 18th of April

2025, 17th of April

2025, 13th of April

2025, 10th of April

2025, 6th of April

2025, 4th April

2025, 3rd April

2025, 28th March — The Mail Day

2025, 27th March

2025, 26th March

2025, 23rd March

2025, 22nd March

2025, 21st March

2025, 20th March

2025, sometime between 24th of January and the 20th of March

2025, 24th January


Notes to Myself

These notes are meant to be readable by me, and may seem a bit unstructured or "ramble-y" to others. Notes that have no use anymore will be marked with strikethrough.