Tasha’s Trinkets
--
So far, my peers have been largely spared from my… egregious relationship with the Dungeons and Dragons tabletop roleplaying game. Yet all good things must come to an end…
This project, my fourth of my time at DigitalCrafts, is a mock ecommerce site. Its ostensible premise is that Tasha — one of D&D’s most popular characters — is selling you magic items from within the game’s fiction.
Check out the live site here or read on for more information!
The basic skeleton of the site runs on three databases: Products, which detail the so-called trinkets for sale; Customers, which detail the accounts that users make; and Orders, which link the two. Each row of all three databases has a unique ID assigned to it (automatically through Sequelize). Each row of the Orders table links the ID of a Customer with the ID of a Product.
The Products database was seeded through calling the Open5e API. (As a result, only the magic items in D&D’s Basic Rules document exist in the database — which means the magic items in Tasha’s Cauldron of Everything are unfortunately excluded from this database.) To access images, we used www.aidedd.org, which happens to host images of many magic items with a predictable URL that only needs the name of the magic item.
The Customers database is modified by the creation and deletion of the accounts of customers via the live webpages when the server is running. Similarly, the Orders database is modified by users adding or removing items from their carts.
To get this project up and running on your own machine, you’ll need any application that allows you to start and view a server (such as Nodemon) and npm. Next, fork the project’s GitHub repo and clone a copy onto your local files. Once inside the project’s directory, you’ll need to run the following command in your terminal:
npm i
This will download all dependencies. Next, you’ll need to set up a database and configure your connection to that database. In the file sequelize/config/config.json, you’ll need to paste something of the form:
{
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
We used ElephantSQL as our online database using the dialect postgres. The values for the keys username, password, database, and host will vary based on which service you use, but for ElephantSQL, you can find these details in the ‘Details’ section as ‘User & Default database’, ‘Password’, ‘User & Default database’, and ‘Server’, respectively.
Next, you’ll need to migrate the database’s tables. This will set up the necessary tables in your database with the information in this project’s ‘models’ file. Navigate your terminal into the ‘sequelize’ file, then run this command:
npx sequelize db:migrate
Now that your database is populated, you’re ready to start the server and view the live site! Simply type ‘nodemon’ in your terminal at the root of the project and open ‘http://localhost:3010/’ in the browser of your choice.
The inner workings of this site function in three large categories: product pages, cart management, and account management. Other functions and routes of the site are trivial.
Customers have their accounts managed by the routes in ‘routes/account.js’. These are simple create (sign up), read (log in), update (update buttons on account page), and destroy (delete button on account page) routes. When logged in, a user also gets a session stored in the JavaScript variable req.session, which is managed by Express Session and available to all other routes. This session allows a user to stay logged in even after the page is closed, and it is deleted when they log out or delete their account, and it expires after two weeks. The only tricky thing here is a “log in as guest” route, which creates an account for a user (referencing some bits of Tasha’s lore) and logs them in (creating a session) all at the same time.
Product pages are managed by the routes in ‘routes/products.js’ and function by simply querying the Products database for products of a certain type — for example, the weapons page will query for all weapons, then display them using a simple JavaScript loop. During this process, each item also has its unique ID passed to a “add to cart” button above that.
The user’s cart is managed by select routes in the ‘index.js’ file at the root of this project. Products are added to the cart by the aforementioned button, which adds a row to the Orders database with the item’s unique ID (passed from the button to the route via a query string) and the user’s unique ID (taken from the session data, which is available in all routes). When the user visits the cart page, the items that they add to cart unsurprisingly populate the page. This process starts with a query to the Orders database searching for rows where the user ID on that row is the same as the current user ID in the session data. The product IDs of these rows are used in a query to the Products database, and the results of that query populate the page much in the way that the product pages are populated.
At the bottom of the cart page, a user can finalize their purchase. This doesn’t do anything though because this site is fake.
This project was completed in a little less than a week, and it was an excellent learning experience in backend functionality. I now feel much more comfortable and familiar with routes and Express Router, servers, databases, SQL, and all the logic that comes with backend.
Had we more time, we would’ve tested more strenuously and created a 404 page for unrecognized routes. We also would’ve finished things out with a more ceremonious “just kidding this site is fake” page and included more functionality in that “buy” route such as clearing the cart of the current user. Speaking of the cart, I would’ve liked to make items stack by quantity and implement buttons to entirely clear the cart or remove all items of a certain type. Overall, I think even the daughter of Baba Yaga herself would be happy with this project after only a workweek of building and learning.
Extra special thanks to Veronica Lino, who had no responsibility whatsoever to help me with this project and yet helped me squash a bug that had evaded me and others for about two hours previously.
Special thanks to Vinny for tirelessly designing this site’s frontend, adding uncountable buttons.