Project 2 — Dynamically Generated Content

CS-332: Web Programming

Fall 2023

For the duration of this course, you will work in teams to develop a microblogging and social networking web application based loosely around X (formerly Twitter). In this second project, you will work in teams to add dynamic content to your user interface from Project 1. You will gain experience programming in JavaScript, manipulating the DOM, and using asynchronous fetch.

SlugFest is said to be the next hit social media site1—you just have to create it first! Members can post short messages ("slimes") for their followers to read. Members can also "favorite" slimes that they like or even "reslime" so that the post shows up on their own profile. Additionally, this is a social site, so it is possible to reply to slimes creating a "slime trail" conversation. If these features sound familiar, that's because they are based off of those supported by a popular microblogging and social media site.

You will be given a collection of JSON files containing the information for SlugFest to display. It is your job to recreate many of the pages from Project 1 using this information.

Requirements

Working in your assigned group of 4-5 students (found on Canvas), create a collection of HTML and JavaScript files that:

  • Uses Bootstrap 5 for styling
  • Implements the following pages:
    • a "home" feed page,
    • profile pages for four users (Kevin Angstadt, Ed Harcourt, Choong-Soo Lee, and Lisa Torrey),
    • a "slime trail" page showing the slime with ID 611fcaf640148d94e2a469c7 and its replies, and
    • a notification page
  • Uses JavaScript to dynamically display slime and user information on each of the pages. That is, your HTML should not contain any of the content beyond the basic structure of each page.
    • There should only be one copy of the code for generating user profiles. Do not hard-code usernames into separate JavaScript files that are identical except for usernames!
    • There should only be one copy of the code for producing a slime in user profiles and the home feed. You may need different code on the slime trail page.
  • Closely matches the styling from Project 1
  • Supports navigation between the various pages
  • Displays well on desktops, laptops, and mobile devices

Individually, you must also submit a short reflection on your contributions to and experiences with your student group.

Assets

 Download p2_assets.zip

You are provided with the profile pictures for users of SlugFest. Additionally, there are JSON files in an API (Application Programming Interface) directory. These JSON files contain structured data representing each slime as well as each user account. Skeleton HTML files are also provided, should you wish to use them (you may also use your own code).

These files may be downloaded here. The contents of this file is:

              
                unzip -l p2_assets.zip 
                (out)Archive:  p2_assets.zip
                (out)  Length      Date    Time    Name
                (out)---------  ---------- -----   ----
                (out)    3810  10-23-2023 13:54   starter-code/skeletons/feed.html
                (out)    5612  10-23-2023 13:54   starter-code/skeletons/profile.html
                (out)    2941  10-23-2023 13:54   starter-code/skeletons/notifications.html
                (out)    3046  10-23-2023 13:54   starter-code/skeletons/slime.html
                (out)        0  10-18-2023 12:02   starter-code/api/favorites/
                (out)    1013  10-18-2023 12:02   starter-code/api/favorites/ltorrey.json
                (out)    2425  10-18-2023 12:02   starter-code/api/favorites/ed.json
                (out)    2121  10-18-2023 12:02   starter-code/api/favorites/list.json
                (out)        3  10-26-2021 14:59   starter-code/api/favorites/choongsool.json
                (out)    2121  10-18-2023 12:02   starter-code/api/favorites/kevinaangstadt.json
                (out)        0  10-18-2023 12:02   starter-code/api/statuses/
                (out)        0  10-18-2023 12:02   starter-code/api/statuses/replies/
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ccd3969d515951edefac.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175cb4a969d515951edefa9.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ccf1969d515951edefaf.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ca7a969d515951edefa7.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ccbe969d515951edefaa.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ccfa969d515951edefb0.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ccde969d515951edefad.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175cce8969d515951edefae.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ccc7969d515951edefab.json
                (out)    1241  10-18-2023 12:02   starter-code/api/statuses/replies/611fcaf640148d94e2a469c7.json
                (out)    1367  10-18-2023 11:33   starter-code/api/statuses/replies/6175c92c969d515951edefa3.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175c9a2969d515951edefa4.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175cb11969d515951edefa8.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175c9e3969d515951edefa5.json
                (out)        3  11-02-2021 13:31   starter-code/api/statuses/replies/6175ca53969d515951edefa6.json
                (out)        0  10-18-2023 12:02   starter-code/api/statuses/show/
                (out)      971  10-18-2023 12:02   starter-code/api/statuses/show/6175ccd3969d515951edefac.json
                (out)    1275  10-18-2023 11:34   starter-code/api/statuses/show/6175cb4a969d515951edefa9.json
                (out)      972  10-18-2023 12:02   starter-code/api/statuses/show/6175ccf1969d515951edefaf.json
                (out)    2098  10-18-2023 12:02   starter-code/api/statuses/show/6175ca7a969d515951edefa7.json
                (out)      971  10-18-2023 12:02   starter-code/api/statuses/show/6175ccbe969d515951edefaa.json
                (out)      971  10-18-2023 12:02   starter-code/api/statuses/show/6175ccfa969d515951edefb0.json
                (out)      972  10-18-2023 12:02   starter-code/api/statuses/show/6175ccde969d515951edefad.json
                (out)      971  10-18-2023 12:02   starter-code/api/statuses/show/6175cce8969d515951edefae.json
                (out)      972  10-18-2023 12:02   starter-code/api/statuses/show/6175ccc7969d515951edefab.json
                (out)    1109  10-18-2023 11:33   starter-code/api/statuses/show/611fcaf640148d94e2a469c7.json
                (out)    1151  10-18-2023 12:02   starter-code/api/statuses/show/6175c92c969d515951edefa3.json
                (out)    2020  10-18-2023 12:02   starter-code/api/statuses/show/6175c9a2969d515951edefa4.json
                (out)    2151  10-18-2023 12:02   starter-code/api/statuses/show/6175cb11969d515951edefa8.json
                (out)    1023  10-18-2023 12:02   starter-code/api/statuses/show/6175c9e3969d515951edefa5.json
                (out)    1148  10-18-2023 12:02   starter-code/api/statuses/show/6175ca53969d515951edefa6.json
                (out)        0  10-18-2023 12:02   starter-code/api/statuses/user_timeline/
                (out)    3476  10-18-2023 12:02   starter-code/api/statuses/user_timeline/ltorrey.json
                (out)    4503  10-18-2023 12:02   starter-code/api/statuses/user_timeline/ed.json
                (out)    7327  10-18-2023 12:02   starter-code/api/statuses/user_timeline/choongsool.json
                (out)    4856  10-18-2023 12:02   starter-code/api/statuses/user_timeline/kevinaangstadt.json
                (out)    5642  10-18-2023 12:02   starter-code/api/statuses/activity.json
                (out)    20156  10-18-2023 12:02   starter-code/api/statuses/home_timeline.json
                (out)        0  10-18-2023 11:32   starter-code/api/user/
                (out)        0  10-18-2023 12:02   starter-code/api/user/get/
                (out)      572  10-18-2023 12:02   starter-code/api/user/get/ltorrey.json
                (out)      496  10-18-2023 12:02   starter-code/api/user/get/ed.json
                (out)      454  10-18-2023 12:02   starter-code/api/user/get/choongsool.json
                (out)      579  10-18-2023 11:34   starter-code/api/user/get/kevinaangstadt.json
                (out)        0  10-18-2023 11:32   starter-code/assets/profile/
                (out)  249750  09-05-2021 14:17   starter-code/assets/profile/kevin.jpeg
                (out)    79031  09-05-2021 14:20   starter-code/assets/profile/choong-soo.png
                (out)    75662  09-05-2021 14:17   starter-code/assets/profile/ed.png
                (out)    18900  09-05-2021 14:18   starter-code/assets/profile/lisa.jpeg
                (out)        0  10-18-2023 11:32   starter-code/
                (out)        0  10-23-2023 13:54   starter-code/skeletons/
                (out)        0  10-18-2023 11:32   starter-code/api/
                (out)        0  10-18-2023 11:32   starter-code/assets/
                (out)---------                     -------
                (out)  515918                     65 files
              

            

Commentary

As befitting a 300-level elective, this assignment is fairly open-ended. There is no "one true path" to creating and styling the required pages. Thus, this project requires you to tap your inner creativity and problem-solving.

Under-specification is fairly indicative of the real world. Clients will often expect you to "read their mind" to deliver a product that meets their needs. This can definitely be frustrating at times, but it is also a good lesson to learn early. It will help you be a high-quality developer who gains a positive reputation with clients.

A keen eye for detail is also key here. While there is textual description of each page provided, taking a close look at the provided images for styling and inferring withheld information can help you decide how to proceed.

As this is an upper-level course, you may use outside references to complete this assignment. Be sure to keep a running list of citations as you work on this project.

DANGER! This is a typical warning, but do not wait to get started on this project. Front load the work so that you are not scrambling to finish.

Recommended Approach

You will most certainly want to split your code into multiple JavaScript files. A good first step is to create a file for generating the HTML needed to display slimes. Note that you may need separate functions for slimes on "standard" pages vs. the "slime trail" page. One possible function interface is shown below.

              
                /**
                 * Create a Slime DOM and return it
                 * @param slimeData {object} all of the data needed to create a slime 
                 * @return a DOM Element object for the slime 
                 */
                function createSlime(slimeData) {

                }
              
            

There are many opportunities for code reuse across this project. One such place is for generating user profile pages. Thus, only write this code once. Write this code as a function that receives a username as a parameter so that it can be used for all profile pages. Then, have a small piece of JavaScript on each individual user profile page that calls this function with the appropriate username after the page has loaded.

To assist your code reuse, avoid the temptation of combining code to process and manipulate JSON data with code to produce and manipluate DOM nodes. This can be very tempting, but it reduces your ability to reuse code. Write some functions that fetch and process JSON to produce JavaScript objects. Write different functions that take an object and produce a DOM node. You might even consider writing separate functions that take DOM nodes and insert them at specific selectors on a page.

Be sure to ask lots of questions as you work on this project. Questions about the desired behavior are likely to receive more expressive answers than direct questions about the reference implementation (your clients won't have a reference impelmentation).

Because there will be a nontrivial amount of code for this project, make a separate folder to hold all of this code. Typically, this folder will be named js.

You may want to look back at the Project 1 specification for styling hints.

Working in Groups

In the industry, it is extremely rare to be working on your own. Therefore, it is important to learn how to work with others efficiently and effectively. You will not always be able to choose your colleagues, and thus, trying your best to work with others is a valuable skill to develop.

The following are some tips for working in groups:

  • Discuss and agree on a communication plan for your group. Will you use email, Teams, Canvas collaboration tools, Discord, Slack, etc.? Avoid mixing this with your informal communication channels. It's best to separate out work and friendship. Agree on the times when you all expect each other to be reachable. The precise plan does not matter, but make sure that everyone is comfortable with the plan.
  • Schedule more meetings than you think you will need. It is easier to cancel a meeting than it is to scramble to find additonal common times.
  • Once a communication plan is established, it is your responsibility to be an active participant in discussions.
  • Agree on a plan to share and collaborate on files. A private GitHub repository is a great option for this. OneDrive is slightly less ideal since one team member can overwrite the files of another, but could work in a pinch. VSCode Live Share is another option. Emailing files back and forth is inefficient, and you should avoid this.
  • Discuss a plan for tackling the project. Are you going to break up the work? Are you all going to work together on one screen?
  • Do the work you agreed to do. If you are having trouble, ask for help. Do not do others' work without explicitly discussing it. You are a team player, not a lone ranger.
  • If the tasks comes more naturally to you, help others in the group who are finding the work challenging. Don't do the work for them, but assist in their learning.
  • If the tasks are challenging, ask for help and brainstorming. Do not expect other group members to do your work for you.
  • Leave time before the due date to make sure your artifacts are internally consistent and work together.
  • If you are assigning individual tasks, take some time to figure out what the appropriate separation of work is. The most naive approach (e.g., breaking things down by page) is rarely a good idea (think about code reuse!)

What to Submit for P2

Be sure that you are submitting to the correct assignment on Gradescope! Further, be sure to make sure that you submit all required files. Don't wait until the last minute to submit (you can resubmit up to the deadline).

Submit the following:

  • *.html: all HTML files needed for your pages
  • *.js: all JavaScript files needed for your pages
  • *.css: any additional CSS files you may have needed.
  • All asset files used in your project (e.g., profile images, JSON)
  • An HTML or TXT file containing a list of citations for resources you used to complete this project. No specific convention is required, but this list should provide sufficient information to find a copy of each resource.

I will view your files by creating a small Python webserver as we have done in class:

              
                python3 -m http.server
              
            

Thus, make sure that your files are submitted with a folder structure identical to your development machine. As a hint, submit directly from GitHub or create a zip or tar archive of all the files. You will likely want to use relative URIs for assets.

Individual Report

Individually, submit a short (1-2 paragraph) report on your contributions to the project. You will submit this report to a separate Gradescope assignment. This should include:

  • A summary of what you contributed to the project (e.g., "I created the login page"). What do you "own" of the artifacts?
  • How you feel about your contributions. Did you do a similar amount of work to your peers? Was your work successful?
  • A reflection on the process of working in a group. What went well? What changes did you make from the last collaboration, and were these changes beneficial? Are there changes you might make for a future collaboration?

Grading Rubric

P2 Grading (out of 100 points):

  • 28 points: Webpage content
    • Each of the required pages is worth 4 points
    • To receive all five points per page, ensure that all content is generated for each page and that each page functions as expected.
  • 57 points: JavaScript Implementation
    • You will be graded on your proper use of JavaScript, including:
      • Use of the fetch API
      • Higher-order functions
      • Asynchronous programming (Promises, Callbacks, async/await)
      • Proper use of event handlers
    • You will receive more points for increased use of good coding habits. Such habits include:
      • Splitting out DOM manipulation from data manipulation
      • Reducing code reuse by placing common code in functions
      • Splitting JavaScript into several files to facilitate use across pages
      • Minimizing the number of global bindings (variables) created in your code
  • 5 points: Formatting of HTML and JavaScript
    • 5 — files are well-formatted (proper indentation, no extremely long lines, etc.)
    • 3 — files are generally well-written, but spacing is not uniform (e.g., large gaps, old commented code, etc.).
    • 1 — files are very difficult to follow and contain the bare minimum of formatting.
    • 0 — script contains no comments.
  • 5 points: References
    • 5 — Standalone references file exists and contains a list of resources used for this assignment. This includes course materials.
    • 2 — References file exists, but might not be separate, is the wrong format, or does not adequately identify resources used for this assignment.
    • 0 — No references file provided.
  • 5 points: Individual Report
    • 5 — Report is well written, addresses all required content, and has minimal spelling/grammar errors.
    • 3 — Report is generally well written, but fails to address one required topic.
    • 1 — Report could benefit from significant revisions or fails to address two or more topics.
    • 0 — No report provided.

Relevant API JSON Data

Below is a description of some of the API data provided in the assets for this project. Note that you will likely have to look through this data in more detail, but use this as a starting place for finding the right files.

As a side note, this JSON file structure is based very closely on the Twitter v1.1 API to give you a real sense of implementing a real-world application. Some aspects of the file layout have been modified to work better with this project.

Favorites

Lists of each user's favorited slimes are stored in /api/favorites/<username>.json. These are sorted in reverse order (with the newest first). Note that the associated slime IDs are also available through the User API for individual access through the Statuses API.

Users

Information about each user is provided in /api/user/get/<username>.json. These JSON files contain information about each user account on SlugFest.

Statuses

The statuses API provides information about status updates (aka slimes). There are several relevant pieces, ranging from timelines to individual slimes.

Timelines

Timelines (sorted lists of slimes) for each user are provided in /api/statuses/user_timeline/<username>.json.

The main timlines (the home feed page) is provided in /api/statues/home_timeline.json

Individual Slimes

Individual slimes are available in /api/statuses/show/<slime_id>.json. A slime ID is a unique string associated with each slime when it is posted.

It is also possible to see the slimes that are in reply to another slime. This information is stored in /api/statuses/replies/<slime_id>.json, where a slime ID is defined as above.

Slime Activity

Slime activity (aka notifications) are stored in /api/statuses/activity.json. To simplify coding, this will only show reslimes and replies (we are dropping favorites from notifications).

Acknowledgements

The initial concept for this project is borrowed from an assignment designed by Andrew DeOrio at the University of Michigan.

1By your professor