Advanced Trivia App


Updated Jun 16th, 2022

CRUD for custom questions: requires database and user auth for super admin.

Can create different master lists by subject. Send people to these individual sites. Stoicism, Harry Potter, Web dev, Sports, Etc. People share the site with there friends. Leave tips so we don’t have to monetize with ads. This strategy is different than having one master site with all these individual topics.

Admins can help Super-Admins add to master trivia question list. Requires user-auth for registered users, admins, and super admins so three total.

Another strategy is to let registered users create their own list of trivia questions. Take quizzes with these questions share links to them. User can see their dashboard with no questions. User can CRUD own questions. User gets custom trivia page. User can browse master list of trivia questions created by admins and easily add to their own list User can export list of questions in CSV format.

CRUD on Questions

Questions and categories are needed for the quiz themselves. This is read access and simple.

The real magic happens on an admin page where we can add, view, edit and delete.

Create: Easiest ADD form. Created comps with separate pages.

Read to Admin Panel: connect to DB and find ALL or X number at a time. The challenge becomes searching without pulling all.

Update from Admin Panel: Each Q should not need its own page to edit, should just use modal instead (see quotes app and RFTROU course edit posts section for help).

Delete from admin page.

The admin page fetches items from database on page load. When changes are made, like a question is edited, we need to update the UI to reflect the changes live. On page reload we want the data to persist instead of separate database call so use local storage right?

Generating Quizzes on HomePage

Read from API: simple, API route connects to DB and responds with 5 random. Gets more difficult when trying to customize results via inputs for things like number of questions, category, and difficulty.

Dynamically select number of questions and the category. Difficulty is another option to implement later.

The drop-downs dynamically updating the query string is rather simple.

Do we need an API route for each (seems inefficient) or can we pass the data from the query string into the function that grabs the questions from the database?

My ideas that just have select drop-downs for number and category and these selections get passed as arguments to the function that gets the questions from the database. Inside this function It uses these parameters to dynamically change the MongoDB aggregate operation. Number of questions would be the easiest one to implement first. Start with the default value of 5 or 10.

GET request versus GetStaticProps

My current implementation of fetching questions is to send a GET request using fetch as if it was a 3rd party API. This make the passing of parameters to the getQsFromDB function impossible. Option #1 is to go back to the getStatic props functions with router.replace implementation to pull fresh data in GSP without refreshing entire page. Option #2 is to use URLSearchParams but not sure how this affects the “api page routing” meaning does “/api/questions?amount=11” still ping “/api/questions” route?

Router.pathname, Router.query and in api routes, req.query


Interesting that opentdb uses input of type that accepts any number instead of select option. Here is an example querystring:

They have this API query generator tool but clearly they don’t have a route for every possible combination. They likely extract the data from the query using something like URLSearch Params, (more info here).

Query Path versus Query Parameters

Path parameters are dynamic parts of a path. These are denoted with a colon before the question mark.

Query parameters are different information that you give when calling the resource. Not part of the path itself. Denoted after the question mark. Can have multiple query parameters separated with an ampersand. Looking at the example api, they have mapped categories to a number. Access these values with “req.query” as seen in this video and this post.

app.get('/profile', (request, response) => {
  let name =
  if(people[name]) {
  } else {
    response.json({message: "not found"})

If I ping “/api/questions?category=sports” and in my api handler I have “console.log(`Query: ${req.query.category}`)” I get a result of “sports.”

To take this a step further, if I add the following code I get the expected result:

if (req.query.category === "sports") {
      console.log("True Story")

So we could just chain some if statements to have a different response based on the query parameters sent.

Users Take Quizzes with Random Questions From Master Questions

Users Take Quizzes with Random Questions From Their Own Questions

Users Create Quizzes with Fixed Questions

Let users: Create quiz with the same set of questions that they can share and invite others to take and they can compare results with other users. Leaderboard.

Advanced: Multiple Categories Allowed in Quiz

Not just all or single category, (example: CSS, JS, and React categories but not NextJS and Redux categories).


A quiz or a trivia game should be made up of a deck or a combination of decks.

A quiz or game can contain a singular topic or multiple topics.

Unlimited decks with recurring subscription or or one time fee. Share revenue with deck users depending on use.

Decks are made up of cards. A deck needs a topic and an author.

Put the App on Blockchain

The primary idea here is that if we want to have as many decks to review as possible and show results as a proof of ability/results then the blockchain would be a good idea here.

If a user creates a deck and that deck becomes very popular then they should share in the revenue from the users who buy and use the deck.

The app should keep a portion as the rails to the concept application whatever you want to call it but a certain percentage of the revenue should go to the deck author.

Handling Categories

This was not as easy to implement. In order to select a category you need to know what the categories are and without looping through all questions in the database. So my solution was to create a separate categories collection which meant I needed a way to add categories so I created a new component. Easy enough.

Then you need a database call to get all the categories and show the select options. Once they are shown and a user selects one you need to customize the query string to get the questions by adding the selection to the query parameter and do so in a way that keeps the “all functionality”

Another consideration was how to handle a category which has less questions than the number selection. A conditional check uses the number of questions if that is lower than the number of questions.

Is a way to handle a lot of these db issues to just load all questions into state on load?

Is there a URL encoding/de-encoding procedure?

What should happen to the questions in a category when the category is deleted?

If we delete a category do we want all question with that category to be deleted or converted to “random” or “uncategorized?” We could also give the user and option in the modal. Are you sure, cancel, confirm and delete all questions, confirm delete but keep questions with category set to “X”


A new category cannot have the same name as one that already exists