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 |
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.
Choose what the site will be about
Create at least two pages on the site (Does the homepage count as a page?)
Include at least one form on the site
The site should be responsive, and it should work well and look good on different devices and browsers
The site should have validated and correct code, and it should be written with correct indentation (Errors should be noted and explained here)
Use at least one image on the site (Does the logo count? Do users' profile pictures count?)
Add the ability to edit and delete posts
Add the ability to edit, delete, and archive topics
Add a "login-token" that is stored in the cookies of users' browsers, and allow users to choose whether to stay logged in or not
Add proper email verification, with a limit of one account per email (like the one account per username limit)
Add a safeguard for the "delete account" page (so you cannot be sent there by a hyperlink and have your account deleted)
Add a cookie notice
Allow users to set their public userpage to private, so only the most basic information about the user is shown (such as username and profile picture)
Allow users to set a bio/description for topics
Allow users to set a bio for their account
Create a basic layout
Create the actual forum
Disallow creating posts and threads for accounts with unverified emails
Force users with "legacy" accounts (no email) to register an email
Fix issue where users are unable to register an account due to an SQL error
Make the "Account Has Been Deleted" page use something other than a modal (so it doesn't require JavaScript to display)
Update all old SQL queries so they are more secure
Update the Privacy Policy to reflect the recent changes with cookie collection and email usage (Feels like this is necessary as I am going to maintain this after my web development course has finished)
Write a Terms of Service (Feels like this is necessary as I am going to maintain this after my web development course has finished)
Add the ability to use simple markdown formatting in posts (Italic, Bold, Bold Italic, - Unordered Lists, 1. Ordered Lists, Hyperlinks, etc.)
Add the ability to link directly to posts with permalinks
Add user-searchable tags or categories to topics
Add attributes to users, such as "administrator"
Add a page which parses and displays this README.md file
Add a modal or page which acts as a guide for how to format your messages (such as how to do markdown and LaTeX formatting), also notifying the user of which functions are disabled
Add a notice that you will have a worse experience on the site without JS if the user does not allow (or cannot use) JavaScript
Add a preview toggle when creating posts so you can see how your formatting looks before posting it
Add an admin panel
Add an anonymous chat section where anyone can create posts, but with limited features (for example no markdown parsing).
Allow changing your preferred timezone that is used when displaying posts
Allow configuring how many posts are displayed per page with the paginator
Allow liking posts
Allow sorting topics in the topic viewer by clicking the header ("Name", "Last Post", "Created At", etc.) in the topic viewer table that you want to sort by
Allow users to pick a profile picture (not by uploading their own, there will be a selection of images to choose from)
Allow users to sign out of other sessions
Improve the public-facing userpages by making them more aesthetically pleasing, informative, and customizable
Link to the public-facing userpages from posts
Optimize the site so it gets a green total score on Google PageSpeed using the mobile mode (optional, but would be nice, save this for last)
Optimize the SEO for the site
Pick a style for the site
Make it so that you submit forms by pressing Ctrl + Enter
Make the code more easy for others to use
Move commonly used functions to their own files
Move all modals to a "modals.php" file
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.
clone this repo: git clone https://github.com/mrblomblo/website-forum.git
Rename "config-template.php" to "config.php", and fill in the variables and the Brevo API key.
Edit "sendmail.php" and change all references of "Blomblo", such as my online alias and email addresses, to your own details.
Edit "header.php" and change the website title to what you want.
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)
Install some composer packages, you do this by running composer install in the terminal while in the same directory that "composer.json" is in.
Create a database. More instructions regarding this will come at a later date.
The forum should now be functional after completing the above steps.
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.
This section covers the content of the site, such as your user account, the forum itself, etc.
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.
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=
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.
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.
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.
(Leave this section alone until I am done with the site!)
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.
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!
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!
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.
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.
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.
For the anonymous chat, I can make it so that a random string of numbers and letters are generated and stored in the session.
The string will be used as the suffix for the "Anon-" name that everyone will have (for example: "Anon-rgt18c8hlg" & "Anon-j9r4kb3cc0"), as well as the seed for a color generator which will display the username in a unique color so users are easily differentiated.
The following sites seem to have good examples of cookie notices I can use: 1, 2
I have found a Markdown parser called "Parsedown", which seems to be recommended by many people for its robustness and speed. I will try to use it for the forum posts, along with the page that displays this README.md file.
Perhaps display which users have liked a post (and add a setting that allows you to turn off displaying your name in said list).
Email verification could be done by generating and temporarily storing a 6-digit number and then sending it to the provided email. After verification, it should be deleted.
Also allow users to generate a new code after 1 minute, if the user does so then delete the old code from the database.
Move usernames in posts to the card header, and remove the footer for posts not created by the currently logged-in user. If a post has been edited, there should be a text on the right (end) in the header that says "Edited:
Posts created by the logged-in user should have the footer, where two buttons will be visible, one for editing the post, and one for deleting the post.
Account deletion could be made more secure by having the user enter their password in a textbox in the modal that pops up.
It could be made near impossible (or at least very difficult) to delete someone else's account by sending them to the /user/delete-account page. I think I could do this by randomly generating and temporarily storing a large number in the user's session after clicking the "Delete Account" button in the "Are you sure" modal. That number can then be sent to the /user/delete-account page with POST, and be compared to the number in the session.
If the numbers match, the account is deleted. If they don't match, you get shown a notice that tells you that someone probably tried deleting your account. It also tells you that if it actually was you that tried deleting your account, you can enter your password and press "Delete Account".
When looking at another forum, I see that they have formatted the URL like this: "/
I want https://forum.blomblo.com/user_profile.php?id=40986 to be = https://forum.blomblo.com/users/40986, but I can't find a way to do it (I have tried using the .htaccess file to make the /users/ page an alias of the php file)