A Simple MERN App to Track Visitors |
---|
![]() |
This MERN app shows the visitors of my homepage at aabbtree77.github.io. To see the list, one must click on the link "Guests". There is no "R" in this application, only plain Js. This code is hosted on render.com (with a free plan) and uses a free mongodb.com account to store data. The frontend code is at https://github.com/aabbtree77/aabbtree77.github.io.
Tracking can be accomplished with Google Analytics (GA) for free, without coding. However, GA is banned in many European countries such as France, Finland, Sweden... It is not banned in Lithuania though.
MERN is ideal for this kind of a simple CRUD app. A single language (Js) on the server and client, communication with JSON, no choice-induced paralysis.
The client side Js gave me one small headache with an "async double fetch" which had to be nested.
I did not bother much with Fetch vs Axios, TanStack Query, Js vs Ts, also used ChatGPT whenever needed. Fixing Js and CSS problems with console.log() and Chrome F12 tools is a joy compared to working with OpenGL, or reading Weinberg's QFT, despite all the garbage called asynchrony, nested callbacks, and dynamic typing.
During the development, I learned from reddit that Postman API could be in the process of enshittification, and rushed to use VS Code with an extension called REST Client. The latter is simple and snappy, which I cannot say about VS Code.
The cloud shuts down the nodes with the free plan after 15 minutes of any request inactivity: 1, 2. Later on, the first request will take the whole minute or two to process (!), the things run smoothly again, until the next inactivity. This is definitely not going to be a good user experience. Concerning this web app specifically, I can wait for my personal list of guests to load, but there is no way for the free plan to work without some kind of a constant pinging.
It is not reliable with the city detection. It confuses Vilnius with Kaunas in Lithuania. Sometimes the returned city is an empty string. It is unclear if the geoip-lite database will be updated on render.com, and how often. This part needs to be totally rewritten.
There are a lot of ways to set up and manage the database. I have used two: (i) The ATLAS cloud with the online GUI in my desktop browser, and (ii) the tool called MongoDB Compass which I have installed on Ubuntu 22.04.
The online GUI occasionally is disfunctional with
"Request invalid. Please visit your Clusters and try again."
after clicking on Database -> Cluster0 -> Collections, despite the IP being whitelisted. Googling does not help much, but the error does not happen often.
MongoDB Compass solves this problem, but it is an extra desktop app with its own GUI and shell. It works well though.
Deleting multiple entries (documents) is not possible in the online GUI. In MongoDB Compass, one needs to get into MONGOSH shell, and then execute the commands such as
> db.guests.deleteMany({city:"Kaunas"})
> {
acknowledged: true,
deletedCount: 19
}
The shell does not support the right mouse click, and the selection with mouse is limited to a single line, ctrl+c works fine.
One has to be extra-careful with connection URIs. Database -> Connect gives a generic URI, but one needs to append it with a specific database (collection) name set up during the creation, which may not be visible at all due to the retrieval error indicated above. Typing this in MongoDB Compass (with a proper username and password)
mongodb+srv://<username>:<password>@cluster0.0vbktln.mongodb.net/
does not display any errors, it connects and displays the collections, but MONGOSH would not work. I had to explicitly reconnect with the collection name "guests" appended
mongodb+srv://<username>:<password>@cluster0.0vbktln.mongodb.net/guests
for MONGOSH to work.
Note the collection names, look into .env files in the server side code.
I have limited my MongoDB collection to 10MB and 200 documents (the free MongoDB Atlas plan provides a lot more, 512MB storage). This is a capped collection, the newest document overwrites the oldest one, so an attacker can only flood the server API, but it won't crash the server. The frontend is set to retrieve only 50 latest items, all at once, so it should not hang the browser. Typically, it will be less than 250KB of data to download. The log is visible to everyone as there is no sensitive data.
Mermaid diagrams are only good for tiny simple diagrams, but I would no longer use them for anything. See the figure above, the automated node placement and styling are just plain horrid. Next time I will use Excalidraw or draw.io (app.diagrams.net).
This mini web app runs for about a month continuously (January 2024). It takes one click to redeploy the newest github commit on render.com, but the free plan with cold starts is annoying. It solves the problem though, I can log my visitors.
It is not clear if MERN is the way. It feels too low level, but so do all the newest frameworks. They all lack a built-in user sign-up and a standard to code things per user. Hunting for the 3rd party authentication solutions to save time does not solve the problem.
I am looking into this self-hosted Payload CMS applied with Next.js 14 and Express now. A lot gets done in a short time, but it is not clear if this is reliable. I do not see much development on the github repository by the author (Josh) and his youtube followers. I will evaluate Payload CMS and Next.js, but most likely will stick to MERN. TBC...
I have greatly benefited from these works:
Web Dev Cody: TODO with Authentication. The React part feels rushed and convoluted, and I am not sure about authentication, but my web journey has begun with this code.
Net Ninja: TODO-I, TODO-II. The same thing, but also mildly styled and expanded. I am not sure if I should stick to pure MERN, or it should be MERN+Next.js.
EdRoh: MERN Dashboard. Shows the deployment on render.com. Unlike some other tutorials, it does not miss an important step that demands whitelisting render.com IP addresses on mongodb.com.
The following two notes belong to frontend, but I will mention them here since I do not have a separate memo about my frontend code:
Rajkumar Gaur: Beautiful Spinner in CSS.. I did not want to load any images, so this blog article solved the problem admirably. It had one bug visible when the spinner size was large. See my CSS code around "@keyframes rotate" inside spinner.css at https://github.com/aabbtree77/aabbtree77.github.io/miniguestlog, but I have also modified the way the spinner spins later on. These bugs are easy to fix with Chrome's F12 at runtime. Add a break point, click on "Elements", and then enable/disable various CSS properties while observing the result. Imagine we had such debuggability with 3D backends and Make files... I would take dynamic typing over the static any day.
Josephine Loo: How to Overlay Text on an Image in HTML and CSS. This is a useful note to center and overlay stuff. To display a loading message with a spinner, I did not go this way as it would rotate the message with the spinner. Instead, I made a separate div centered at the same place as the spinner, and then simply set a large z-index value of this message div.
MongoServerError: user is not allowed to do action [collMod].